Using Spring and OpenJPA with WebSphere Application Server

This article shows how to leverage the Spring Framework and Apache OpenJPA to improve the productivity and application development experience for your J2EE projects. Our sample application uses Spring in several scenarios in different architectural layers of a Web application, focusing on the business tier, particularly the service and data access layers.

Marko Asplund (marko.asplund@yahoo.com), Senior Consultant, Ixonos oyj

author photoMarko Asplund is a senior consultant specializing in the design and implementation of enterprise information systems, typically implemented using Java technologies. He is a Sun Certified Enterprise Architect, Sun Certified Business Components Developer and Sun Certified Java Programmer.



29 October 2008

Also available in Chinese Japanese

Introduction

Spring is a Java™ framework that simplifies J2EE development. It has facilities for all the layers of a J2EE application. It also does not impose a particular programming model so it is runtime-environment agnostic, meaning you can use it in application servers other than the Java SE environments. The popularity Spring has enjoyed in recent years can probably, at least in part, be attributed to these design principles. Some Spring proponents even see the framework as an alternative to J2EE. In our opinion, using J2EE does not preclude the possibility of using Spring or vice versa, but these technologies complement each other rather nicely.

OpenJPA is a Java Persistence API (JPA) implementation whose roots go back to the SolarMetric Kodo Java Data Objects (JDO) implementation. Kodo was acquired by BEA, which extended Kodo to implement the Java Persistence API and eventually open-sourced the code base as Apache OpenJPA. Currently OpenJPA is a viable object-relational mapping tool for Java with both BEA and IBM contributing to the project, among others.


Sample application

You should know

WebSphere Application Server V6.1 and V7 support EJB 3, which supports JPA natively, and simplifies development in many ways that are similar to Spring. See this related article and the Resources below for more information.

This article uses a basic Web application called Events to demonstrate various techniques for using Spring and OpenJPA to develop applications that run on WebSphere Application Server. We designed a simple application to focus on demonstrating how these technologies can be used together. The sample provides three simple use cases: add event, list events and edit event. Information input by the user is persisted in a relational database. Users can view a list of events stored in the system (Figure 1). For each event, the event list shows an internal identifier as well as an event title.

Figure 1. Listing events
Event list form

The user can add events by clicking the Add button in the listing view. When adding an event, the user is required to type in the title, category, start time and duration fields. Mandatory fields are marked with an asterisk (Figure 2). The Id field is inactive when adding an event.

The user can also modify event data, using the corresponding Edit link in the list view.

Figure 2. Adding an event
Event add form

Architectural overview

The Events application uses Java SE 5 and J2EE 1.4, and runs on WebSphere Application Server 6.1. It also uses JavaServer Faces (JSF) 1.1 technology to implement the user interface. We leverage the Spring Framework throughout the application architecture, and use the Java Persistence API in the data access layer.

Figure 3 shows a somewhat simplified structural view of the application. JSF pages use JSF managed beans for performing actions such as loading and storing event information. For improving reusability there are two types of managed beans: beans that perform actions (EventBacking) and beans that hold state (EventSession). The action (or backing) beans are request scoped, while state holding beans are session scoped. This separation makes it easier to reuse both types of beans across different views, if you happened to have a large number of views in your application. The backing bean gets a handle to the current user session state because the state is injected into the backing bean via the JSF managed bean facility.

Figure 3. Architecture diagram
Graphic of architecture flow

The backing bean delegates add event request processing to the EventServiceEJB Stateless Session Bean, and delegates listing and saving events to an EventService implementation. Typically you would access database data in either the Web or EJB application tiers, but not both. The sample application accesses the database through the service layer from both tiers to demonstrate how we use Spring in both of them.

EventServiceEJB further delegates processing to an EventService interface implementation class. The service implementation class then uses a Data Access Object (DAO) implementation class to communicate with the persistent data storage. The service layer has methods for finding a particular event, creating, updating and removing events as well as listing all events. The DAO accesses database data using the Java Persistence API EntityManager (see Figure 4).

Figure 4. Service layer diagram
Graphic of the service layer

The architecture includes several layers, including a service layer, whose main purpose is to make the architecture imitate a real world application. One concrete function that the EventService service layer accomplishes is that it acts as the plug-in point for transaction management, as we’ll show later.

The application’s domain model (Figure 5) consists of a single Java class called Event that we implemented as a JPA entity. We mapped the entity to a single database table that includes the corresponding columns.

Figure 5. Domain model
Graphic of the domain model

The application is structured into four projects:

  • events-ear: EAR packaging, shared libraries etc.
  • events-ejb: business logic tier, EJB session bean
  • events-service: service layer and data access
  • events-war: web tier

Development

To work with the sample application using an IDE, you need to install the following pre-requisite software:

  • Eclipse 3.4 for Java EE
  • IBM WebSphere Application Server v6.1 (v6.1.0.9 or later 6.1 release. Sample application tested with v6.1.0.17)
  • Java SE JDK 1.5 (can use the JDK bundled with WebSphere Application Server)
  • IBM DB2 (DB2 UDB 8.2 or Apache Derby v10.4.2.0)

The sample application uses Spring Framework v2.5.5 and Apache OpenJPA v1.2.0 (see the events-ear/docs/libraries.txt file for a list of other APIs and versions used).

Set up the application project as follows:

  1. Download the events.zip package and extract it
  2. Import the source tree into Eclipse. Select Import under the File menu and choose General / Existing Projects into Workspace. Select the extracted source tree root directory as the import root. The Import dialog should look like Figure 6:
    Figure 6. Import the project
    Eclipse Import form
  3. Create a user library called WAS 6.1 J2EE. Select Window - Preferences and then navigate to Java / Build Path / User Libraries and click New to create a new library. Note that it’s important to use the name WAS 6.1 J2EE so that the library will be automatically added to the events-ejb and events-war project build paths (see Figure 7). After creating the library, add the j2ee.jar file from your WAS 6.1 installation to the library. You’ll find the file at ${app_server_root}/lib/j2ee.jar (where app_server_root refers to your Application Server 6.1 installation root directory).
    Figure 7. Create a user library
    Eclipse user library form
  4. Download the required class libraries and place them in the correct places in the project tree, as described in events-ear/docs/libraries.txt
  5. Edit the build.properties file in the events-ear directory. You should set the was-profile.root variable value to reflect your Application Server 6.1 installation path
  6. Build the project EAR file. Open the build.xml Ant build file under events-ear. Right-click on the “dist” target in the Eclipse Outline view, and choose Run As / Ant Build. When the build is complete, you’ll find the EAR file in the dist directory under the source tree root.

Deployment

When you have built the application EAR package, use the procedure described below for deploying the events.ear in your application server. You’ll find the EAR package in the dist directory under the root of the project structure.

  1. Create a database schema for the application or select an existing schema.
  2. Execute the events.ddl DDL statements to create a database table (in events-service/setup)
  3. Open up the WAS Console and set up an XA data source that connects to the database schema created earlier. Use the JNDI name jdbc/eventDS for the data source, as Figure 8 shows.
    Figure 8. Provide JNDI names for beans
    Application Server console - JNDI name form
  4. Deploy the application. Navigate to Applications / Enterprise Applications in the Application Server console, and click Install. The deployment wizard starts. Select the path to the events.ear file when asked to enter the path to the new application.
  5. Map the ejb/EventServiceEJB resource reference to ejb/EventServiceEJB, as Figure 9 shows:
    Figure 9. Map EJB references to beans
    Application Server console - Map EJB references form
  6. Next map the jdbc/eventDS resource reference to the jdbc/eventDS JNDI name (Figure 10).
    Figure 10. Map resource references to resources
    Application Server console - Map resources form
  7. Finally, when the deployment wizard finishes, click Manage Applications and select events-ear / Manage Modules / events-war. Set the class loader order to Classes loaded with application class loader first, then click OK and Save.
    Figure 11. Manage events-war module
    Application Server console - Manage events form
  8. Start the application from the Enterprise Applications list. When the application starts a green arrow symbol should be visible under the Application Status column.
  9. Access the application by pointing your browser to
    http://localhost:9080/events-war/faces/jsp/eventsList.jspxThe URL should reflect your Application Server URL

Using the Spring Framework and OpenJPA

So far we’ve covered the sample application from the use case, development and deployment perspectives. Let’s now turn our attention to bootstrapping and using Spring and OpenJPA. In the next section we’ll see how to use some of Spring’s mechanisms designed to make life easier for the Java enterprise developer, including support for loose coupling, transaction management, exception handling, data access and distribution.

Container instantiation

One of the fundamental tenets of the Spring Framework is that it lets the developer declare service objects (beans in Spring parlance), along with their interdependencies, to be managed by the framework inside a light-weight container. The container takes responsibility for managing the lifecycle of declared beans and their dependencies. When a container is instantiated, Spring wires up any declared collaborating objects. Because the framework is responsible for ensuring that dependent objects have access to their collaborators, as opposed to the dependent objects having to lookup their collaborators, Spring is also called an Inversion of Control (IoC) container. You can declare the beans using different mechanisms, one of them being an XML configuration file. You can also use programmatic or annotation- based bean declaration.

You instantiate the container a bit differently depending on the application tier. In the Web tier, you can instantiate the container by simply putting the XML fragment from Listing 1 in your /WEB-INF/web.xml file:

Listing 1. Listener class
<listener>
  <listener-class>
    org.springframework.web.context.ContextLoaderListener
  </listener-class>
</listener>

By default, this class loads the /WEB-INF/applicationContext.xml file, which is expected to include Spring bean declarations. You can customize the default configuration file path if required. The Web application’s ServletContext is used as a bind target for the container instance, to make it available for subsequent use without having to instantiate it multiple times.

Since there’s no standard way to initialize an application in the EJB as in the Web tier initialization mechanism in J2EE 1.4, you need to instantiate the Spring container a bit differently there. Spring includes several different implementation classes for creating and loading the container. Because instantiating the container is costly, we should avoid doing it every time we require an instance. Since the EJB specification has no suitable facility for sharing container instances, it’s often appropriate to use a singleton-based instantiation strategy.

To use this method you typically need to create an EJB-specific Spring bootstrap configuration file called beanRefContext.xml (by default), that in turn loads a set of other bean configuration files. You would also override setSessionContext in your EJB implementation class. Container instantiation doesn’t work quite as non-intrusively in the EJB tier as it does in the Web tier. One visible drawback is that you need to use the Spring APIs to explicitly look up beans.

A similar approach is to use one of Spring’s abstract EJB implementation support classes as a base class for your EJB implementation. These convenience classes relieve the coder from having to implement the EJB component interface methods, but also take care of instantiating the Spring container. You would still have to create beanRefContext.xml and implement setSessionContext, though. One downside to this method is that you can’t use your own EJB base classes.

Sometimes you end up with situations where ServletContext is not available, even in the Web tier. This might happen if you’re extending a third party application or framework, and you want to use Spring beans in your code, but the API doesn’t pass the context to the extending classes. In this case you could instantiate the Spring container in a similar fashion as described above for the EJB tier.

Dependency injection

With Spring, the container takes care of making references to collaborating objects available to dependent objects, using a technique called Dependency Injection (DI). Dependency injection differs from the standard J2EE mechanism for providing access to collaborating objects. In J2EE, you use the JNDI Environment Naming Context (ENC) as a mechanism for making collaborating objects available via a name space, and acquiring references to them. By using JNDI ENC, the dependent object can explicitly request a reference to a certain collaborator.

When using Spring DI, the programmer requests that the container resolves dependencies by making collaborator references available to dependent objects, by using constructor or setter injection variants. With constructor injection, the container passes the collaborator in the constructor call, whereas with setter injection the container passes the reference using a mutator method call after creating the dependent object. In both cases you need to declare the dependency (e.g. using the Spring configuration file) and add a corresponding constructor or mutator method to the dependent object class.

The classic book on design patterns, Design Patterns: Elements of Reusable Object-Oriented Software, promoted the “program to an interface, not an implementation” design principle. Even if you program to an interface the implementation class still needs to be instantiated somewhere. You can simply instantiate it programmatically, but then your code will depend on a concrete implementation class. Another approach would be to create a factory class for instantiating the implementations, but there would still be a dependency to the implementation class in your code. It’s important to note that even if the dependencies can be confined and few in number, source code level dependencies still exist.

The EventService interface implementation class in Listing 2 demonstrates this approach. Here the service implementation only has a source-level dependency on the EventDAO interface, not the DAO implementation class:

Listing 2. EventService interface implementation
public class EventServiceImpl implements EventService {
  private EventDAO eventDAO;

  public void setEventDAO(EventDAO eventDAO) {
    this.eventDAO = eventDAO;
  }
  // …
}

The dependency is declared in Spring configuration as follows:

<bean id="eventDAO" class="events.service.EventDAOJPA"/>

<bean id="eventService" class="events.service.EventServiceImpl">
  <property name="eventDAO" ref="eventDAO"/>
</bean>

Spring provides loose coupling by letting you declare the dependencies in a configuration file and then wires collaborators to dependent objects. This makes it possible to entirely decouple the caller from the implementation class, which makes your code much more flexible. Switching an implementation class now becomes a matter of simply modifying the Spring configuration file.

Exception handling

In recent years, criticism has arisen on how Java APIs use the Java exception model. Many people have argued that you, the programmer, should not be forced to handle fault conditions that are expected to be rare in nature, and arise from system or programmer failures that can’t be reasonably recovered from. Instead, you should use unchecked exceptions for such conditions, so that you can optionally handle these conditions. In this school of thought, only application or user errors that are expected to happen during normal operation should be reported using checked exceptions. This exception handling strategy has become increasingly popular with many frameworks and APIs subscribing to this way of thinking, including Spring.

Service layer support

Having a well-designed and implemented service layer can have a large positive impact on the extensibility and robustness of your application. Adding new end-user features and modifying existing ones can prove much simpler with a highly reusable service layer.

Transaction demarcation can have a negative effect on service layer reusability if implemented inappropriately. This is a challenge, since you could use the service layer to implement vastly different use cases, causing the service-layer caller to operate in dissimilar contexts. Callers will have varying transactional requirements, so the service layer should allow the caller to affect transaction handling.

When the transactional requirements of the application are not very complex, programmatic transaction demarcation can be cumbersome and error-prone. Declarative transaction demarcation lets you declare rules for the transactional behavior of the software, and have the transaction manager automatically carry out these rules. Spring supports both programmatic and declarative transaction demarcation. The sample application uses the declaration in Listing 3 to define transactional attributes for the service layer:

Listing 3. Transactional attributes
<tx:advice id="txAdvice" transaction-manager="transactionManager">
  <tx:attributes>
    <tx:method name="*" propagation="REQUIRED"/>
  </tx:attributes>
</tx:advice>

<aop:config>
<aop:pointcut id="serviceMethods"
       expression="execution(* events.service.EventService.*(..))"/>
  <aop:advisor advice-ref="txAdvice" pointcut-ref="serviceMethods"/>
</aop:config>

This configuration uses Spring’s support for Aspect Oriented Programming (AOP). In Listing 3, we define something called a transaction advisor object and bind the transaction manager to this advisor. We tell the transaction advisor to apply the REQUIRED transaction attribute to all of the declared methods. The semantics of the REQUIRED transaction attribute are the same as in J2EE, meaning that the method will always execute within a transaction. If the caller is running in a transactional context, the method executes in the caller’s context. Otherwise it creates a new transaction context.

The aop:config part then defines a set of methods, namely all methods in the events.service.EventService interface to which we apply the transactional declaration. Transactionally advised classes don’t have to implement special component interfaces; transactional attributes can be specified for Plain Old Java Object (POJO) classes. To implement this, Spring wraps the original service object with a transactional proxy. One caveat here is that service object local calls do not go through the transactional proxy, and thus will always occur in the transaction context of the caller.

