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

com.netflix.governator.guice.jetty.JettyModule Maven / Gradle / Ivy

There is a newer version: 1.17.13
Show newest version

package com.netflix.governator.guice.jetty;

import java.util.EnumSet;
import java.util.Set;

import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import javax.servlet.DispatcherType;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.ServerConnector;
import org.eclipse.jetty.servlet.DefaultServlet;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.inject.AbstractModule;
import com.google.inject.Provides;
import com.google.inject.ProvisionException;
import com.google.inject.multibindings.Multibinder;
import com.google.inject.servlet.GuiceFilter;
import com.netflix.governator.AbstractLifecycleListener;
import com.netflix.governator.LifecycleManager;
import com.netflix.governator.LifecycleShutdownSignal;
import com.netflix.governator.spi.LifecycleListener;

/**
 * Installing JettyModule will create a Jetty web server within the context
 * of the Injector and will use servlet and filter bindings from any additionally
 * installed ServletModule.
 * 
 * 
 * 
 * {@code
    public static void main(String args[]) throws Exception {
        Governator.createInjector(
                new SampleServletModule(), 
                new ShutdownHookModule(), 
                new JettyModule())
                .awaitTermination();
    }
 * }
 * 
 * To change Jetty's configuration provide an override binding for JettyConfig.class.
 * 
 * 
 * {@code 
    public static void main(String args[]) throws Exception {
        Governator.createInjector(
                new SampleServletModule(), 
                new ShutdownHookModule(), 
                Modules.override(new JettyModule())
                       .with(new AbstractModule() {
                           @Overrides
                           private void configure() {}
                           
                           @Provider
                           @Singleton 
                           private JettyConfig getConfig() {
                               DefaultJettyConfig config = new DefaultJettyConfig();
                               config.setPort(80);
                               return config;
                           }
                       })
                .awaitTermination());
    }
 * }
 * 
* * Note that only one Jetty server may be created in an Injector * * @author elandau * */ public final class JettyModule extends AbstractModule { private final static Logger LOG = LoggerFactory.getLogger(JettyModule.class); /** * Eager singleton to start the Jetty Server * * @author elandau */ @Singleton public static class JettyRunner { private final Server server; private final int port; @Inject public JettyRunner(Server server, final LifecycleManager manager) { this.server = server; LOG.info("Jetty server starting"); try { server.start(); port = ((ServerConnector)server.getConnectors()[0]).getLocalPort(); LOG.info("Jetty server on port {} started", port); } catch (Exception e) { try { server.stop(); } catch (Exception e2) { } throw new ProvisionException("Jetty server failed to start", e); } } public boolean isRunning() { return server.isRunning(); } public int getLocalPort() { return this.port; } } @Singleton static class OptionalJettyConfig { @com.google.inject.Inject(optional=true) private JettyConfig jettyConfig; public JettyConfig getJettyConfig() { return jettyConfig != null ? jettyConfig : new DefaultJettyConfig(); } } /** * LifecycleListener to stop Jetty Server. This will catch shutting down * Jetty when notified only through LifecycleManager#shutdown() and not via the * LifecycleEvent#shutdown(). * * @author elandau * */ @Singleton public static class JettyShutdown extends AbstractLifecycleListener { private Server server; @Inject public JettyShutdown(Server server) { this.server = server; } @Override public void onStopped(Throwable optionalError) { LOG.info("Jetty Server shutting down"); try { Thread t = new Thread(new Runnable() { @Override public void run() { try { server.stop(); LOG.info("Jetty Server shut down"); } catch (Exception e) { LOG.warn("Failed to shut down Jetty server", e); } } }); t.start(); } catch (Exception e) { LOG.warn("Error shutting down Jetty server"); } } } @Override protected void configure() { bind(JettyRunner.class).asEagerSingleton(); Multibinder.newSetBinder(binder(), LifecycleListener.class).addBinding().to(JettyShutdown.class); bind(LifecycleShutdownSignal.class).to(JettyLifecycleShutdownSignal.class); Multibinder.newSetBinder(binder(), JettyConnectorProvider.class); } @Provides @Singleton private Server getServer(OptionalJettyConfig optionalConfig, Set jettyConnectors) { JettyConfig config = optionalConfig.getJettyConfig(); Server server = new Server(config.getPort()); Resource staticResourceBase = Resource.newClassPathResource(config.getStaticResourceBase()); if (staticResourceBase != null) { // Set up a full web app since we have static content. We require the app to have its static content // under src/main/webapp and any other static resources that are packaged into jars are expected under // META-INF/resources. WebAppContext webAppContext = new WebAppContext(); // We want to fail fast if we don't have any root resources defined or we have other issues starting up. webAppContext.setThrowUnavailableOnStartupException(true); webAppContext.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class)); webAppContext.addServlet(DefaultServlet.class, "/"); webAppContext.setResourceBase(config.getWebAppResourceBase()); webAppContext.setContextPath(config.getWebAppContextPath()); webAppContext.setAttribute(WebInfConfiguration.CONTAINER_JAR_PATTERN, ".*\\.jar$"); webAppContext.setConfigurations(new Configuration[]{ new WebXmlConfiguration(), new WebInfConfiguration(), new MetaInfConfiguration(), new FragmentConfiguration(), }); server.setHandler(webAppContext); } else { // We don't have static content so just set up servlets. ServletContextHandler servletContextHandler = new ServletContextHandler(server, config.getWebAppContextPath(), ServletContextHandler.SESSIONS); servletContextHandler.addFilter(GuiceFilter.class, "/*", EnumSet.allOf(DispatcherType.class)); servletContextHandler.addServlet(DefaultServlet.class, "/"); servletContextHandler.setResourceBase(config.getWebAppResourceBase()); } if (jettyConnectors != null) { for (JettyConnectorProvider connectorProvider : jettyConnectors) { server.addConnector(connectorProvider.getConnector(server)); } } return server; } @Provides @Singleton @Named("embeddedJettyPort") public Integer jettyPort(JettyRunner runner) { return runner.getLocalPort(); } @Override public boolean equals(Object obj) { return JettyModule.class.equals(obj.getClass()); } @Override public int hashCode() { return JettyModule.class.hashCode(); } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy