This article discusses applications of the Spring framework in configuring Servlets that have database interactions and need to use transactions. Before beginning, it is important to understand in practice how Spring can be used to configure Servlet object instances provided to a Servlet 3.0 container. I discussed this in detail in an earlier article, Servlet dependency injection with Spring; if you are not familiar with the techniques available to cause Spring to create Servlet objects for you, you should read this article now.
Most Java Enterprise applications interact with some form of database. This is typically achieved by presenting some set of “model” objects to the interface code. The model objects are often managed by a framework like Hibernate or an alternative implementation of the Java Persistence API, which typically communicates with a relational database to store them.
Because such applications often run in parallel and modifications to model objects can often change many objects simultaneously (e.g. adding credit to one account while deducting from another) with a requirement that the changes be atomic (i.e. it is not permissible if credit is added to one account but the corresponding deduction not made on the other) and isolated (i.e. the state of the database used to make decisions while processing a request must remain consistent over multiple steps of the process), the use of database transactions is a common requirement. Even in simpler applications, where controllers might access an SQL database directly, transactions are often a requirement. And while transactions are not typically difficult to manage, programmer effort can be saved by automating the process of managing them.
In a web-based environment, it is highly unusual for transactions to persist outside of the scope of a single request. Clients are not generally considered reliable, and server software is not usually notified when they disappear, so allowing a transaction to persist pending a second request that may never arrive is not often a good idea.
It is also unusual to need more than one transaction within a single request: a request encapsulates a logical unit of work, and if there is a need for more than one transaction this is perhaps a sign that the request should be split into multiple requests (perhaps using a technology such as AJAX, or simply by refreshing the browser page periodically) which would allow a better user experience - the ability to cancel an operation in progress, for example, along perhaps with a display of progress.
It therefore seems sensible to automate transactions by automatically generating them on a per-request basis. The transaction would thereafter be committed on successful completion of the request (or rolled back if the request failed, for example by throwing an exception).
Aspect-oriented programming in Spring
In addition to its primary focus on dependency injection, the Spring framework provides support for a variety of additional features, and aspect-oriented programming is one of the most useful. Aspect-oriented programming, or AOP, is a system that provides an ability to declare that certain code is to be executed when certain events occur in other code. For example, we can instruct Spring to execute one method any time some other method is executed. In particular, we can have our own code executed before and after the HttpServlet.service() method is called, which corresponds exactly to the lifespan we want our transactions to have. Let’s see some code that shows how this would work (we’ll not complicate matters with a database just yet, so we won’t generate any transactions yet, but printing some messages to the server console will suffice to see what’s going on).
First, we need a base project set up with Servlet objects being created by Spring, as described in the earlier article mentioned above. And we also need to add some external libraries to our classpath, as Spring’s AOP support relies on code that comes from a couple of third-party products. The code we need is “aopalliance.jar” (which can be downloaded from http://sourceforge.net/projects/aopalliance/), and “aspectjrt-1.7.0.jar” and “aspectjweaver-1.7.0.jar” (both of which are from http://www.eclipse.org/aspectj/downloads.php). Once these are installed, we can set up our application context to support aspect-oriented code.
Listing 1: applicationContext.xml with support for AOP
<?xml version="1.0" encoding="UTF-8"?>
<aop:config proxy-target-class="true" />
There are three significant changes here, which I’ve highlighted in bold. First, we’re declaring the ‘aop’ namespace and schema, which lets us use the AOP features of the Spring container. Then we configure the AOP system to use proxies for classes. Spring’s AOP works by creating a proxy for any beans whose methods need to have calls intercepted, but by default it will only do this for methods declared in interfaces. Unfortunately, the method we want to intercept calls to, HttpServlet.service(), is declared in HttpServlet which is a class. We must therefore tell Spring to proxy classes as well as interfaces. Finally we tell Spring to scan the beans we create for AspectJ annotations. We will use such annotations later to configure the events we want to respond to.
Next, we need a servlet whose requests will be intercepted. We can use the “hello world” servlet from before, so we just add the necessary configuration into the servlet map:
Listing 2: configuring a servlet
<entry key="/hello"><bean class="com.example.web.HelloWorldServlet" /></entry>
And finally we need an object that will be notified when the servlet’s service method is executed:
Listing 3: declaring an aspect
<bean id='testAspect' class="com.example.springtransactions.TestAspect" />
With the necessary Spring configuration done, we just need some code. Annotations in that code will tell Spring exactly what to do with it.
Listing 4: TestAspect - logging requests to System.out
public class TestAspect
@Before("execution(* javax.servlet.http.HttpServlet.service(..)) && "+
public void printRequests (HttpServletRequest request)
System.out.println ("Request: " + request.getMethod () + " " + request.getRequestURL ());
Our class is annotated with @Aspect to tell Spring to look in it for declarations of methods to invoke when it detects the appropriate conditions. We call such a class an ‘aspect’. This aspect has a single such method (we call the method an ‘advice’, because it is used to advise us of its specific condition). It is annotated with @Before to tell Spring to call it before a particular event occurs (we call such an event a ‘pointcut’ because execution is cut at that point and passed to the advice, and then usually restored after the advice has finished executing). The pointcut in this case is execution of the HttpServlet.service() method, which is configured by the string “execution(* javax.servlet.http.HttpServlet.service(..))”. The pointcut definition continues to specify a name for the invocation’s first parameter; we then declare a parameter in our advice with this name to tell Spring to pass us the parameter from the original invocation of service().
Running this in an appropriate server (I used an instance of Apache Tomcat 7.0 running under Eclipse so I could easily monitor its ouput) and requesting the /hello page, you should see something like this:
Request: GET http://localhost:8080/simplespring/hello
As well as @Before, there are various other kinds of advice. The most important are @AfterReturning (which is executed if the method returns successfully), @AfterThrowing (executed if the method throws an exception), @After (executed however the method ends), and @Around (executed before the method and passed an object that can be used to invoke the method from within the advice).
Hope you liked the article. See you next time.