![]() |
![]() |
![]() |
![]() |
![]() |
|||||||||||||||||||||||||||||
![]() |
Home | Download | Lists | Issues | ![]() |
|||||||||||||||||||||||||||||||
![]() |
![]() |
![]() |
![]() |
![]() |
|||||||||||||||||||||||||||||
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:
Required jarsTo setup the integration you'll need:
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.3-SNAPSHOT</version> </dependency> <dependency> <groupId>org.apache.openejb</groupId> <artifactId>openejb-spring</artifactId> <version>3.1.3-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 xmlBootstrapping 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>
The CodeIn 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 TestCaseThe 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()); } } RunningThe 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 |
![]() |
||||||||||||||||||||||||||||||||
|
![]() |