Embedded Jetty does not find Annotated Servlet

2019-07-16 11:22发布

问题:

Short: I have a project that provides a war artifact which includes a servlet with annotations but no web.xml. If i try to use the war in jetty i always get only the directory listing of the war content but not the servlet execution.

Any idea?

Long story: My servlets look like this

package swa;

import java.io.IOException;
import java.io.PrintWriter;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet( asyncSupported = false, urlPatterns={"/*"})
public class ServletX extends HttpServlet {

    private static final long serialVersionUID = 1L;

    public void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        // Set response content type
        response.setContentType("text/html");

        // Actual logic goes here.
        PrintWriter out = response.getWriter();
        out.println("<h1>Hi there..</h1>");
    }

}

So nothing special i guess. When i use mvn jetty:run everything is fine. After ensuring this the project is packed into a war-archive.

This war archive is used within another project that has to set up jetty within code. This is how its done:

        String jettyPort = properties.getProperty("jetty.port", "8080");
        Server server = new Server();

        ServerConnector httpConnector = new ServerConnector(server, new HttpConnectionFactory());
        httpConnector.setPort(Integer.parseInt(jettyPort));
        httpConnector.setAcceptQueueSize(2);
        httpConnector.setHost("0.0.0.0");
        httpConnector.setIdleTimeout(30000);
        server.setConnectors(new Connector[] { httpConnector });

        WebAppContext wacHandler = new WebAppContext();
        wacHandler.setContextPath("/admin");
        wacHandler.setWar("swa-0.0.1-SNAPSHOT.war");
        wacHandler.setConfigurationDiscovered(true);

        server.setHandler(wacHandler);

        server.start();

When executing this project the logs tell me that the war is found. But if i open the url http://localhost:8080/admin i only see the listing of the war content (instead of 'Hi there').

Can someone point me to my failure?

回答1:

You need to define the WebAppContext configurations appropriately (and in the correct order).

    wacHandler.setConfigurations(new Configuration[]
    { 
        new AnnotationConfiguration(), 
        new WebInfConfiguration(), 
        new WebXmlConfiguration(), 
        new MetaInfConfiguration(), 
        new FragmentConfiguration(),
        new EnvConfiguration(), 
        new PlusConfiguration(), 
        new JettyWebXmlConfiguration() 
    });

Don't forget to add the jetty-annotations.jar.

This is from the EmbedMe.java example for embedded-jetty use with Servlet 3.1 found at

https://github.com/jetty-project/embedded-servlet-3.1/



回答2:

In addition to adding the necessary configurations as stated in the abovementioned answer, one needs to force Jetty to scan the current project compiled classes, which Jetty ignores by default. To do that, just call the following on your WebAppContext:

context.setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern", ".*/classes/.*")

Please see the complete example here (in Kotlin): https://github.com/mvysny/vaadin-on-kotlin/blob/master/vok-example-crud/src/test/java/com/github/vok/example/crud/Server.kt

This works awesome and discovers all @WebServlets, @WebListeners and others.