Combining the power of EJB 3 and Spring

In addition to using JPA with Spring, you may combine the flexibility of Spring beans with the power of EJB 3 in your applications. You have two options. You can use the power of Spring—POJO injection, AOP features, etc.—by developing Spring-enabled EJB applications, or you can invoke an EJB from a Spring bean. At the time of this writing, Spring 2.0 has no documented support for EJB 3 session beans, but we found some ways to make EJB 3 beans work with Spring beans and in this section we’ll reveal our discoveries.

In this section you’ll see two ways you can combine power of EJB 3 components and Spring beans. First you’ll learn about using Spring from EJB 3 components; then we’ll show you how to access an EJB 3 session bean from a Spring bean.

Developing Spring-enabled EJBs

Let’s say you want to use declarative transactions, timers, security, and the web services features of EJB in your applications, but you also want to leverage the POJO injection, AOP, and JpaTemplate features of Spring 2.0. Spring provides several support classes, listed in table 16.3, that you can use to integrate EJBs. Note that these are the classes provided for use with EJB 2, and we expect there will be several changes in these classes to be used with EJB 3. However, you can still use these abstract classes with EJB 3 beans.

The abstract classes provide access to the Spring bean factory, and you have to implement the onEjbCreate method in your EJB class to retrieve a Spring bean.


Table 16.3 Spring support classes for building Spring-enabled EJBs

Support Class

Purpose

tmp4B-27

Used for Spring-enabled stateless session beans

tmp4B-28

Used for Spring-enabled stateful session beans

tmp4B-29

Used for Spring-enabled JMS message-driven beans

tmp4B-30

Used for Spring-enabled connector-based MDBs

In ActionBazaar we want to use Spring with session beans. This means that the BidServiceBean we developed in section 16.1 is used by the PlaceBid EJB, as shown in figure 16.2.

The BidServiceBean is defined as a Spring bean using a Spring configuration file named actionBazaar-service.xml as follows:

tmp4B-31_thumb

When an EJB instance is created, a Spring bean factory is automatically created and is made available to the EJB. While using this approach, you typically use the EJB as a fagade and delegate the task to Spring beans.

Listing 16.3 shows the PlaceBid EJB developed as a Spring-enabled stateless session bean. In this example, the PlaceBid EJB acts as a fagade and delegates the actual business logic to the BidServiceBean.

You can combine the power of Spring and EJB 3 by developing a Spring-enabled session bean. You can use the declarative transaction, security, and web services features of EJB 3 with the POJO injection and JpaTemplate features of Spring.

Figure 16.2 You can combine the power of Spring and EJB 3 by developing a Spring-enabled session bean. You can use the declarative transaction, security, and web services features of EJB 3 with the POJO injection and JpaTemplate features of Spring.

Listing 16.3 Spring-enabled stateless PlaceBid EJB

Listing 16.3 Spring-enabled stateless PlaceBid EJB

In listing 16.3 the bean class extends the Spring support class in the (org.spring-framework.ejb.support.AbstractStatelessSessionBean) package Q. Note that the EJB bean cannot inherit from another bean or class because Java does not support multiple inheritances.

The BidServiceBean POJO is defined as an instance variable Q. When a Place-Bid EJB instance is created, the onEjbCreate method is invoked and an instance of BidServiceBean is retrieved d and stored in the POJO that we defined Q. The business method delegates the task to the BidServiceBean when it is invoked O.

Now you must be wondering how the Spring bean factory is created and how the Spring configuration is provided. Under the covers, when an EJB instance is created it performs a JNDI lookup to locate the path (java:comp/env/ejb/Bean-FactoryPath) for the bean factory. Therefore, you have to define the following environment variable in the EJB deployment descriptor for the EJB:

tmp4B-34_thumb

The env-entry-value for the ejb/BeanFactoryPath environment variable is set to /actionBazaar-service.xml.

After you package the EJB and Spring configuration file, you should be able to invoke the EJB, and internally it will use Spring beans to perform the intended task.

Using session beans from Spring beans

Perhaps by now you’ve grown fond of EJB 3 and worked with it in your application. Some of your other application modules happen to use Spring. What you’d like to do is reuse the business logic you’ve developed in your EJBs by incorporating it into your Spring component, as shown in figure 16.3. In this section we’ll show you how to inject instances of session beans into your Spring beans.

Suupose you have a session bean named ItemManager:

You can access a session bean from a Spring bean and reuse the business logic.

Figure 16.3 You can access a session bean from a Spring bean and reuse the business logic.

tmp4B-36_thumb

tmp4B-37_thumb

You want to use the ItemManager session bean in the ItemServiceBean, which is a Spring POJO (see listing 16.4).

Listing 16.4 A Spring POJO that uses an injected stateless session bean

Listing 16.4 A Spring POJO that uses an injected stateless session bean

In listing 16.4 you will see no difference in using a POJO because EJB 3 session beans are also POJOs. In the Spring bean, we’ve defined an instance variable for the EJB interface ItemManager Q and we use setter injection to inject an instance of the EJB object C and invoke a method on the EJB d.

You must be wondering where the actual magic happens. We aren’t doing a JNDI lookup, and we’re not using the @EJB annotation to inject an EJB object. The real magic occurs in wiring the EJB in the Spring configuration, as shown in listing 16.5. Spring has factory classes for wiring invocation of EJB 2.1 session beans. Fortunately, you don’t need those and you can use the JndiObject-FactoryBean.

Listing 16.5 A Spring POJO that uses an injected stateless session bean

Listing 16.5 A Spring POJO that uses an injected stateless session bean

In listing 16.5 we define a bean instance that injects an EJB instance by looking it up in the JNDI Q when referenced by another bean instance ©.

If you are a big fan of the new Spring 2.0 configuration, then you’ll be tempted to use the following instead of JndiObjectFactoryBean. Go ahead; indulge your temptation.

tmp4B-40_thumb

Unlike in EJB 2, there is no difference between invoking remote or local EJBs in EJB 3, and the configuration will be identical for both local and remote session beans.

Summary

This topic explained that even though EJB 3 is a specification and Spring is a framework, you can use them together successfully to build flexible, powerful applications. You can use parts of the EJB 3 implementation, or all of it, within your Spring applications. Spring can simplify the use of both EJB 3 and JPA, but at the price of foraging through Spring’s XML configuration files. You learned how to develop a Spring-enabled EJB (session bean or MDB) and leverage the power of Spring within your EJB components. Similarly, you can access an EJB 3 session bean from your Spring bean and reuse your business logic.

EJB 3 is a great framework for building enterprise Java applications, and it significantly improves developer productivity. It has some minor limitations, such as  support for POJO injection, and we hope that these limitations will be addressed in the next version of the specification. Throughout this topic we provided many best practices and tuning tips, and we trust you can use this information to effectively build your next application.

Next post:

Previous post: