All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.opentable.server.EmbeddedReactiveJetty Maven / Gradle / Ivy

Go to download

Wiring for basic Jetty core servlet regardless of MVC or JaxRS choices. Also wires logging, metrics, etc

There is a newer version: 6.0.4
Show newest version
/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.opentable.server;

import java.time.Duration;
import java.util.Map;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.thread.ThreadPool;
import org.springframework.boot.web.embedded.jetty.JettyReactiveWebServerFactory;
import org.springframework.boot.web.embedded.jetty.JettyServerCustomizer;
import org.springframework.boot.web.embedded.jetty.JettyWebServer;
import org.springframework.boot.web.server.WebServer;
import org.springframework.boot.web.servlet.ServletContextInitializer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.core.env.PropertyResolver;
import org.springframework.http.server.reactive.HttpHandler;
import org.springframework.http.server.reactive.JettyHttpHandlerAdapter;

import com.opentable.logging.jetty.JsonRequestLogConfig;

/**
 * Configure an embedded {@code Jetty 9} HTTP(S) server for use with reactive spring, and tie it into the Spring Boot lifecycle.
 *
 * Spring Boot provides a very basic Jetty integration but it doesn't cover a lot of important use cases.
 * For example even something as trivial as configuring the worker pool size, socket options,
 * or HTTPS connector is totally unsupported.
 */
@Configuration
@Import(JsonRequestLogConfig.class)
public class EmbeddedReactiveJetty extends EmbeddedJettyBase {

    @Bean
    public JettyReactiveWebServerFactory webServerFactory(final JsonRequestLogConfig requestLogConfig,
                                                          final Map activeConnectors,
                                                          final PropertyResolver pr) {
        final JettyReactiveWebServerFactory factory = new OtJettyReactiveWebServerFactory();
        JettyReactiveWebServerFactoryAdapter factoryAdapter = new JettyReactiveWebServerFactoryAdapter(factory);
        this.configureFactoryContainer(requestLogConfig, activeConnectors, pr, factoryAdapter);
        return factoryAdapter.getFactory();

    }

    static class JettyReactiveWebServerFactoryAdapter implements WebServerFactoryAdapter {
        private final JettyReactiveWebServerFactory factory;

        JettyReactiveWebServerFactoryAdapter(JettyReactiveWebServerFactory factory) {
            this.factory = factory;
        }

        @Override
        public void setPort(int port) {
            factory.setPort(port);
        }

        @Override
        public void addServerCustomizers(JettyServerCustomizer... customizers) {
            factory.addServerCustomizers(customizers);
        }

        @Override
        public void setSessionTimeout(Duration duration) {
            // Currently Spring Boot 2.1.2 does not expose this property at this level. Possibly an oversight
            // Also it is questionable that anyone is actually using this feature
            // consider removing
            throw new UnsupportedOperationException("operation not supported by JettyReactiveWebServerFactory");
        }

        @Override
        public void setThreadPool(ThreadPool threadPool) {
            factory.setThreadPool(threadPool);
        }

        // TODO: Investigate if this is supported now
        @Override
        public void addInitializers(ServletContextInitializer... initializers) {
            // currently not supported by Spring Boot 2.1.2. Consider removing since we only
            // add two listeners health and metrics which have spring equivalents
            throw new UnsupportedOperationException("operation not supported by JettyReactiveWebServerFactory");
        }

        @Override
        public JettyReactiveWebServerFactory getFactory() {
            return factory;
        }
    }

    /*
    Declaring this as a static-inner class to prevent:
        org.springframework.beans.FatalBeanException: ReactiveWebServerFactory implementation com.opentable.server.EmbeddedReactiveJetty$1 cannot be instantiated.
        To allow a separate management port to be used, a top-level class or static inner class should be used instead
    */
    static class OtJettyReactiveWebServerFactory extends JettyReactiveWebServerFactory {
        @Override
        public WebServer getWebServer(HttpHandler httpHandler) {
            JettyHttpHandlerAdapter servlet = new JettyHttpHandlerAdapter(httpHandler);
            Server server = createJettyServer(servlet);
            return new JettyWebServer(server, true);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy