Kohei Nozaki's blog 

Lean example of Tomcat 8 + Guice 4


Posted on Monday Aug 03, 2015 at 06:56PM in Technology


I prefer Java EE stack usually, but I need to learn a Tomcat based stack for some reasons these days. in this entry, I introduce you a very simple example of Tomcat 8 + Guice 4 app which uses GuiceFilter and GuiceServletContextListener so that bring Guice to a Servlet based web application.

The entire project which based on Maven can be obtained from My GitHub repository.

Dependencies

<dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <version>3.1.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>com.google.inject</groupId>
    <artifactId>guice</artifactId>
    <version>4.0</version>
</dependency>
<dependency>
    <groupId>com.google.inject.extensions</groupId>
    <artifactId>guice-servlet</artifactId>
    <version>4.0</version>
</dependency>

web.xml

<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
         version="3.1">

    <listener>
        <listener-class>guice.tomcat.MyGuiceServletConfig</listener-class>
    </listener>

    <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>

</web-app>

MyGuiceServletConfig.java

We need to declare servlet mappings and the mappings between interfaces and implementations here.

public class MyGuiceServletConfig extends GuiceServletContextListener {
    @Override
    protected Injector getInjector() {
        return Guice.createInjector(new ServletModule() {
            @Override
            protected void configureServlets() {
                serve("/*").with(MyServlet.class);
                bind(MyService.class).to(MyServiceImpl.class);
            }
        });
    }
}

Service class

We use a pair of a very simple implementation of a service class. it simply creates a greetings which uses an argument.

MyService.java

public interface MyService {
    String hello(String name);
}

MyServiceImpl.java

public class MyServiceImpl implements MyService {
    @Override
    public String hello(String name) {
        return "Hello, " + name;
    }
}

MyServlet.java

Note that we use @javax.inject.Singleton and @javax.inject.Inject annotations, that are standardized JSR API.

@javax.inject.Singleton
public class MyServlet extends HttpServlet {

    @javax.inject.Inject
    private MyService myService;

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        resp.getWriter().write(myService.hello("Guice"));
    }
}

Test run

After deployment, send a request to check the response:

$ curl http://localhost:8080
Hello, Guice

Other things/functions need to be studied

  • Transaction management

  • CDI Producer equivalent

  • AOP

  • Automatic implementation scanning/binding



Comments:

This is an excellent bare-bones example showing the base "root level" mapping which seems to work ok, but there is a quirky difference between web.xml's filter-mapping/url-pattern behavior and the GuiceServletContextListener's serve(urlPattern) behavior for non-root-level paths. The JEE pattern matches more actual urls. For example, if the url-pattern were "/someresource/*" it would match "/myresource/metadata" and "/myresource?param1=2" and even "/myresource" but serve("/myresource/*") won't match all of those, and serve("/myresource") won't either. You would need to serve() both patterns to get the same coverage.

Posted by Fred on April 21, 2020 at 09:52 AM JST #


Leave a Comment

HTML Syntax: NOT allowed