Easing JPA application developement by Using Google-Guice
Posted on October 15, 2007 by prashant
Filed Under Applications, Programming, Technology.
Persistence Support in Dekoh
At the core of Dekoh is a Servlet (2.4) Container on which any Java web applications can be deployed. Persistence support for Dekoh applications is achieved by using a JPA provider - Toplink Essentials (Part of Glassfish). Each Dekoh desktop installation includes Toplink-Essentials and a Derby database. Dekoh Applications developers can use Java Persistence API to specify the OR mapping of the application data.
An important interface between JPA application developers and the JPA provider software is the javax.persistence.EntityManager. The EntityManager is used to create new persistent entities representing application data, and to query for already persisted entities.
A Java EE Container, would manage the life cycle of the EntityManager instances and inject these managed instances into EJB Session/Entity beans. However since, Dekoh application use EntityManager in Java SE mode, applications have to manage the life cycle of EntityManager instance. Dekoh applications will also have to manage local transactions wherever required.
Guice and its extension warp-persist come to the rescue. Guice is a lightweight dependency injection framework and warp-persist is an extension of Guice which provides a way to have EntityManager injected. The instances into which EntityManager needs to be injected are managed by Guice.
Let me explain how to use these two packages with the help of a sample Blog Reader application which bookmarks links to interesting blogs.
Using Guice in a Dekoh application
Before going over how to configure Guice, warp-persist, lets look at the JPA Entity class the sample application will be using. A JPA Entity is a Java Bean whose state is OR mapped to a Database.
@Entity
@NamedQueries({
@NamedQuery(name = Blog.LIST_ALL_QUERY, query = "SELECT o FROM Blog o"),
@NamedQuery(name = Blog.BY_SUBJECT, query = "SELECT o FROM Blog o WHERE o.subject=:subject")
})
public class Blog
{
public static final String BY_SUBJECT = "sample.Blog.findBySubject";
public static final String LIST_ALL_QUERY = "sample.Blog.listAll";
private Long id; //get and set method omitted for brevity
private String subject; //Subject of the blog entry being bookmarked
private String link; //Link to the actual blog entry
public Blog(String subject, String text)
{
this.subject = subject;
this.link = text;
}
}
As you can see, Blog is a simple JPA entity with two persistent fields - subject and link. Our sample web application will let users create many bookmarks to blog entries and then list the bookmarks. Each bookmarked blog entry is an instance of the Blog entity.
The persistence.xml for this application :
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="blog-persistence-unit" transaction-type="RESOURCE_LOCAL">
<provider>oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider</provider>
<class>sample.Blog</class>
<properties/> <!--DB, connection and driver details -->
</persistence>
Note that the transaction-type is chosen to be RESOURCE_LOCAL. This means that instead of using JTA to manage the transactions, we will be using the local transaction support provided by the EntityManager.
In this Blog Reader application, we will be creating a new instance of EntityManager for every HTTP request. warp-persist allows applications to configure the scope of each EntityManager instance created. To do this we need to configure a Filter to intercept all HTTP requests.
<filter>
<filter-name>sessionPerRequestFilter</filter-name>
<filter-class>com.wideplay.warp.jpa.SessionPerRequestFilter</filter-class>
</filter>
With this filter setup, warp-persist will create one instance of EntityManager for each HTTP request. Each created instance is also closed when response is committed. A resource local transaction is used within this scope when required.
But before warp-persist can create an instance of EntityManager for you, it needs to be told of the persistence-unit of your application. To do this bootstrapping we will use a ServletContextListener. A persistence-unit is defined in JPA’s deployment descriptor - persistence.xml and contains details on how to connect to Database, and qualified class names of the entity classes.
public class BlogAppContextListener implements ServletContextListener
{
private static Injector injector;
public void contextInitialized(ServletContextEvent servletContextEvent)
{
//Based on code examples in the the Warp-persist guide
injector = Guice.createInjector(new BlogModule(), PersistenceService
.usingJpa()
.across(UnitOfWork.REQUEST)
.addAccessor(BlogAccessor.class)
.transactedWith(TransactionStrategy.LOCAL)
.buildModule());
}
public static <T> T getInstance(java.lang.Class<T> aClass) { //gets injected instances
assert injector!=null : "contextInitialized is expected to be called before invoking this method";
return injector.getInstance(aClass);
}
public void contextDestroyed(ServletContextEvent servletContextEvent)
{
//stop persistence service here..
}
}
Creating and Finding Blog Entities
Lets look at the code to create and persist Blog entities.
public class CreateBlog
{
@Inject
Provider<EntityManager> em;
@Transactional
public Blog createBlog(String subject, String link)
{
Blog blog = new Blog(subject, link);
em.get().persist(blog);
return blog;
}
}
This class uses wrap-persist annotations to inject the EntityManager. Also notice that the method createBlog simply uses Transactional annotation to let warp-persist start a local transaction at the beginning of the method, and the same transaction is committed before the method returns. Without using the @Transaction annotation, this method would have to manage the local transaction by itself. So this boilerplate code is avoided.
Since this class needs EntityManager injected, and since we need warp-persist to intercept method calls to createBlog, instances of this class will be managed by Guice framework. To get an instance of CreateBlog we will use the following snippet of the code :
Blog blog = BlogAppContextListener.getInstance(CreateBlog.class).createBlog(subject, link);
Remember that the BlogAppContextListener is the ServletContextListener which holds the configured injector instance.
Finding instances of Blog Entities
The Blog entity uses JPA’s @NamedQuery annotation to define Queries using JPA Query Language. We can use EntityManager instance to create instances of these queries. This is what the BlogAccessorWithJPAQueries shown below does. Again this class needs EntityManager injected, so its instances are managed by Guice.
public class BlogAccessorWithJPAQueries {
@Inject
Provider<EntityManager> em;
@SuppressWarnings("unchecked")
public List<Blog> getAllBlogs() {
EntityManager entityManager = em.get();
Query listAllBlogs = entityManager.createNamedQuery(Blog.LIST_ALL_QUERY);
return (List<Blog>) listAllBlogs.getResultList();
//For a more interesting note that covers various approaches to cast the result list see :
//http://www.javaspecialists.co.za/archive/newsletter.do?issue=133&locale=en_US
}
@SuppressWarnings("unchecked")
public List<Blog> getBlogBySubject(String name) {
EntityManager entityManager = em.get();
Query listAllBlogs = entityManager.createNamedQuery(Blog.BY_SUBJECT).setParameter("subject",name);
return (List<Blog>) listAllBlogs.getResultList();
}
}
Finding instances of Blog Entities made easy with Dynamic Finders
A very innovative feature of warp-persist is the @Finder annotation. Any defined JPA NamedQuery can be supplied to Finder annotation and warp-persist will take care the code to create instance of javax.persistence.Query, set the required dynamic parameters on the Query, and finally execute the Query to return the ResultList.
Lets look at a version of BlogAccessor class which uses the @Finder annotation provided by warp-persist, and accomplishes the task of finding Blog instances with lesser amount of code.
public interface BlogAccessor
{
@Finder(namedQuery = Blog.LIST_ALL_QUERY)
List<Blog> getAllBlogs();
@Finder(namedQuery = Blog.BY_SUBJECT)
List<Blog> getBlogsBySubject(@Named("subject")String name, @MaxResults int pageSize, @FirstResult int firstResultIndx);
@Finder(namedQuery = Blog.LIST_ALL_QUERY)
List<Blog> getBlogPage(@MaxResults int pageSize, @FirstResult int firstResultIndx);
}
First thing to notice is that the BlogAccessor is now an interface. The finder methods getAllBlogs are backed by NamedQueries already defined in the Blog entity. The implementation of this accessor object is supplied by warp-persist package. Instances of BlogAccessor class can be obtained by asking the Guice’s injector instance. Notice that when the injector was being configured in the BlogApplicaitonContextListener, we needed to add the accessor class.
The dynamic parameters that need to be inserted into the javax.persistence.Query can be specified by using the method parameter name. In the JPA Query SELECT o FROM Blog o WHERE o.subject=:subject the dynamic parameter that needs to be supplied is subject.
List<Blog> getBlogsByName(@Named("subject")String name, @MaxResults int pageSize, @FirstResult int firstResultIndx);
So the value passed in method parameter name, is set as the value of query parameter subject.
Using the finder annotation supplied by warp-persist package, JPA applications eliminate lot of similar looking code which creates instance of javax.persistence.Query objects, sets the required parameters and then obtains the result list.
Pagination of the result list of any NamedQuery is also trivial to achieve using the annotations provided by warp-persist package.
@Finder(namedQuery = Blog.LIST_ALL_QUERY)
List<Blog> getAllEntityAByPage(@MaxResults int pageSize, @FirstResult int firstResultIndx);
By supplying the values for method parameter annotated @MaxResults the number entity instances returned in the result list are controlled. The method parameter annotated @FirstResult is used to walk to the next page of results.
The index.jsp page in the application gets the instance of the BlogAccessor and displays the bookmarked blogs.