Spring uses a transaction manager interface implementation to perform the actual transaction demarcation at runtime. You can configure your service layer to use different transaction managers depending on the capabilities of the target environment. For example, when your service layer runs in a J2EE application server, you can tell Spring to use the application server’s transaction manager, as in Listing 4:

Listing 4. Transaction manager configuration
<tx:jta-transaction-manager/>

This configuration would make Spring automatically pick up your application server’s transaction manager. In a Java SE environment, you could configure Spring to use the JPA API’s transaction demarcation facilities, as in Listing 5:

Listing 5. JPA transaction manager declaration
<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
  <property name="entityManagerFactory" ref="emFactory"/>
</bean>

This technique makes it possible to implement a service layer for use in EJB and Web tiers, or in a Java SE environment, without any code modifications. Testing the service layer outside the container also becomes very easy, which can significantly speed up the development cycle.

Another issue that can have a negative effect on service layer reusability is your exception handling strategy. You should handle exceptions coherently throughout the application. Typically you should not be forced to handle system errors but it should still be possible to process these if required. Often, data access APIs such as JDBC and JPA provide only very generic information about the exception condition, and do not allow the specific cause to be effectively identified. When a service layer uses a data access layer for accessing data stored in a certain enterprise information system, the service layer should not allow any information-system-specific exceptions to be propagated to upper layers.

