Can't get Jetty to scan for annotated classes

Viewed 14096

I have an application with an embedded jetty server which I'm starting up like this (placed in main() and launched with eclipse):

Server server = new Server(port);

WebAppContext context = new WebAppContext();
context.setResourceBase("web/");
context.setDescriptor("web/WEB-INF/web.xml");
context.setConfigurations(new Configuration[]{
            new AnnotationConfiguration(), new WebXmlConfiguration(),
            new WebInfConfiguration(), new TagLibConfiguration(),
            new PlusConfiguration(), new MetaInfConfiguration(),
            new FragmentConfiguration(), new EnvConfiguration()});

context.setContextPath("/");
context.setParentLoaderPriority(true);
server.setHandler(context);
server.start();
server.join();

My web.xml looks like this (empty for now, I'm not sure if I can remove it completely):

<web-app 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns="http://java.sun.com/xml/ns/javaee" 
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
    metadata-complete="false"
    version="3.0">
</web-app>

And I have a simple class set up like this:

import java.io.IOException;

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(urlPatterns={"/test"})
public class TestServlet extends HttpServlet {

    protected void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException  {
        request.getRequestDispatcher("/WEB-INF/html/index.html").forward(request,response);
    }
}

My application works fine when I use traditional servlet mappings in web.xml. But when I remove the web.xml mappings and use annotations, I only get 404s. It doesn't look like it's scanning for annotations at all. The console looks like this:

2012-08-01 17:40:37.021:INFO:oejs.Server:jetty-8.1.5.v20120716
2012-08-01 17:40:37.227:INFO:oejpw.PlusConfiguration:No Transaction manager found - if your webapp requires one, please configure one.
2012-08-01 17:40:37.294:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.547:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.547:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.547:INFO:oejsh.ContextHandler:started o.e.j.w.WebAppContext{/,file:/Users/me/project/web/}
2012-08-01 17:40:37.641:INFO:oejs.AbstractConnector:Started SelectChannelConnector@0.0.0.0:8080

Some things that I have checked already from my research:

  • servlet-3.0 jar is in the classpath
  • metadata-complete set to false in web.xml
  • I made sure to include AnnotationConfiguration in web app context

I've run out of ideas and am about to just revert back to the old web.xml, but it's killing me why I can't get this to work.

7 Answers

You can

  1. provide EmptyResource.INSTANCE if you do not need static resources

  2. add AnnotationConfiguration and override scanForAnnotations method, adding classpath resource to WebAppContext Metadata, possibly with path to root package for a scan

    WebAppContext webapp = new WebAppContext();
        webapp.setContextPath("/");
        webapp.setBaseResource(EmptyResource.INSTANCE);
        webapp.setConfigurations(new Configuration[]{
                new AnnotationConfiguration(){
                    @Override
                    protected void scanForAnnotations(WebAppContext context) throws Exception {
                        Resource classPathResource =    Resource.newResource(EmbeddedServerApp.class.getResource("/my/learn/jetty/servlet").toURI());
                        context.getMetaData().addContainerResource(classPathResource);
                        super.scanForAnnotations(context);
                    }
                },
        });
        server.setHandler(webapp);
        server.start();
    
Related