So in this blog entry we have seen how to use Guice and warp-persist package to write a JPA based web application; which can be deployed on Dekoh. We have also seen how employing these two packages will eliminate a lot of boilerplate code when coding JPA applications that will be deployed in a Java SE environment like a Dekoh Servlet Container.
Download source code of the sample
- Blog reader sample WAR file to be deployed on Dekoh.
- Blog reader sample application source code and project files
Comments
3 Responses to “Easing JPA application developement by Using Google-Guice”
Leave a Comment













Doesn’t work. When I deploy the war on tomcat, I get the error “SEVERE: Context [/blogreader] startup failed due to previous errors”.
Hi pablo,
The sample application assumes that the JPA (java persistence api) engine and derby are available on the server. Tomcat does NOT have these by default so you could try adding these libraries in the WEB-INF\lib of the application.
Instead, you could try running the application on Dekoh. The sample works out-of-the-box on Dekoh, because Dekoh Server ships the JPA Engine, Derby DB, RSS publish/subscribe library, UI widgets and much more. Despite all these additional features you will find Dekoh download smaller.
To try this sample on Dekoh, you need to:
1. Install Dekoh
a. Sign-up with Dekoh for free
b. You will notice and install link after signing up, click on it to install the platform. Or you could use an offline installer.
2. Deploy the application using one of the options:
a. Download the war and place it under ${install.root}\server\downloads and restart dekoh desktop. (Click on the shutdown button on right most corner of the desktop portal main page, after that you will be redirected to shutdown page. In the shutdown page you can restart the Dekoh desktop, using the link provided.
b. If you plan to develop and deploy more apps, you may be interested in installing devtool. This eases the deployment process and the applications can be deployed onto the Dekoh Desktop on single button click. Devtool can be installed from the list of available applications tab in dekoh desktop.
c. You could also use the shell to deploy the application.
Thanks,
Amar.
Thanks.