Is there any way to add handlers to a running embedded Jetty instance? We have migrated an old Jetty 6 based project to Jetty 9 and we need for our plugin system the possibility add and remove dynamically handlers...
See the example below...
Server server = new Server();
[...]
server.start();
[...]
Handler[] existingHandler = server.getHandlers();
// There is no more
server.addHandler(newHandler);
// only this you can do, but only if the server is stopped
server.setHandler(newHandler)
Note: newHandler
is a HandlerCollection
...
With Jetty 9.1.0.v20131115 you can use the mutableWhenRunning
flag on HandlerCollection
constructor ...
HandlerCollection coll = new HandlerCollection(true);
This will ignore the isStarted()
tests on the collection itself during .setHandlers(Handlers[])
and .addHandler(Handler)
calls.
This behavior is only available for the HandlerCollection
itself, you can add individual handlers, or set the entire handler tree without regards to the LifeCycle
of the HandlerCollection
.
Eg:
Server server = new Server(8080);
HandlerCollection myhandlers = new HandlerCollection(true);
server.setHandler(myhandlers);
// add some initial handlers
myhandlers.setHandlers(new Handlers[] { helloHandler, indexHandler });
// start server
server.start();
// ... at some point later, during runtime
FooHandler fooHandler = new FooHandler();
fooHandler.start();
myhandlers.addHandler(fooHandler);
BarHandler barHandler = new BarHandler();
barHandler.start();
myhandlers.addHandler(barHandler);
Here a complete code sample. Next to using HandlerCollection(true)
, it is also important to start the new context handler explicitly.
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.Request;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.AbstractHandler;
import org.eclipse.jetty.server.handler.ContextHandler;
import org.eclipse.jetty.server.handler.HandlerCollection;
public class DynamicContextHandlers {
public static void main(String[] args) throws Exception {
new DynamicContextHandlers().run();
}
public void run() throws Exception {
int port = 8080;
Server server = new Server(port);
ContextHandler contextHandler = new ContextHandler();
contextHandler.setContextPath("/hello");
contextHandler.setResourceBase(".");
contextHandler.setClassLoader(Thread.currentThread().getContextClassLoader());
contextHandler.setHandler(new HelloHandler(""));
HandlerCollection contextHandlerCollection = new HandlerCollection(true); // important! use parameter
// mutableWhenRunning==true
// add context handler before starting server (started implicitly)
contextHandlerCollection.addHandler(contextHandler);
server.setHandler(contextHandlerCollection);
server.start();
System.out.println("Server started at port " + port + " with context handler for /hello");
System.out.println("Press enter to add context handler for /hello2");
System.in.read();
ContextHandler contextHandler2 = new ContextHandler();
contextHandler2.setContextPath("/hello2");
contextHandler2.setResourceBase(".");
contextHandler2.setClassLoader(Thread.currentThread().getContextClassLoader());
contextHandler2.setHandler(new HelloHandler("2"));
// add handler after starting server.
contextHandlerCollection.addHandler(contextHandler2);
// important! start context explicitly.
contextHandler2.start();
System.out.println("Press enter to exit.");
System.in.read();
server.stop();
}
public class HelloHandler extends AbstractHandler {
String string;
public HelloHandler(String string) {
this.string = string;
}
public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response)
throws IOException, ServletException {
response.setContentType("text/html;charset=utf-8");
response.setStatus(HttpServletResponse.SC_OK);
baseRequest.setHandled(true);
response.getWriter().println("<h1>Hello World" + string + "</h1>");
}
}
}