Four Areas of Consideration when Migrating from EJB to Spring
Many Java Enterprise Edition (JEE) applications make use of the Enterprise Java Bean (EJB) architecture to encapsulate the business logic for enterprise applications. This works well whenever the application is expected to run within the application server for which the application was developed. Unfortunately, converting the application to run within a different application can be challenging. Also, many application servers are slow to adopt the latest JEE specifications, often forcing developers to wait one or more years in order to use a particular set of features. For these reasons, it may be more advantageous to move to an architecture such as Spring (http://www.springsource.org) to meet the same objectives.
Four Areas of Consideration when Migrating from EJB to Spring
When it comes to inversion of control and dependency injection, EJB3 and Spring provide analogous constructs, and converting from one to the other is mostly straight-forward. For example, change @Local to @Service and @EJB to @Resource – now stateless session beans are Spring component beans, and EJB dependencies are now Spring auto-wired dependencies. Although the conversion is mostly straightforward, there are four areas that in our experience presented a challenge and require careful consideration when transitioning an application from EJB 3 to Spring.
Authentication/Authorization
Spring Security is an add-on to Spring that provides a flexible means of authenticating and authorizing behavior for a user. The mechanism for storing a user principal in a SecurityContext is analogous to the SessionContext used by EJB3. Although not as simple as changing annotations, there a few things that can be done to minimize the aggravation of transitioning to Spring Security:
Pre-Authentication: If you already have container-managed authentication mechanism in place (ie JAAS), you can configure Spring Security to bypass its own authentication and use the principal created by the container. The container principal is copied to a new principal inside the Spring SecurityContext, and afterward the JEE-specific principal construct is no longer used.
Role names: The default convention for Spring Security is to use the prefix “ROLE_” for assigning and authorizing roles. You can either customize this or modify your role naming structure, depending on how complicated it is.
RunAs: Spring provides the RunAsManager construct, similar to @RunAs in EJB3, which grants temporary authority to a logged in user in order for method to be run which requires access the user doesn’t have.. In order for it work the @Secured method must contain two roles: the role granted to the user at authentication, and role named “RUN_AS_[SOMETHING]”, which the RunAsManager will grant to the user (ROLE_RUN_AS_[SOMETHING]) for the duration of the method.
Distributed Transaction Management
If you have both JDBC and JMS operations occurring in the same transaction, most likely you are using the built-in transaction (XA) support provided by your JEE container to make those transactions atomic. When moving the transaction handling away from the EJB container and into Spring, the choices for implementing distributed transactions are limited. The most straight-forward solution is to utilize a third party XA provider such as Atomikos (http://www.atomikos.com/ .) However, because Atomikos needs to manage its own connection pool, you lose the most basic benefit of a Java application server – database connection pooling.
It is a good idea to consider whether true XA transaction handling is required by your application. There is a significant amount of overhead that can be saved if, for example you can afford to have a message fail to send after a database update. This article provides a comprehensive discussion on techniques for achieving distributed transactions: http://www.javaworld.com/javaworld/jw-01-2009/jw-01-spring-transactions.html
Message Driven Beans
While Message Driven Beans are a built-in construct of EJB3, creating the same behavior with Spring is not so straight-forward. Spring provides the MessageListenerContainer construct to tie any Spring Bean to a message queue. This requires some extra XML configuration but it is pretty easy, and it can be made multi-threaded to improve performance. One caveat is that if the JMS message queue is actually a topic, the MessageListenerContainer can only be single-threaded.
You can overcome this limitation by making the processing of the message asynchronous, as opposed to creating multiple threads to receive the messages. As discussed below, Spring provides an easy way to cause any chosen method to execute in a new thread, with the ability to control the number of pooled threads. The only refactoring of code required is to move all of the processing logic to a new asynchronous method, and have onMessage() call that method.
Timers/Asynchronous Execution
It is common for an enterprise application to have a background-processing component, and EJB3 provides the @Schedule annotation to create a timer to execute code at specified times, similar to the UNIX cron facility… Spring provides analogous annotations in the form of the @Scheduled annotation. In addition, Spring provides the ability to execute code asynchronously via @Async. Once again there is minimal XML configuration required. The trick here is that if you are using method-level security or if you need the background process to run as a particular user/role, there is no equivalent to the @RunAs annotation in EJB3.
One solution is to programmatically “login” a user using the Spring Security API. This places a user into the SecurityContext which can then be accessed by any other method or by the @Secured method annotation. To be safe, also perform a “logout” in a “finally” block when the background logic is complete, so that if a pooled thread is reused you do not inadvertently grant another user an invalid authority.
Due to the variations in the EJB containers supported by an application server, it is often challenging to deploy a JEE application into a different application server. By using the Spring framework instead of EJB 3 a JEE application can be easily deployed in various application servers with little to no code modifications. This is definitely an advantage for applications that are required to support various application servers now or possibly in the future. Converting a JEE application from EJB 3 is relatively straightforward as long as care is taken in the areas of Authentication/Authorization, Distributed Transaction Management, Message Driven Beans, and Timers/Asynchronous Execution.
Authored by: Nate Jackson –Lead System Engineer, CollabraSpace Inc.