io.github.factoryfx.jetty.JettyServerFactory Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of jettyFactory Show documentation
Show all versions of jettyFactory Show documentation
factoryfx dependency injection framework
package io.github.factoryfx.jetty;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.RequestLog;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.eclipse.jetty.util.thread.ThreadPool;
import com.fasterxml.jackson.annotation.JsonIgnore;
import io.github.factoryfx.factory.FactoryBase;
import io.github.factoryfx.factory.attribute.dependency.FactoryAttribute;
import io.github.factoryfx.factory.attribute.dependency.FactoryListAttribute;
import io.github.factoryfx.factory.attribute.dependency.FactoryPolymorphicAttribute;
/**
* usage example.
*
* {@code
* public class SimpleHttpServer extends SimpleFactoryBase {
*
* public final FactoryAttribute> server = new FactoryAttribute<>(JettyServerFactory.class);
*
* {@literal @}Override
* protected Server createImpl() {
* return server.instance();
* }
* }
*
* builder.addFactory(JettyServerFactory.class, Scope.SINGLETON, ctx-> new JettyServerBuilder<>(new JettyServerFactory())
* .withHost("localhost").withPort(8005)
* .withResource(ctx.get(CustomResourceFactory.class)).build());
*
* }
*/
public class JettyServerFactory> extends FactoryBase {
private static final Logger jerseyLogger1 = Logger.getLogger(org.glassfish.jersey.internal.inject.Providers.class.getName());
private static final Logger jerseyLogger2 = Logger.getLogger(org.glassfish.jersey.internal.Errors.class.getName());
static {
jerseyLogger1.setLevel(Level.SEVERE); //another useless warning https://github.com/jersey/jersey/issues/3700
jerseyLogger2.setLevel(Level.SEVERE);//warning about generic parameters, works fine and no fix available so the warnings are just useless
}
public final FactoryListAttribute> connectors = new FactoryListAttribute>().labelText("Connectors").userNotSelectable();
public final FactoryAttribute> handler = new FactoryAttribute>().labelText("Handler collection");
public final FactoryPolymorphicAttribute threadPool = new FactoryPolymorphicAttribute().labelText("Thread Pool").nullable();
public final FactoryPolymorphicAttribute requestLog = new FactoryPolymorphicAttribute().labelText("RequestLog").nullable();
public JettyServerFactory(){
configLifeCycle().setCreator(this::createJetty);
configLifeCycle().setUpdater(this::update);
configLifeCycle().setStarter(this::start);
configLifeCycle().setDestroyer(this::stop);
config().setDisplayTextProvider(() -> "Jetty http server");
}
//api for customizing JettyServer creation
protected Server createJetty() {
Server server;
if (threadPool.get()==null){
server = new Server();
} else {
server = new Server(threadPool.instance());
}
connectors.instances().forEach(httpServerConnector -> httpServerConnector.addToServer(server));
handler.instance().setServer(server);
server.setHandler(handler.instance());
server.setRequestLog(requestLog.instance());
return server;
}
@SuppressWarnings("unchecked")
private void update(Server server){
for (Connector connector : server.getConnectors()) {
server.removeConnector(connector);
}
for (HttpServerConnector connector : connectors.instances()) {
connector.addToServer(server);
}
if (server.getThreadPool() instanceof QueuedThreadPool && threadPool.get() instanceof ThreadPoolFactory){
((QueuedThreadPool) server.getThreadPool()).setMaxThreads(((ThreadPoolFactory)threadPool.get()).poolSize.get());
}
}
/**
* model navigation shortcut, only works with th e default setup form the builder
* @param clazz resource clazz
* @param resource factory
* @return resource
*/
public final > RF getResource(Class clazz){
return getDefaultJerseyServlet().resources.get(clazz);
}
/**
* model navigation shortcut, only works with th e default setup form the builder
* @param resource resource
*/
public final void setResource(FactoryBase,R> resource){
JerseyServletFactory jerseyServletFactory = getDefaultJerseyServlet();
jerseyServletFactory.resources.removeIf(factoryBase -> factoryBase.getClass()==resource.getClass());
jerseyServletFactory.resources.add(resource);
}
/**
* model navigation shortcut, only works with th e default setup form the builder
* @param clazz servlet class
* @param servlet factory
* @return servlet
*/
@SuppressWarnings("unchecked")
public final > F getServlet(Class clazz){
ServletContextHandlerFactory servletContextHandler = getDefaultServletContextHandlerFactory();
for (ServletAndPathFactory servletAndPath : servletContextHandler.updatableRootServlet.get().servletAndPaths) {
if (servletAndPath.servlet.get().getClass()==clazz){
return (F)servletAndPath.servlet.get();
}
}
return null;
}
@SuppressWarnings("unchecked")
public final > F getServletUnsafe(Class> clazz){
return getServlet((Class)clazz);
}
public final > void clearResource(Class resource){
getDefaultJerseyServlet().resources.removeIf(factoryBase -> factoryBase.getClass()==resource);
}
@SuppressWarnings("unchecked")
private JerseyServletFactory getDefaultJerseyServlet() {
ServletContextHandlerFactory servletContextHandler = getDefaultServletContextHandlerFactory();
ServletAndPathFactory servletAndPathFactory = servletContextHandler.updatableRootServlet.get().servletAndPaths.get(0);
return (JerseyServletFactory) servletAndPathFactory.servlet.get();
}
@SuppressWarnings("unchecked")
@JsonIgnore
public ServletContextHandlerFactory getDefaultServletContextHandlerFactory() {
return (ServletContextHandlerFactory)((handler.get().handlers.get(GzipHandlerFactory.class)).handler.get());
}
public void start(Server server) throws Error {
try {
server.start();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
public void stop(Server server) {
try {
if (Thread.interrupted())
throw new RuntimeException("Interrupted");
//server.setStopTimeout(1L);
server.stop();
//because stop call can be inside this one of jetty's threads, we need to clear the interrupt
//to let the rest of the factory updates run. They might be interrupt-sensitive
Thread.interrupted();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}