Spring defines a coherent data access exception class hierarchy (Figure 12) that you can use as a basis for your service- and DAO-layer exceptions. Spring’s data access facilities automatically translate data-access exceptions into this exception class hierarchy. You can also extend this hierarchy with your own, more specialized exceptions, if needed. As mentioned previously, the exceptions in this hierarchy are unchecked. (View a larger version of this diagram.

Figure 12. Spring data access exception hierarchy (diagram from Spring reference documentation)
Spring reference documentation diagram

DAO support

A key concept of the JPA is that of a persistence context. You interact with a persistence context that lets you execute data access operations against a relational database. The persistence context is responsible for synchronizing the managed object state with the entity state stored in the database. You can access a persistence context via the EntityManager interface.

When the application runtime environment doesn’t support container-managed persistence contexts, the context lifecycle needs to be explicitly managed by the application. This can be a bit cumbersome, but fortunately Spring lends a hand here. The line in Listing 6 configures the Spring container with a set of bean post-processors that enhance managed beans under the covers:

Listing 6. Configuring the Spring container
<context:annotation-config/>

Among other things, the processors handle annotations in Spring beans,which makes it possible to inject a JPA persistence context into a Java class, such as a DAO implementation class like Listing 7:

Listing 7. JPA persistence context
@PersistenceContext
private EntityManager em;

This annotation makes Spring inject a transactional persistence context into the class instances. Since Spring simulates having a container-managed persistence context with POJOs, the DAO implementation layer becomes a lot cleaner. Note that in Java EE 5 you can only inject the persistence context into managed objects such as EJBs, not POJOs.

You can also tell Spring to translate data access exceptions for data access implementation classes, simply by adding the line in Listing 8 to Spring’s configuration file:

Listing 8. Translating data access exceptions
<bean class="org.springframework.dao.annotation.
      PersistenceExceptionTranslationPostProcessor"/>

Additionally, the DAO implementation classes have to be annotated with @Repository.

JavaServer Faces support

JSF has a mechanism for customizing the resolution of top-level variables in JSF EL expressions. Spring comes with a variable resolver implementation class that lets you reference Spring managed beans in JSF expressions. For each top-level variable name, the class first checks if a bean by that ID exists in the Spring container. If a bean exists, the class resolves the reference to this bean. Otherwise it consults the JSF default variable resolver. Using this resolver lets you inject Spring beans into JSF managed beans, or reference Spring beans in EL expressions in JSF pages. Listing 9 shows how to configure the variable resolver in the faces-config.xml file:

Listing 9. Configuring the variable resolver
<variable-resolver>
	org.springframework.web.jsf.DelegatingVariableResolver
</variable-resolver>

Accessing EJB beans

Using EJB session beans can result in quite verbose code on the caller side. A typical code fragment for looking up and calling a service method implemented as a remote stateless session bean can look like Listing 10:

Listing 10. Verbose code for EJB session bean
try {
  Context ctx = new InitialContext();
  Object homeObj = ctx.lookup("java:comp/env/ejb/EventServiceEJB");
  EventServiceEjbHome eventHome = (EventServiceEjbHome)
    PortableRemoteObject.narrow(homeObj, EventServiceEjbHome.class);
  EventServiceEjb eventService = eventHome.create();
  String msg = eventService.getGreeting("world");
} catch (NamingException e) {
  // handle exception
} catch (CreateException e) {
  // handle exception
} catch (RemoteException e) {
  // handle exception
}

The lookup code and exception handling are the main contributors to the verbosity of Listing 10. A typical solution to overcome these issues, is to implement the ServiceLocator pattern, where you move the lookup code to a separate class that the service user calls to get a reference to the service implementation class. The ServiceLocator can also translate the checked exceptions (that get thrown during lookup or creation of the bean) into unchecked exceptions. You would still need to handle RemoteException exceptions when using the EJB.

Again, Spring offers a nice solution to this problem. You can specify the EJB bean as a Spring bean in the Spring configuration, and then inject them using Spring’s normal dependency injection methods as a collaborator to any other Spring bean.

Listing 11. Declaring a remote stateless session bean as a Spring bean
<jee:remote-slsb id="eventServiceEjb"
 jndi-name="java:comp/env/ejb/EventServiceEJB"
 business-interface="events.service.EventService"
 home-interface="events.ejb.EventServiceEjbHome"/>

If the target field type specifies the EJB business interface type, the caller does not need to be concerned with any of the specifics of calling an EJB. Spring catches exceptions such as NamingException and RemoteException, and re-throws them as unchecked exceptions, which you are free to handle explicitly. Spring can also catch exceptions thrown during business method calls by injecting a reference to a proxy object instead of the actual EJB remote interface stub. This way the proxy can intercept calls to the EJB and translate exceptions as appropriate. Remote method calls still use call-by-value semantics of which you certainly need to be aware.


Conclusion

Spring can simplify many traditional J2EE programming challenges to make you more productive. It’s easy to introduce into your existing code base or in a greenfield application, due to its non-intrusive design. You can also pick and choose which facilities to deploy; it’s not mandatory to use the whole stack if just a small piece is required. Spring also integrates well with WebSphere Application Server and OpenJPA. This article showed how to use just a few of Spring’s features, so the reader is encouraged to explore other features that might be beneficial to your projects, starting with the resources section below.


Download

DescriptionNameSize
Sample Web applicationevents.zip37KB

Resources

Learn

Get products and technologies

Comments

developerWorks: Sign in

Required fields are indicated with an asterisk (*).


Need an IBM ID?
Forgot your IBM ID?


Forgot your password?
Change your password

By clicking Submit, you agree to the developerWorks terms of use.

 


The first time you sign into developerWorks, a profile is created for you. Information in your profile (your name, country/region, and company name) is displayed to the public and will accompany any content you post, unless you opt to hide your company name. You may update your IBM account at any time.

All information submitted is secure.

Choose your display name



The first time you sign in to developerWorks, a profile is created for you, so you need to choose a display name. Your display name accompanies the content you post on developerWorks.

Please choose a display name between 3-31 characters. Your display name must be unique in the developerWorks community and should not be your email address for privacy reasons.

Required fields are indicated with an asterisk (*).

(Must be between 3 – 31 characters.)

By clicking Submit, you agree to the developerWorks terms of use.

 


All information submitted is secure.

Dig deeper into WebSphere on developerWorks


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=1
Zone=WebSphere, Open source
ArticleID=348185
ArticleTitle=Using Spring and OpenJPA with WebSphere Application Server
publish-date=10292008