Google Guice

Exclusive offer: get 50% off this eBook here
Learning Google Guice

Learning Google Guice — Save 50%

Utilize dependency injection to develop applications quickly and efficiently using Google Guice with this book and ebook

$17.99    $9.00
by Hussain Pithawala | September 2013 | Open Source Web Development

In this article by Hussain Pithawala, author of the book Learning Google Guice we will develop a web application in Java using servlets and JSPs, and will see how Guice makes it simple to wire dependencies and helps to achieve separation of concerns easily. It even provides a programmatic approach to confi gure routing to servlets and JSPs while avoiding declarative approach in web.xml. As part of our learning we will fit flight search functionality in a web application. It is assumed that the reader is familiar with JSP, servlet development, and knows how to deploy a WAR file to a web container. Use of Tomcat to deploy the examples is suggested. We also need an extension of Guice for web development, guice-servlet-3.0. As usual, the dependency for this has been declared in pom.xml and once packaged it would be available in WAR (web application archive) also.

(For more resources related to this topic, see here.)

Structure of flightsweb application

Our application has two servlets: IndexServlet, which is a trivial example of forwarding any request, mapped with "/" to index.jsp and FlightServlet, which processes the request using the functionality we developed in the previous section and forwards the response to response.jsp. Here in, we simply declare the FlightEngine and SearchRequest as the class attributes and annotate them with @Inject. FlightSearchFilter is a filter with the only responsibility of validating the request parameters. Index.jsp is the landing page of this application and presents the user with a form to search the flights, and response.jsp is the results page.

The flight search form will look as shown in the following screenshot:

The search page would subsequently lead to the following result page.

In order to build the application, we need to execute the following command in the directory, where the pom.xml file for the project resides:

shell> mvn clean package

The project for this article being a web application project compiles and assembles a WAR file, flightsweb.war in the target directory. We could deploy this file to TOMCAT.

Using GuiceFilter

Let's start with a typical web application development scenario. We need to write a JSP to render a form for searching flights and subsequently a response JSP page. The search form would post the request parameters to a processing servlet, which processes the parameters and renders the response.

Let's have a look at web.xml. A web.xml file for an application intending to use Guice for dependency injection needs to apply the following filter:

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

It simply says that all the requests need to pass via the Guice filter. This is essential since we need to use various servlet scopes in our application as well as to dispatch various requests to injectable filters and servlets. Rest any other servlet, filter-related declaration could be done programmatically using Guice-provided APIs.

Rolling out our ServletContextListener interface

Let's move on to another important piece, a servlet context listener for our application. Why do we need a servlet context listener in the first place? A servlet context listener comes into picture once the application is deployed. This event is the best time when we could bind and inject our dependencies.

Guice provides an abstract class, which implements ServletContextListener interface. This class basically takes care of initializing the injector once the application is deployed, and destroying it once it is undeployed. Here, we add to the functionality by providing our own configuration for the injector and leave the initialization and destruction part to super class provided by Guice. For accomplishing this, we need to implement the following API in our sub class:

protected abstract Injector getInjector();

Let's have a look at how the implementation would look like:

package org.packt.web.listener; import com.google.inject.servlet.GuiceServletContextListener; import com.google.inject.servlet.ServletModule; public class FlightServletContextListener extends GuiceServletContextListener { @Override protected Injector getInjector() { return Guice.createInjector( new ServletModule(){ @Override protected void configureServlets() { // overridden method contains various // configurations } }); }}

Here, we are returning the instance of injector using the API:

public static Injector createInjector(Module... modules)

Next, we need to provide a declaration of our custom FlightServletContextListener interface in web.xml:

<listener> <listener-class> org.packt.web.listener.FlightServletContextListener </listener-class> </listener>

ServletModule – the entry point for configurations

In the argument for modules, we provide a reference of an anonymous class, which extends the class ServletModule. A ServletModule class configures the servlets and filters programmatically, which is actually a replacement of declaring the servlet and filters and their corresponding mappings in web.xml.

Why do we need to have a replacement of web.xml in the first place? Think of it on different terms. We need to provide a singleton scope to our servlet. We need to use various web scopes like RequestScope, SessionScope, and so on for our classes, such as SearchRequest and SearchResponse. These could not be done simply via declarations in web.xml. A programmatic configuration is far more logical choice for this. Let's have a look at a few configurations we write in our anonymous class extending the ServletModule:

new ServletModule(){ @Override protected void configureServlets() { install(new MainModule()); serve("/response").with(FlightServlet.class); serve("/").with(IndexServlet.class); } }

A servlet module at first provides a way to install our modules using the install() API. Here, we install MainModule, which is reused from the previous section. Rest all other modules are installed from MainModule.

Binding language

ServletModule presents APIs, which could be used for configuring filters and servlets. Using these expressive APIs known as EDSL, we could configure the mappings between servlets, filters, and respective URLs.

Guice uses an embedded domain specific language or EDSL to help us create bindings simply and readably. We are already using this notation while creating various sort of bindings using the bind() APIs. Readers could refer to the Binder javadoc, where EDSL is discussed with several examples.

Mapping servlets

Here, following statement maps the /response path in the application to the FlightServlet class's instance:

serve("/response").with(FlightServlet.class);

serve() returns an instance of ServletKeyBindingBuilder. It provides various APIs, using which we could map a URL to an instance of servlet. This API also has a variable argument, which helps to avoid repetition. For example, in order to map /response as well as /response-quick, both the URLs to FlightServlet.class we could use the following statement:

serve("/response","/response-quick").with(FlightServlet.class);

serveRegex() is similar to serve(), but accepts the regular expression for URL patterns, rather than concrete URLs. For instance, an easier way to map both of the preceding URL patterns would be using this API:

serveRegex("^response").with(FlightServlet.class);

ServletKeyBindingBuilder.with() is an overloaded API. Let's have a look at the various signatures.

void with(Class<? extends HttpServlet> servletKey); void with(Key<? extends HttpServlet> servletKey);

To use the key binding option, we will develop a custom annotation @FlightServe. FlightServlet will be then annotated with it. Following binding maps a URL pattern to a key:

serve("/response").with(Key.get(HttpServlet.class, FlightServe.class));

Since this, we need to just declare a binding between @FlightServe and FlightServlet, which will go in modules:

bind(HttpServlet.class). annotatedWith(FlightServe.class).to(FlightServlet.class)

What is the advantage of binding indirectly using a key? First of all, it is the only way using which we could separate an interface from an implementation. Also it helps us to assign scope as a part of the configuration. A servlet or a filter must be at least in singleton In this case we can assign scope directly in configuration. The option of annotating a filter or a servlet with @Singleton is also available, although.

Guice 3.0 provides following overloaded versions, which even facilitate providing initialization parameters and hence provide type safety.

void with(HttpServlet servlet); void with(Class<? extends HttpServlet> servletKey, Map<String, String>
initParams); void with(Key<? extends HttpServlet> servletKey, Map<String, String>
initParams); void with(HttpServlet servlet, Map<String, String> initParams);

An important point to be noted here is that ServletModule not only provides a programmatic API to configure the servlets, but also a type-safe idiomatic API to configure the initialization parameters. It is not possible to ensure type safety while declaring the initialization parameters in web.xml.

Mapping filters

Similar to the servlets, filters could be mapped to URL patterns or regular expressions. Here, the filter() API is used to map a URL pattern to a Filter. For example:

filter("/response").through(FlightSearchFilter.class);

filter() returns an instance of FilterKeyBindingBuilder. FlightKeyBindingBuilder provides various APIs, using which we can map a URL to an instance of filter. filter() and filterRegex() APIs take exactly the same kind of arguments as serve() and serveRegex() does when it comes to handling the pure URLs or regular expressions.

Let's have a look at FilterKeyBindingBuilder.through() APIs. Similar to ServletKeyBindingBuilder.with() it also provides various overloaded versions:

void through(Class<? extends Filter> filterKey); void through(Key<? extends Filter> filterKey);

Key mapped to a URL, which is then bound via annotation to an implementation could be exemplified as:

filter("/response"). through(Key.get(Filter.class,FlightFilter.class));

The binding is done through annotation. Also note, that the filter implementation is deemed as singleton in scope.

bind(Filter.class). annotatedWith(FlightFilter.class). to(FlightSearchFilter.class).in(Singleton.class);

Guice 3.0 provides following overloaded versions, which even facilitate providing initialization parameters and provide type safety:

void through(Filter filter); void through(Class<? extends Filter> filterKey, Map<String, String>
initParams); void through(Key<? extends Filter> filterKey, Map<String, String>
initParams); void through(Filter filter, Map<String, String> initParams);

Again, these type safe APIs provide a better configuration option then declaration driven web.xml.

Web scopes

Aside from dependency injection and configuration facilities via programmable APIs, Guice provides feature of scoping various classes, depending on their role in the business logic.

As we saw, while developing the custom scope, a scope comes into picture during binding phase. Later, when the scope API is invoked, it brings the provider into picture. Actually it is the provider which is the key to the complete implementation of the scope. Same thing applies for the web scope.

@RequestScoped

Whenever we annotate any class with either of servlet scopes like @RequestScoped or @SessionScoped, call to scope API of these respective APIs are made. This results in eager preparation of the Provider<T> instances. So to harness these providers, we need not configure any type of binding, as these are implicit bindings. We just need to inject these providers where we need the instances of respective types.

Let us discuss various examples related to these servlet scopes. Classes scoped to @RequestScoped are instantiated on every request. A typical example would be to instantiate SearchRequest on every request. We need to annotate the SearchRQ with the @RequestScoped.

@RequestScoped public class SearchRequest { ……}

Next, in FlightServlet we need to inject the implicit provider:

@Inject private Provider<SearchRequest> searchRQProvider;

The instance could be fetched simply by invoking the .get() API of the provider:

SearchRequest searchRequest = searchRQProvider.get();

@SessionScoped

The same case goes with @SessionScoped annotation. In FlightSearchFilter, we need an instance of RequestCounter (a class for keeping track of number of requests in a session). This class RequestCounter needs to be annotated with @SessionScoped, and would be fetched in the same way as the SearchRequest. However the Provider takes care to instantiate it on every new session creation:

@SessionScoped public class RequestCounter implements Serializable{……}

Next, in FlightSearchFilter, we need to inject the implicit provider:

@Inject private Provider<RequestCounter> sessionCountProvider;

The instance could be fetched simply by invoking the .get() API of the provider.

@RequestParameters

Guice also provides a @RequestParameters annotation. It could be directly used to inject the request parameters. Let's have a look at an example in FlightSearchFilter. Here, we inject the provider for type Map<String,String[]> in a field:

@Inject @RequestParameters private Provider<Map<String, String[]>> reqParamMapProvider;

As the provider is bound internally via InternalServletModule (Guice installs this module internally), we can harness the implicit binding and inject the Provider.

An important point to be noted over here is that, in case we try to inject the classes annotated with ServletScopes, like @RequestScoped or @SessionScoped, outside of the ServletContext or via a non HTTP request like RPC, Guice throws the following exception:

SEVERE: Exception starting filter guiceFilter com.google.inject.ProvisionException: Guice provision errors: Error in custom provider, com.google.inject.OutOfScopeException: Cannot
access scoped object. Either we are not currently inside
an HTTP Servlet request, or you may have forgotten to apply
com.google.inject.servlet.GuiceFilter as a servlet filter for this
request.

This happens because the Providers associated with these scopes necessarily work with a ServletContext and hence it could not complete the dependency injection. We need to make sure that our dependencies annotated with ServletScopes come into the picture only when we are in WebScope.

Another way in which the scoped dependencies could be made available is by using the injector.getInstance() API. This however requires that we need to inject the injector itself using the @Inject injector in the dependent class. This is however not advisable as it is mixing dependency injection logic with the application logic. We need to avoid this approach.

Exercising caution while scoping

Our examples illustrate cases where we are injecting the dependencies with narrower scope in the dependencies of wider scope. For example, RequestCounter (which is @SessionScoped) is injected in FlightSearchFilter (which is a singleton).

This needs to be very carefully designed, as in when we are absolutely sure that a narrowly scoped dependency should be always present else it would create a problem. It basically results in scope widening, which means that apparently we are widening the scope of SessionScoped objects to that of singleton scoped object, the servlet. If not managed properly, it could result into memory leaks, as the garbage collector could not collect the references to the narrowly scoped objects, which are held in the widely scoped objects.

Sometimes this is unavoidable, in such a case we need to make sure we are following two basic rules:

  • Injecting the narrow scoped dependency using Providers. By following this strategy, we never allow the widely scoped class to hold the reference to the narrowly scoped dependency, once it goes out of scope. Do not get the injector instance injected in the wide scoped class instance to fetch the narrow scoped dependency, directly. It could result in hard to debug bugs.
  • Make sure that we use the dependent narrowly scoped objects in APIs only. This lets these to live as stack variables rather than heap variables. Once method execution finishes, the stack variables are garbage collected. Assigning the object fetched from the provider to a class level reference could affect garbage collection adversely, and result in memory leaks.

Here, we are using these narrowly scoped dependencies in APIs: doGet() and doFilter(). This makes sure that they are always available.

Contrarily, injecting widely scoped dependencies in narrowly scoped dependencies works well, for example, in a @RequestScoped annotated class if we inject a @SessionScoped annotated dependency, it is much better since it is always guaranteed that dependency would be available for injection and once narrowly scoped object goes out of scope it is garbage collected properly.

We retrofitted our flight search application in a web environment. In doing so we learned about many aspects of the integration facilities Guice offers us:

  • We learned how to set up the application to use dependency injection using GuiceFilter and a custom ServletContextListener.
  • We saw how to avoid servlet, filter mapping in web.xml, and follow a safer programmatic approach using ServletModule.
  • We saw the usage of various mapping APIs for the same and also certain newly introduced features in Guice 3.0.
  • We discussed how to use the various web scopes.
Learning Google Guice Utilize dependency injection to develop applications quickly and efficiently using Google Guice with this book and ebook
Published: September 2013
eBook Price: $17.99
Book Price: $29.99
See more
Select your format and quantity:

Integrating Guice with Struts 2

It is an action oriented, web framework based on MVC architecture. Guice integrates easily to provide dependency injection facility into the application developed. We will discuss the special modules and classes, which accomplish the task of integration. On top of it we would retrofit our application developed in the last section to be based on Struts 2. While doing so we will avoid writing servlets and filters and instead use Struts 2 provided classes.

It is desired that the reader is familiar with Struts 2, as primarily we are interested in injecting dependencies in Struts 2-based applications and not exploring Struts 2 itself. However, for the sake of completion of the subject matter, we will begin with a gentle introduction of the framework and go forward.

To begin development with Struts 2 we need struts2-core-2.3.14.jar file in our classpath. Also, for integrating it along with Guice, we need an extension of Guice for Struts2, guice-struts-2.3.0.jar. These two files along with various dependencies are listed in pom.xml, hence need not be separately downloaded. Readers could simply execute the maven command to package the WAR, and the necessary dependencies would be downloaded and packaged in the WAR file.

Introducing Struts 2

Struts 2 is an action-oriented MVC framework for web application development. It is based on the philosophy that framework should be action-oriented and loosely coupled with application logic. For example, a request handling should be an action itself and need not involve interacting with pieces which are a part of the framework. Unlike other frameworks, which impose conditions like extending from a class or implementing an interface to handle requests, Struts 2 defies such behavior. Instead, it provides various convenient interfaces or classes that could be used as per our application requirements and upfront coupling is not required. Struts 2 also defies the use of special classes, which are used to convey the result objects from model to view. Against this, Struts 2 provides the OGNL and ValueStack, which help to make available the member of Action class variables in the view.

ValueStack is a ThreadLocal object created to cater a request. For every request a different ValueStack is created. It comprises of two parts.

First is an ObjectStack, where objects are created and stored for processing a request. These are named objects, such as Application, Session, and Request, which are stored prior to request specific objects. Later request specific objects, such as Model and Action are created and stored. Temporary objects, which are created during execution of a JSP page are also stored over here.

Second is an ActionContextMap, which holds various maps related to an application. An example is an AttributeMap. It is a map of Request attributes, Session attributes, and Application attributes. Using an attribute map indirectly via an ActionContextMap, we can search for any attribute present in a request, session or application attribute map.

OGNL stands for Object Graph Navigation Language. It is similar to JSP Expression language and based on the idea of having a root object within the context. The properties of this root object can be referenced using the markup notation. An ActionContextMap is created by framework to act as a context. ActionContextMap consists of various objects, such as Application, Session, ValueStack, Request, Parameters, and Attributes.

OGNL assists in data transfer and type conversion. Its rich expression syntax allows easy referencing and manipulation of objects on ValueStack.

There are a few important characteristics of Struts 2, which facilitate application development greatly. These are:

  • Interceptors for layering cross cutting concerns away from the Action logic
  • Annotation-based configuration, which eliminates a lot of redundant configuration details
  • A tag-based MVC API, which supports modifiable and reusable components

MVC implementation in Struts 2 is fairly simple. Have a look at the following diagram for better understanding:

StrutsPrepareAndExecuteFilter acts as a controller. The essential purpose it serves is to inspect each incoming request to determine which action should handle the request. Once identified it passes on the control to the particular action instance.

Action, which is a model of application, serves two important functions. It encapsulates all the business logic needed to accomplish the request in a single unit of work. Secondly, it indicates what view to serve as per the request conclusion. For example, it could route to different views based on the processing of request; an error page for handling exceptions while a response page on successful request completion.

View is the presentation component of the application development. It could be a JSP page, an XSLT handling an example response, a FreeMarker, or a Velocity template. The working of a Struts 2 application could be summarized using the following diagram:

A chain of interceptors from Struts 2 intercepts any request to create a ValueStack. Once a ValueStack is prepared it is used to store and manipulate request-related objects like Model and Action, via ActionContextMap. The result, which could be a JSP page, manipulates and refers to ValueStack using OGNL and finally renders the response, which also passes back through the interceptor chain. In this way, a complete request-response cycle is handled.

Guice 3 and Struts 2 integration

There are several artifacts provided by guice-struts-2.3.0 extension to assist in implementing Guice 3 as the dependency injection provider. Let's examine them.

Struts2GuicePluginModule

Struts2GuicePluginModule needs to be installed before any of our modules are installed. This module basically requests the static injection of the Strtus2Factory class. Struts2Factory uses the injector later to prepare the instances of the requested object.

Struts2Factory

The Struts2Factory class is a sub class of com.opensymphony.xwork2.ObjectFactory. ObjectFactory is responsible for building the core framework objects in Struts 2. ObjectFactory.buildBean (class java.util.map) method is used to build all the core framework objects like interceptors, actions, and results. Struts2Factory overrides this method and requests their instance creation using injector. This instance of Struts2Factory as a Guice managed object prepares every required object through dependency injection.

FlightSearch application with Struts 2

Let us examine the artifacts one by one, which illustrate how quickly we could retrofit our application to use Struts 2 with Guice 3.

FlightServletContexListener

Here in the configureServlets(…) API, we simply need to install Struts2GuicePluginModule before installing our MainModule. Next, to it we need to declare a filter mapping indicating all the requests need to pass through StrutsPrepareAndExecuteFilter and provide it a singleton scope. Following listing shows the required piece of code.

install(new Struts2GuicePluginModule()); bind(StrutsPrepareAndExecuteFilter.class).in(Singleton.class); filter("/*").through(StrutsPrepareAndExecuteFilter.class);

Index page

The index page uses struts tags for rendering form and processing the request. The form variables on the index page appear as the properties of the FlightSearchAction class. Using ValueStack and OGNL, these are directly bound. This relieves us of the coupling between framework components and application logic. The relevant piece of code is as follows:

<%@ taglib prefix="s" uri="/struts-tags" %> <s:form action="Search"> <s:textfield name="source" label="From"/> <s:textfield name="destination" label="To"/> <s:textfield name="date" label="Date"/> <s:submit label="Submit"/> </s:form>

FlightSearchAction

FlightSearchAction is annotated with @Namespace and @ResultPath annotation to indicate the routing path. These are used while the action classes are being scanned by, for the declaration of mappings between URL and action mapping while the application is being loaded.

@Namespace("/") @ResultPath(value="/") public class FlightSearchAction extends ActionSupport{…}

Similarly, execute API of FlightSearchAction is also annotated with @Action annotation, which has a value parameter indicating a complete URL to be mapped against a executable API of Action class. This URL is the action of the search form in the index.jsp page.

Execute API of FlightSearchAction handles one complete instance of a work. Here it is to process the request and to return the SUCCESS signal. In case of any checked exception handling or any adverse condition, a different value could be returned, which could be any of the values from the com.opensymphony.xwork2.Action interface. The following code snippet shows the relevant piece of code where execute API of the FlightSearchAction is annotated with the @Action annotation, illustrating various result mappings.

@Action(value="Search",results={ @Result(name="success",location="response.jsp"), @Result(name="error",location="error.jsp") }, exceptionMappings={ @ExceptionMapping( exception="org.packt.exceptions.NoCriteriaMatchException", result="error",params={"message","No match found for the supplied
criteria"}), @ExceptionMapping(exception="org.packt.exceptions.
NoFlightAvailableException", result="error", params={"message","No Flight available exception"}) }) public String execute() {..}

Here, we could see that for various results, we have mapped different JSPs. We have mapped response.jsp to success and error.jsp to error. Also we could provide mappings for the run-time exception, if any, which result during execution of the request.

For instance, we throw two different kinds of run-time exceptions from the FlightEngine.process; these are NoCriteriaMatchException and NoFlightAvailableException. We could even provide the mapping for these and redirect them to the appropriate result location:

@Inject private RequestCounter requestCounter; @Inject private FlightEngine flightEngine; @Inject private Provider<SearchRequest> provider;

The singleton scoped, request scoped, and session scoped dependencies are injected and are used in a more simpler fashion than during pure web development.

Response page

The response page uses struts tags to display the properties of the SearchResponse object. The list of SearchResponse, which is the result of invoking FlightEngine.processRequest(…) is now assigned to a class attribute. This makes it directly accessible in the JSP page as it is present on the ValueStack and accessible by OGNL. The relevant piece of code is as follows:

<%@ taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%> <%@ taglib uri="http://struts.apache.org/tags-logic" prefix="logic"%> <logic:iterate name="results" id="searchResponse"> <bean:write name="searchResponse" property="flightNumber"/> </logic:iterate>

Integrating Guice with JPA 2

A familiarity with the JPA and Hibernate is desired, particularly in a web environment. However, we will begin with a gentle introduction to JPA and Hibernate. Post that, we will continue with our Struts 2 retrofitted application from the last section and make it driven by a JPA, Hibernate-backed database. In this process, we will see how to fit Guice in both standalone as well as a web application to be used as a persistence provider.

We will introduce the concept of transaction in a stand-alone application and in a web application with two strategies like Session per transaction and Session per request.

The guice-persist is the extension for working with JPA and Hibernate. Along with this, there are a couple of dependencies we need, like hibernate-entitymanager, hibernate-annoations, and hibernate-jpa-2.0. These are provided as maven dependencies and are available in packaged WAR.

We would stick to JPA 2.0 standard while using Hibernate 3 as a vendor implementation. For a database, we will use MySQL, although any database could be chosen for this purpose. The reader needs to change the relevant driver classes and configuration properties to use a different database. Please consult the Appendix for installing MySQL on your machine and also how to dump the data we will need to run the application.

Introduction to JPA 2 and Hibernate 3

Java Persistence API (JPA) is a specification for accessing, persisting, and managing data between Java objects or classes and a relational database. JPA is considered to be a standard approach for Object to Relational mapping (ORM) in Java.

JPA 2 is a work of the JSR 317 Expert Group. JPA 2 in itself is not a product, but is merely a set of interfaces which define how the persistence mechanism should work. There are a couple of open source and proprietary implementations of JPA 2 available. Hibernate, EclipseLink, and OpenJPA are prominent among them. We will be using Hibernate 3 as an implementation of the JPA 2 specification.

Hibernate is an object-relational-mapping library for java language, providing a framework for mapping an object-oriented-domain model to a relational database. Hibernate solves the problem of object-relational-impedance mismatch by replacing direct persistence-related database accesses with high-level object handling functions. Hibernate 3.5.0 and up is a certified implementation of Java Persistence API 2.0 specification via a wrapper for the core module, which provides conformity with the JSR 317.

For more information related to Hibernate and JPA, readers are encouraged to have a look at the following links:

Hibernate: http://en.wikipedia.org/wiki/Hibernate_(Java) and JPA: http://en.wikipedia.org/wiki/Java_Persistence_API

JPA 2 specifies various artifacts and interfaces, which help us to complete object relational mapping between various POJOs and database tables, and subsequently executing various operations over them. Let's glance over some important interfaces and artifacts.

Persistence Unit

A persistence unit represents the set of all classes that are grouped or related in an application. In simple terms, these are the POJOs, which are mapped to tables in a database.

PersistenceContext

PersistenceContext represents a set of entity instances in which for any persistent entity, there is a unique entity instance. In PersistenceContext, the entity instances and its lifecycle is managed by an Entity manager. PersistenceContext could be scoped either to a transaction or an extended unit of work.

For preparing a persistence context, the declarative way is the usual approach. The declaration for a persistence context is provided in a persistence.xml file, which resides in classpath in META-INF folder. This file contains definition about a particular persistence unit, wherein what classes are part of it. It also contains other properties, such as a database connection, and a database dialect.

EntityManagerFactory

An EntityManagerFactory creates instances of EntityManager for a particular PersistenceContext. It could only create instances of an EntityManager for a particular PersistenceContext. It is equivalent to SessionFactory in Hibernate.

EntityManager

EntityManager is used to access the database in a particular unit of work. It is used to create, remove, and query persistent entity instances. This is equivalent to session in Hibernate. Although read-only operations could be completed outside the purview of a transaction, insert, update, and delete operations need to be covered under transactions. Generally, transactions are enabled declaratively using annotations, and are performed using interceptors.

Session Strategies

There are two types of session strategies generally considered for different situations.

  • Session-per-transaction: In this, a session (in our case, EntityManager) is prepared just before a transaction is required, and closed thereafter. This is not a preferred strategy, but is mostly used in standalone applications and unit testing.
  • Session-per-request: In this, a session is prepared once a request is received. For example, in a web application, the session is opened once a request is received. This is usually accomplished using a Filter. Generally, these are OpenSessionInViewFilter for Hibernate or OpenEntityManagerInViewFilter for JPA specification. The session is closed once the filter finishes the work.

Guice 3 with JPA 2

The extension guice-persist provides various classes, which facilitate the injection of EntityManger in our data access layer classes.

PersistService

PersistService is an interface, exposing two APIs, start and stop. The implementations of these two APIs means preparing and destroying the EntityManagerFactory instance, using Persistence.createEntityManagerFactory() API.

UnitOfWork

UnitOfWork is an interface, exposing two APIs, begin() and end(). The implementations of these two APIs necessarily mean creating an EntityManager instance using the EntityManagerFactory created earlier. It serves an essential purpose, because it opens the session for read-only operations, and closes them accordingly.

JpaPersistService

It is the implementation of the two interfaces we discussed as well as the Provider for EntityManager. JpaPersistService takes a String and a Properties reference as an argument to its constructor. JpaPersistService prepares and destroys the EntityManager when called to start() and stop() arrives respectively. On the other hand, begin() and end() APIs begin and end a transaction using the EntityManager prepared earlier. Through the get() API, the provider provides the reference to the EntityManager prepared.

PersistFilter

This filter basically acts to start or stop the persistence service while the request is being made. It implements the Session-per-request strategy, a common strategy in web applications. During the initialization of the filter, the start() method is invoked, while during the destruction of the filter, the stop() method is invoked. In doFilter() API while handling the request, the request-handling portion is wrapped in invocation calls of begin() and end(). This basically makes the EntityManager available for database read-only operations.

@Transactional

Transaction is a cross-cutting concern. There is a little point in managing transactions on our own, particularly in data access classes. It makes a lot of sense to get these accomplished using framework utility classes. Guice provides @Transactional interface, which essentially means to include the annotated method inside a transaction. All the methods annotated with @Transactional are intercepted and wrapped around calls to begin and conclude the transaction. In the event of an exception, necessary steps to rollback or ignore the exception could also be configured via this annotation. The important caution is that whatever methods which are being annotated with this annotation, must be publicly accessible and should be present in classes which are managed by Guice. The invocation of @Transactional annotated methods should be done only on Guice managed objects, which are effectively injected instance variables.

For example, the getResults() method of FlightJPASupplier is annotated with @Transactional. This method is invoked on the instance of FlightJPASupplier, which is injected in FlightEngine.

JpaLocalTxnInterceptor

Before we proceed to discuss JpaLocalTxnInterceptor, lets look at what is an Interceptor? An Interceptor, or more precisely a method, intercepts an invocation call to a matching method and wraps the original invocation call inside its own execution. This methodology is suitable to handle cross-cutting concerns. Such a way to handle cross-cutting concerns falls under the purview of Aspect Oriented Programming (AOP). We discuss AOP implementation of Guice.

The interceptor whose invoke() comes into the picture once the methods annotated with @Transactional are invoked, accomplishes following things:

  • Checks if a unit of work has started; if not, start it.
  • Begins a transaction.
  • Allows normal method invocation to proceed.
  • Ends a transaction.
  • In case of an exception which is configured for rolling back a transaction, the transaction is rolled back.
  • In case of an exception which is configured for ignoring, the transaction is committed, and an exception is propagated.
  • Essentially, it ends a unit of work.
  • Returns the result.

JpaPersistModule

This module basically configures the JpaPersistService and binds it to the interfaces PersistService and UnitOfWork as the implementation. The constructor argument is the name of the persistence unit configured in the persistence.xml file. Properties are derived from the persistence.xml file itself.

The following figure shows various artifacts and their relationship with each other:

FlightSearch application with JPA 2 and Hibernate 3

We will retrofit the application to run in two different modes. First in a standalone mode, we will use the Client as our pivot. Later, we will refactor and use it for a web application.

Persistence.xml

Persistence.xml contains the declaration for a persistence-unit. The following code shows that:

<persistence-unit name="flight" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>org.packt.supplier.SearchResponse</class> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5InnoDBDialect"/> <property name="hibernate.connection.driver_class" value="com.mysql.jdbc.Driver"/> <property name="hibernate.connection.driver" value="com.mysql.jdbc.Driver"/> <property name="hibernate.connection.url" value="jdbc:mysql://localhost/flights"/> <property name="hibernate.connection.user" value="flight"/> <property name="hibernate.connection.password" value="flight"/> </properties> </persistence-unit>

Persistence-unit basically defines what needs to be encompassed in an instance of PersistenceContext.

Client

Client has two extra APIs to encapsulate service initialization and destruction. In standalone moden we need to invoke the service.start() and service.stop() methods manually. The following code shows that:

public static void main(String args[]){ Injector injector = Guice.createInjector( newJpaPersistModule("flight"),new MainModule()); Client client = injector.getInstance(Client.class); client.startService(); client.makeRequest(); client.stopService(); }

A notable point here is Session per transaction strategy. Before we make a transaction, we prepare the EntityManagerFactory using startService(), and later destroy it using stopService(). The unitOfWork.begin() and unitOfWork.end() invocation happens inside the JpaLocalTxnInterceptor.invoke() method.

We need to inject the PersistService inside the Client, and use it from encapsulated methods. The following code explains how:

@Inject private PersistService persistService; private void startService(){ persistService.start(); } private void stopService(){ persistService.stop(); }

SearchResponse

SearchResponse is annotated with @Entity, and hence is an entity in the persistent unit flight. Its instances are available in a persistence context, which is on looked by an instance of an EntityManager. The following code shows that:

@Entity @NamedQueries({ @NamedQuery(name="SearchResponse.findAll",query="select s from
SearchResponse s") }) @Table(name="flight") public class SearchResponse implements Comparable<SearchResponse>,
Serializable{ private static final long serialVersionUID = 1L; @Id private Long id; }

There are named queries, which we will be using from our data access layer. Let's have a look at our data access layer.

FlightEngineModule

Declaration to bind an instance of the FlightSupplier interface with an implementation of FlighJPASupplier is provided in the FlightEngine module. Let's look at it in the following code:

bind(FlightSupplier.class) .annotatedWith(Names.named("jpa")) .to(FlightJPASupplier.class).in(Singleton.class);

FlightJPASupplier

FlightJPASupplier, like other suppliers, implements the FlightSupplier interface and is injected in FlightEngine using @Named annotation. Following is a relevant piece of code from FlightEngine:

@Inject @Named("jpa") private FlightSupplier flightJPASupplier;

We will be using flightJPASupplier to retrieve the results rather than other suppliers. Let's look at the FlightJPASupplier.getResults() in the following code:

@Inject private Provider<EntityManager> entityManagerProvider; @Override @Transactional public Set<SearchResponse> getResults() { Query query = entityManagerProvider.get().createNamedQuery
("SearchResponse.findAll"); Set<SearchResponse> resultSet = new HashSet<SearchResponse>(); resultSet.addAll((List<SearchResponse>)query.getResultList()); return resultSet; }

The method is annotated with @Transactional, and hence provides us declaratively managed transactions. Also, the EntityManager is provided by the entityManagerProvider, which is provided by JpaPersistenceService. We query in a persistence context using the named queries, and fetch the result.

The following sequence diagram highlights how the call propagation progress in stand-alone mode. This was the example of Session-per-transaction strategy.

SearchRequest, annotated with @RequestScoped, could be a problem. Because we are operating out of a web context, the injector initialization would fail. We need to remove the @RequestScope before attempting to build the solution for the stand-alone mode. Once we attempt to deploy the solution as a web application, we need to apply the @RequestScoped, and this should work normally.

Now, let's look at what changes are required for making the web application work.

FlightServletContextListener

FlightServletContextListener needs to configure an instance of JpaPersistModule. Afterward, we configure an instance of Struts2GuicePluginModule, and then our MainModule. Later on we just need to configure PersistFilter to provide us OpenEntityManagerInView available for readOnly queries.

protected void configureServlets() { install(new JpaPersistModule("flight")); install(new Struts2GuicePluginModule()); install(new MainModule()); bind(StrutsPrepareAndExecuteFilter.class).in(Singleton.class); filter("/*").through(StrutsPrepareAndExecuteFilter.class); filter("/*").through(PersistFilter.class); }

The following sequence diagram makes it clear how the request propagation works in a web application. This was the example of Session-per-Request strategy.

Summary

In this article we retrofitted our flight search application in a web environment. In doing so we learned about many aspects of the integration facilities Guice offers us. We learned how to set up the application to use dependency injection using GuiceFilter and a custom ServletContextListener. We saw how to avoid servlet, filter mapping in web.xml, and follow a safer programmatic approach using ServletModule. We saw the usage of various mapping APIs for the same and also certain newly introduced features in Guice 3.0. We discussed how to use the various web scopes. We would redevelop the application using Struts2.

This article focused on integrating Guice 3 with Struts 2. Installing the module Struts2GuicePluginModule in our FlightServletContextListener.configureServlet(…) API and registering StrutsPrepareAndExecuteFilter to map /* all the URLs to it are the only steps we need to take, to prepare a Struts 2 application to use Guice 3 dependency injection features.

We have learned to use the artifacts provided by the guice-persist extension to integrate JPA, and Hibernate within a web application powered by Struts 2, and also in a stand-alone application. We also implemented various session strategies in different scenarios. Also, we saw that how simple and non-conflicting it is to start a unit of work from a Guice-injected class, and fetch the record from the database. The discussion will be carried out through Guice Service Provider Interfaces (SPI).

Resources for Article:


Further resources on this subject:


Learning Google Guice Utilize dependency injection to develop applications quickly and efficiently using Google Guice with this book and ebook
Published: September 2013
eBook Price: $17.99
Book Price: $29.99
See more
Select your format and quantity:

About the Author :


Hussain Pithawala

Hussain Pithawala is a polyglot programmer, a technical blogger, open source enthusiast, and a certified scrum master.

At present he is a working as technical lead at Synerzip Softech India Pvt. Ltd, a leading dual-shore agile software product development company located in Pune, India.

For the past seven years, he has been working in I.T. industry in various domains such as, office productivity suite, telecom provisioning, travel, and E-commerce.

He holds expertise in software tooling, BPMN-based workflow engines, scripting languages, enterprise application development, mobile application
development, and data analytics.

LinkedIn Profile: http://in.linkedin.com/in/hussainpithawala

Twitter: https://twitter.com/hussainpw

Blog: http://hussainpithawala.wordpress.com

Books From Packt


Google Plus First Look: a tip-packed, comprehensive look at Google+
Google Plus First Look: a tip-packed, comprehensive look at Google+

Google Visualization API Essentials
Google Visualization API Essentials

Google App Inventor
Google App Inventor

Google Web Toolkit GWT Java AJAX Programming
Google Web Toolkit GWT Java AJAX Programming

 Java EE 6 with GlassFish 3 Application Server
Java EE 6 with GlassFish 3 Application Server

Refactoring with Microsoft Visual Studio 2010
Refactoring with Microsoft Visual Studio 2010

 Mastering Ninject for Dependency Injection
Mastering Ninject for Dependency Injection

JBoss Weld CDI for Java Platform
JBoss Weld CDI for Java Platform


No votes yet

Post new comment

CAPTCHA
This question is for testing whether you are a human visitor and to prevent automated spam submissions.
Q
Q
t
H
w
W
Enter the code without spaces and pay attention to upper/lower case.
Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software