the addition of handlers to a running server is a common pattern but the documentation is not clear at all (all the examples in the "embedding jetty" tutorial start the server after the configuration.) AFAIK people is following these approaches:
1) using the HandlerCollection(boolean mutableWhenRunning) ctor to add/remove handlers
2) add and start the handlers explicitly
I observed that #2 was not needed in Jetty 9.1.4, but it is on Jetty 9.2.14 and afterward (BTW these version numbers were picked by Maven as Jersey dependencies which is totally unrelated to this issue.) For example:
// after server creation ...
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
jettyServer.setHandler(contextHandlerCollection);
jettyServer.start();
// ...
ServletContextHandler newSCH= new ServletContextHandler(ServletContextHandler.SESSIONS);
newSCH.setResourceBase(System.getProperty("java.io.tmpdir"));
newSCH.setContextPath("/servlets");
ServletHolder newHolder = new SwServletHolder(servlet);
newSCH.addServlet(newHolder, "/*");
contextHandlerCollection.addHandler(newSCH);
try {
newSCH.start(); // needed from about 9.2
} catch (Exception e) {
logger.info("Exception starting ServletContextHandler for Jetty", e);
}
In order to add a SOAP context this is a code that "used to work" on 9.1.4 (on 9.2.14 it reports 404):
import java.lang.reflect.Method;
import java.net.InetSocketAddress;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
import org.eclipse.jetty.http.spi.JettyHttpServerProvider;
import org.eclipse.jetty.http.spi.HttpSpiContextHandler;
import org.eclipse.jetty.http.spi.JettyHttpContext;
import org.eclipse.jetty.http.spi.JettyHttpServer;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.handler.ContextHandlerCollection;
import com.sun.net.httpserver.HttpContext;
public class JettyJaxWs {
public static void main(String[] args) throws Exception {
Server server = new Server(7777);
ContextHandlerCollection contextHandlerCollection = new ContextHandlerCollection();
server.setHandler(contextHandlerCollection);
server.start();
HttpContext context = buildOrig(server, "/ws");
MyWebService ws = new MyWebService();
Endpoint endpoint = Endpoint.create(ws);
endpoint.publish(context);
// access wsdl on http://localhost:7777/ws/MyWebService?wsdl
}
@WebService
public static class MyWebService {
public String hello(String s) {
return "hi " + s;
}
}
public static HttpContext buildOrig(Server server, String contextString) throws Exception {
JettyHttpServerProvider.setServer(server);
return new JettyHttpServerProvider().createHttpServer(new InetSocketAddress(7777), 5).createContext(contextString);
}
Later, I had to do this for the last method (not sure if there is a better way):
public static HttpContext buildNew(Server server, String contextString) {
JettyHttpServer jettyHttpServer = new JettyHttpServer(server, true);
JettyHttpContext ctx = (JettyHttpContext) jettyHttpServer.createContext(contextString);
try {
Method method = JettyHttpContext.class.getDeclaredMethod("getJettyContextHandler");
method.setAccessible(true);
HttpSpiContextHandler contextHandler = (HttpSpiContextHandler) method.invoke(ctx);
contextHandler.start();
} catch (Exception e) {
e.printStackTrace();
}
return ctx;
}