Kohei Nozaki's blog 

Entries tagged [guice]

Lean example of Tomcat 8 + Guice 4 + EclipseLink 2.6.0


Posted on Tuesday Aug 04, 2015 at 07:26PM in Technology


I wrote a Lean example of Tomcat 8 + Guice 4 in previous entry. this time, I’ll try JPA(EclipseLink) integration with automatic transaction management.

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

Prerequisites

For database connection, we’ll use a DataSource which is defined on Tomcat server. to define a Embedded Derby DataSource, This entry would help.

Dependencies

<dependencies>
    <dependency>
        <groupId>javax.servlet</groupId>
        <artifactId>javax.servlet-api</artifactId>
        <version>3.1.0</version>
        <scope>provided</scope>
    </dependency>
    <dependency>
        <groupId>org.eclipse.persistence</groupId>
        <artifactId>eclipselink</artifactId>
        <version>2.6.0</version>
    </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>
    <dependency>
        <groupId>com.google.inject.extensions</groupId>
        <artifactId>guice-persist</artifactId>
        <version>4.0</version>
    </dependency>
</dependencies>

web.xml

No changes against previous entry except addition of resource-ref element.

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

    <!-- taken from https://github.com/google/guice/wiki/Servlets -->

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

    <resource-ref>
        <res-ref-name>jdbc/derby</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
    </resource-ref>

</web-app>

META-INF/persistence.xml

If you don’t want to use a DataSource on Tomcat, specify the connection information in javax.persistence.jdbc.* properties instead of non-jta-data-source.

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
    <persistence-unit name="myJpaUnit" transaction-type="RESOURCE_LOCAL">
        <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <non-jta-data-source>java:comp/env/jdbc/derby</non-jta-data-source>
        <class>guice.tomcat.MyEntity</class>
        <properties>
            <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
            <property name="eclipselink.logging.level" value="FINE"/>
            <property name="eclipselink.logging.level.sql" value="FINE"/>
        </properties>
    </persistence-unit>
</persistence>

MyGuiceServletConfig.java

The last two statements will take care of JPA integration.

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

                install(new JpaPersistModule("myJpaUnit"));
                filter("/*").through(PersistFilter.class);
            }
        });
    }
}

MyEntity.java

This is a very simple JPA entity which keeps only generated id and ts (a timestamp).

@Entity
@NamedQuery(name = "MyEntity.findAll", query = "SELECT e FROM MyEntity e ORDER BY e.id DESC")
public class MyEntity implements Serializable {

    @Id
    @GeneratedValue
    private Long id;
    @Column(nullable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date ts;

... accessors are omitted

Service class

MyService.java

public interface MyService {
    void save(MyEntity e);
    List<MyEntity> findAll();
}

MyServiceImpl.java

Note that you need to annotate a method with @com.google.inject.persist.Transactional if you need a transaction on it.

public class MyServiceImpl implements MyService {

    // Transactions doesn't start if EntityManager is directly injected via @Inject.
    // I have no idea why...

    // According to https://github.com/google/guice/wiki/JPA,
    // "Note that if you make MyService a @Singleton, then you should inject Provider<EntityManager> instead."
    @Inject
    private Provider<EntityManager> emp;

    @Override
    // @javax.transaction.Transactional is not supported yet. https://github.com/google/guice/issues/797
    @com.google.inject.persist.Transactional
    public void save(MyEntity e) {
        EntityManager em = emp.get();
        em.persist(e);
    }

    @Override
    public List<MyEntity> findAll() {
        return emp.get().createNamedQuery("MyEntity.findAll", MyEntity.class).getResultList();
    }
}

MyServlet.java

This servlet saves a MyEntity with current timestamp, then fetches all of rows and returns them to the client on every request.

@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 {
        MyEntity myEntity = new MyEntity();
        myEntity.setTs(new Date());
        myService.save(myEntity);

        PrintWriter writer = resp.getWriter();
        writer.write("<html><body><ul>");
        for(MyEntity e : myService.findAll()){
            writer.write("<li>");
            writer.write(e.toString());
            writer.write("</li>");
        }
        writer.write("</ul></body></html>");

    }
}

Test run

A row will be saved on every request as follows:

4d678c4b c55c 41e0 ba5d 65d2832409fb


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