javatomcatguicejersey-1.0guice-servlet

Issue with Jersery1.x, Guice and Tomcat


I am developing a simple application using Jersey 1.x, Guice and trying to run on Tomcat.

I used Guice filter and Guice Listener along with Resources and Application.

Below is my web.xml :

<filter>
    <filter-name>guiceFilter</filter-name>
    <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
</filter>

<filter-mapping>
    <filter-name>guiceFilter</filter-name>
    <url-pattern>/*</url-pattern>
</filter-mapping>

<listener>
    <display-name>Guice Listener</display-name>
    <listener-class>com.simple.application.GuiceListener</listener-class>
</listener>

And using GuiceListener I injected all my dependencies,

public class GuiceListener extends GuiceServletContextListener {
    private Injector injector;

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        try {
            super.contextDestroyed(servletContextEvent);
        } finally {
            injector = null;
        }
    }

    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {
        injector = Guice.createInjector(new SimpleServlet());
        super.contextInitialized(servletContextEvent);
        injector.injectMembers(this);
    }

    @Override
    protected Injector getInjector() {
        return injector;
    }
}

And This is how my Servlet looks

public class SimpleServlet extends JerseyServletModule {
    @Override
    protected void configureServlets() {
        configureGuiceServlet();
    }

    private void configureGuiceServlet() {
        bind(SimpleResource.class).in(Scopes.SINGLETON);
        serve("/service/*").with(GuiceContainer.class);
        bind(Manager.class).to(ManagerImpl.class);
    }
}

And I created a resource with a GET method,

@Path("/stuff")
public class SimpleResource {
    private final ManagerImpl manager;

    @Inject
    public SimpleResource(final ManagerImpl manager) {
        this.manager = manager;
    }

    @GET
    @Path("{id}")
    @Produces(MediaType.TEXT_HTML)
    public String submitData(@PathParam("id") final String id) {
        String welcomeScreen = manager.getWelcomeScreen();
        return "This is" + welcomeScreen + id;
    }
}

I used Constructor Injection for injecting classes.

And this is how my application looks

public class SimpleApplication extends Application {
    @Override
    public Set<Class<?>> getClasses() {
        return ImmutableSet.<Class<?>>builder()
            .add(SimpleResource.class)
            .build();
    }
}

I am deploying this on Tomcat 7 and when I try to hit the application endpoint, I am getting 404,

http://localhost:9999/simple-0.0.1-SNAPSHOT/service/stuff/id

I can see in the logs that all the classes are instantiated successfully.

These are the dependencies in my pom.

    <dependency>
        <groupId>com.sun.jersey</groupId>
        <artifactId>jersey-server</artifactId>
        <version>1.18.6</version>
        <scope>compile</scope>
    </dependency>
    <dependency>
        <groupId>com.sun.jersey.contribs</groupId>
        <artifactId>jersey-guice</artifactId>
        <scope>compile</scope>
        <version>1.18.6</version>
    </dependency>
    <dependency>
        <groupId>com.google.inject.extensions</groupId>
        <artifactId>guice-servlet</artifactId>
        <scope>compile</scope>
        <version>3.0</version>
    </dependency>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>servlet-api</artifactId>
        <scope>provided</scope>
        <version>2.5</version>
    </dependency>
    <dependency>
        <groupId>com.google.guava</groupId>
        <artifactId>guava</artifactId>
        <scope>compile</scope>
        <version>14.0</version>
    </dependency>
</dependencies>

Is there anything that I am missing as far as Tomcat with guice?


Solution

  • You're using ServletModule. Use JerseyServletModule instead.

    public class SimpleServlet extends JerseyServletModule
    

    General Cleanup options:

    When I used Guice/Tomcat/Jersey 1.x I did it a bit differently. To promote flexibility you can take the path param off SimpleResource's path param and move it to the method. Also can add Singleton Annotation to the resource directly.

    @Singleton
    @Path("/stuff")
    public class SimpleResource {
        private final ManagerImpl manager;
    
        @Inject
        public SimpleResource(final ManagerImpl manager) {
            this.manager = manager;
        }
    
        @GET
        @Path("{id}")
        @Produces(MediaType.TEXT_HTML)
        public String submitData(@PathParam("id") final String id) {
            String welcomeScreen = manager.getWelcomeScreen();
            return "This is" + welcomeScreen + id;
        }
    }
    

    Remove SimpleApplication and in configureGuiceServlet remove reflection and options map and instead do:

    public class SimpleServlet extends JerseyServletModule{
    
        @Override
        protected void configureServlets() {
            configureGuiceServlet();
        }
    
        private void configureGuiceServlet() {
            serve("/service/*").with(GuiceContainer.class, new HashMap<String, String>());
            bind(Manager.class).to(ManagerImpl.class);
        }
    }