Overview

Configuration

Servers

Integrations

Community

Related Projects

Index

Feeds

 

OpenEJB 3.1 or later required

This example shows how to combine Spring, OpenEJB and Hibernate using the integration code provided by OpenEJB. Here, OpenEJB is used as an embeddable EJB container inside of Spring. See the Spring page for details.

We use the basic Movie example and expand it to include more objects to demonstrate both Spring beans, EJB Session beans, and JPA persistent objects in one application. The premise of the example is a Cineplex that has a number of Theaters (viewing screens), each playing a number of Movies. The basic object layout is as follows:

Object Type Description
CineplexImpl @Stateless Shows the use of @Resource to have Spring beans injected. Specifically, the Theaters Spring bean
Theaters Spring bean Simple wrapper object injected into CineplexImpl
Theater Spring bean Shows that EJBs can be injected into Spring beans. Uses both the Movies EJB and the Movie JPA objects
MoviesImpl @Stateful Wraps a JPA EntityManager and provides transactional access to the persistent Movie objects
Movie @Entity Basic JPA bean that is used both by Spring beans and EJBs. The same Movie object as in all the other persistence related examples.
AvailableMovies Spring bean Simple object used as a clever way to seed the EntityManager (and really, the database) with persistent Movie objects

Required jars

To setup the integration you'll need:

  1. The standard OpenEJB 3.1 libraries
  2. The openejb-spring-3.1.jar or later
  3. Spring 2.5 or other (any version should work)

In Maven2 this can be done by adding the following dependencies to your pom.xml

<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>openejb-core</artifactId>
  <version>3.1.2-SNAPSHOT</version>
</dependency>
<dependency>
  <groupId>org.apache.openejb</groupId>
  <artifactId>openejb-spring</artifactId>
  <version>3.1.2-SNAPSHOT</version>
</dependency>
<dependency>
  <groupId>org.springframework</groupId>
  <artifactId>spring</artifactId>
  <version>2.5.5</version>
</dependency>

For other environments, you can simply download an openejb-3.1.zip or later and include all the jars under the lib/ directory in your classpath. Then download and add the openejb-spring-3.1.jar along with your Spring jars.

The Spring xml

Bootstrapping and Configuring OpenEJB is fairly simple.

<!--
Required:  Set up a TransactionManager for use by OpenEJB or Spring.
The Spring PlatformTransactionManager may be used instead.

In future versions this will not be a required step.
-->
<bean name="TransactionManager" class="org.apache.geronimo.transaction.manager.GeronimoTransactionManager"/>


<!--
Required:  Set up a SecurityService for use by OpenEJB.
In future versions this will not be a required step.
-->
<bean name="SecurityService" class="org.apache.openejb.core.security.SecurityServiceImpl"/>


<!--
Loads the EJBs from the classpath just as when embedding OpenEJB via
the org.apache.openejb.client.LocalInitialContextFactory.  All the discovered
EJBs are imported into this context and available for injection here.
-->
<bean name="classPathApplication" class="org.apache.openejb.spring.ClassPathApplication"/>

As well, you can optionally declare any resources or containers. Anything declarable as a <Resource> or <Container> in the openejb.xml can instead be declared in the Spring xml file as shown here.

<bean name="MovieDatabase" class="org.apache.openejb.spring.Resource">
  <property name="type" value="DataSource"/>
  <property name="properties">
    <props>
      <prop key="JdbcDriver">org.hsqldb.jdbcDriver</prop>
      <prop key="JdbcUrl">jdbc:hsqldb:mem:moviedb</prop>
    </props>
  </property>
</bean>

<bean name="MovieDatabaseUnmanaged" class="org.apache.openejb.spring.Resource">
  <property name="type" value="DataSource"/>
  <property name="properties">
    <props>
      <prop key="JdbcDriver">org.hsqldb.jdbcDriver</prop>
      <prop key="JdbcUrl">jdbc:hsqldb:mem:moviedb</prop>
      <prop key="JtaManaged">false</prop>
    </props>
  </property>
</bean>

And finally our Spring beans.

<bean name="AvailableMovies" class="org.superbiz.spring.AvailableMovies">
  <property name="movies">
    <list>
      <bean class="org.superbiz.spring.Movie">
        <property name="title" value="Fargo"/>
        <property name="director" value="Joel Coen"/>
        <property name="year" value="1996"/>
      </bean>
      <bean class="org.superbiz.spring.Movie">
        <property name="title" value="Reservoir Dogs"/>
        <property name="director" value="Quentin Tarantino"/>
        <property name="year" value="1992"/>
      </bean>
      <bean class="org.superbiz.spring.Movie">
        <property name="title" value="The Big Lebowski"/>
        <property name="director" value="Joel Coen"/>
        <property name="year" value="1998"/>
      </bean>
      <bean class="org.superbiz.spring.Movie">
        <property name="title" value="You, Me and Dupree"/>
        <property name="director" value="Anthony Russo"/>
        <property name="year" value="2006"/>
      </bean>
      <bean class="org.superbiz.spring.Movie">
        <property name="title" value="Wedding Crashers"/>
        <property name="director" value="David Dobkin"/>
        <property name="year" value="2005"/>
      </bean>
      <bean class="org.superbiz.spring.Movie">
        <property name="title" value="Zoolander"/>
        <property name="director" value="Ben Stiller"/>
        <property name="year" value="2001"/>
      </bean>
      <bean class="org.superbiz.spring.Movie">
        <property name="title" value="Shanghai Noon"/>
        <property name="director" value="Tom Dey"/>
        <property name="year" value="2000"/>
      </bean>
    </list>
  </property>
</bean>

<bean name="theater1" class="org.superbiz.spring.Theater">
  <property name="nowPlaying">
    <list>
      <value>Fargo</value>
      <value>Reservoir Dogs</value>
      <value>The Big Lebowski</value>
    </list>
  </property>
</bean>

<bean name="theater2" class="org.superbiz.spring.Theater">
  <property name="nowPlaying">
    <list>
      <value>You, Me and Dupree</value>
      <value>Wedding Crashers</value>
      <value>Zoolander</value>
      <value>Shanghai Noon</value>
    </list>
  </property>
</bean>

<bean name="theaters" class="org.superbiz.spring.Theaters">
  <property name="theaters">
    <list>
      <ref bean="theater1"/>
      <ref bean="theater2"/>
    </list>
  </property>
</bean>
Don't forget
<context:annotation-config/>

It allows various annotations to be detected in bean classes: Spring's @Required and @Autowired, as well as JSR 250's @PostConstruct, @PreDestroy and @Resource (if available), JAX-WS's @WebServiceRef (if available), EJB3's @EJB (if available), and JPA's @PersistenceContext and @PersistenceUnit (if available). Alternatively, you may choose to activate the individual BeanPostProcessors for those annotations.

The Code

In efforts to keep the example page somewhat short, we'll show just three beans, each demonstrating a particular relationship.

The first is the CineplexImpl EJB which shows EJB -> Spring.

@Stateless
public class CineplexImpl implements Cineplex {

    /**
     * The Theaters Spring bean will be injected
     */
    @Resource
    private Theaters theaters;

    public List<Theater> getTheaters() {
        return theaters.getTheaters();
    }
}

The second is the Theater Spring bean which shows Spring -> EJB.

/**
 * Spring bean that references the Movies EJB and the Movie JPA bean.
 * <p/>
 * This bean shows that Spring beans can have references to EJBs.
 */
public class Theater {

    /**
     * The Movies @Stateless EJB
     */
    private final Movies movies;

    private final List<Movie> nowPlaying = new ArrayList<Movie>();

    /**
     * The Movies EJB is passed in on the constructor which
     * guarantees we can use it in the setNowPlaying method.
     *
     * @param movies
     */
    @Autowired
    public Theater(Movies movies) {
        this.movies = movies;
    }

    /**
     * For every title in the list we will use the Movies EJB
     * to lookup the actual Movie JPA object.
     *
     * @param nowPlaying
     * @throws Exception
     */
    public void setNowPlaying(List<String> nowPlaying) throws Exception {
        for (String title : nowPlaying) {
            this.nowPlaying.add(movies.getMovieByTitle(title));
        }
    }

    public List<Movie> getMovies() throws Exception {
        return nowPlaying;
    }
}

The last is the AvailableMovies Spring bean which Shows Spring -> EJB -> JPA

/**
 * This is a simple Spring bean that we use as an easy way
 * to seed the example with a list of persistent Movie objects
 * <p/>
 * The individual Movie objects are constructed by Spring, then
 * passed into the Movies EJB where they are transactionally
 * persisted with the EntityManager.
 */
public class AvailableMovies {

    @EJB
    private Movies moviesEjb;

    private List<Movie> movies;

    @PostConstruct
    public void construct() throws Exception {
        for (Movie movie : movies) {
            moviesEjb.addMovie(movie);
        }
    }

    public List<Movie> getMovies() {
        return movies;
    }

    public void setMovies(List<Movie> movies) {
        this.movies = movies;
    }
}

The TestCase

The JUnit TestCase uses a ClassPathXmlApplicationContext to load the Spring ApplicationContext. Anything that loads your Spring xml file should work fine. The following code would work a plain java app as well.

public class MoviesTest extends TestCase {

    public void test() throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("movies.xml");

        // Can I lookup the Cineplex EJB via the Spring ApplicationContext
        Cineplex cineplex = (Cineplex) context.getBean("CineplexImplLocal");
        assertNotNull(cineplex);

        // Does the Cineplex EJB have a reference to the Theaters Spring bean?
        List<Theater> theaters = cineplex.getTheaters();
        assertNotNull(theaters);

        assertEquals(2, theaters.size());

        Theater theaterOne = theaters.get(0);
        Theater theaterTwo = theaters.get(1);


        // Were the Theater Spring beans able to use the
        // Movies EJB to get references to the Movie JPA objects?
        List<Movie> theaterOneMovies = theaterOne.getMovies();
        assertNotNull(theaterOneMovies);

        List<Movie> theaterTwoMovies = theaterTwo.getMovies();
        assertNotNull(theaterTwoMovies);

        // The first Theater should have used the Movies EJB
        // to get a reference to three Movie JPA objects
        assertEquals(3, theaterOneMovies.size());

        assertEquals("Fargo", theaterOneMovies.get(0).getTitle());
        assertEquals("Reservoir Dogs", theaterOneMovies.get(1).getTitle());
        assertEquals("The Big Lebowski", theaterOneMovies.get(2).getTitle());

        // The second Theater should have used the Movies EJB
        // to get a reference to four Movie JPA objects

        assertEquals(4, theaterTwoMovies.size());

        assertEquals("You, Me and Dupree", theaterTwoMovies.get(0).getTitle());
        assertEquals("Wedding Crashers", theaterTwoMovies.get(1).getTitle());
        assertEquals("Zoolander", theaterTwoMovies.get(2).getTitle());
        assertEquals("Shanghai Noon", theaterTwoMovies.get(3).getTitle());
    }
}

Running

The source for this example can be downloaded from svn via:

$ svn co http://svn.apache.org/repos/asf/openejb/trunk/openejb3/examples/spring-integration

Then, in the "spring-integration" directory, run:

$ mvn clean install

Which should create output like the following.

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running org.superbiz.spring.MoviesTest
log4j:WARN No appenders could be found for logger (org.springframework.context.support.ClassPathXmlApplicationContext).
log4j:WARN Please initialize the log4j system properly.
Apache OpenEJB 3.1    build: 20081009-03:31
http://openejb.apache.org/
INFO - openejb.home = /Users/dblevins/work/openejb3/examples/spring-integration
INFO - openejb.base = /Users/dblevins/work/openejb3/examples/spring-integration
INFO - Configuring Service(id=Default JDK 1.3 ProxyFactory, type=ProxyFactory, provider-id=Default JDK 1.3 ProxyFactory)
INFO - Configuring Service(id=MovieDatabase, type=Resource, provider-id=Default JDBC Database)
INFO - Configuring Service(id=MovieDatabaseUnmanaged, type=Resource, provider-id=Default JDBC Database)
INFO - Found EjbModule in classpath: /Users/dblevins/work/openejb3/examples/spring-integration/target/classes
INFO - Beginning load: /Users/dblevins/work/openejb3/examples/spring-integration/target/classes
INFO - Configuring enterprise application: classpath.ear
INFO - Configuring Service(id=Default Stateless Container, type=Container, provider-id=Default Stateless Container)
INFO - Auto-creating a container for bean CineplexImpl: Container(type=STATELESS, id=Default Stateless Container)
INFO - Auto-linking resource-ref 'org.superbiz.spring.CineplexImpl/theaters' in bean CineplexImpl to Resource(id=theaters)
INFO - Configuring Service(id=Default Stateful Container, type=Container, provider-id=Default Stateful Container)
INFO - Auto-creating a container for bean Movies: Container(type=STATEFUL, id=Default Stateful Container)
INFO - Configuring PersistenceUnit(name=movie-unit, provider=org.hibernate.ejb.HibernatePersistence)
INFO - Enterprise application "classpath.ear" loaded.
INFO - Assembling app: classpath.ear
INFO - PersistenceUnit(name=movie-unit, provider=org.hibernate.ejb.HibernatePersistence)
INFO - Jndi(name=CineplexImplLocal) --> Ejb(deployment-id=CineplexImpl)
INFO - Jndi(name=MoviesLocal) --> Ejb(deployment-id=Movies)
INFO - Created Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container)
INFO - Created Ejb(deployment-id=CineplexImpl, ejb-name=CineplexImpl, container=Default Stateless Container)
INFO - Deployed Application(path=classpath.ear)
INFO - Exported EJB Movies with interface org.superbiz.spring.Movies to Spring bean MoviesLocal
INFO - Exported EJB CineplexImpl with interface org.superbiz.spring.Cineplex to Spring bean CineplexImplLocal
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 3.141 sec

Results :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

   

Apache OpenEJB is an project of The Apache Software Foundation (ASF) - Website Privacy Policy -
Site Powered by Atlassian Confluence .
[ edit ]