Title: Spring Integration
Help us document this example! Source available in svn or git. Open a JIRA with patch or pull request
package org.superbiz.spring;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import java.util.List;
/**
* 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(name = "MoviesLocal")
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;
}
public void setMoviesEjb(Movies moviesEjb) {
this.moviesEjb = moviesEjb;
}
}
package org.superbiz.spring;
import java.util.List;
public interface Cineplex {
public List<Theater> getTheaters();
}
package org.superbiz.spring;
import javax.annotation.Resource;
import javax.ejb.Stateless;
import java.util.List;
@Stateless
public class CineplexImpl implements Cineplex {
/**
* The Theaters Spring bean will be injected
*/
@Resource
private Theaters theaters;
public List<Theater> getTheaters() {
return theaters.getTheaters();
}
}
package org.superbiz.spring;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
@Entity
public class Movie {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String director;
private String title;
private int year;
public Movie() {
}
public Movie(String director, String title, int year) {
this.director = director;
this.title = title;
this.year = year;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
}
package org.superbiz.spring;
import java.util.List;
public interface Movies {
void addMovie(Movie movie) throws Exception;
void deleteMovie(Movie movie) throws Exception;
List<Movie> getMovies() throws Exception;
Movie getMovieByTitle(String title) throws Exception;
}
package org.superbiz.spring;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.persistence.Query;
import java.util.List;
/**
* A normal Stateful EJB that uses a JPA EntityManager.
* <p/>
* We use this bean to transactionally wrap access to the
* EntityManager persist, remove, and query methods.
*/
@Stateful(name = "Movies")
public class MoviesImpl implements Movies {
@PersistenceContext(unitName = "movie-unit", type = PersistenceContextType.EXTENDED)
private EntityManager entityManager;
public void addMovie(Movie movie) throws Exception {
entityManager.persist(movie);
}
public void deleteMovie(Movie movie) throws Exception {
entityManager.remove(movie);
}
public List<Movie> getMovies() throws Exception {
Query query = entityManager.createQuery("SELECT m from Movie as m");
return query.getResultList();
}
public Movie getMovieByTitle(String title) throws Exception {
Query query = entityManager.createQuery("SELECT m from Movie as m where m.title = ?1");
query.setParameter(1, title);
return (Movie) query.getSingleResult();
}
}
package org.superbiz.spring;
import javax.inject.Inject;
import javax.inject.Named;
import java.util.ArrayList;
import java.util.List;
/**
* 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
*/
@Inject
@Named(value = "MoviesLocal")
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;
}
}
package org.superbiz.spring;
import java.util.List;
/**
* Injection of collections of Spring beans into an EJB
* is not yet supported, so this Spring bean exists to
* wrap the collection as an injectable object.
*/
public class Theaters {
private List<Theater> theaters;
public List<Theater> getTheaters() {
return theaters;
}
public void setTheaters(List<Theater> theaters) {
this.theaters = theaters;
}
}
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="1.0">
<persistence-unit name="movie-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>MovieDatabase</jta-data-source>
<non-jta-data-source>MovieDatabaseUnmanaged</non-jta-data-source>
<class>org.superbiz.spring.Movie</class>
<properties>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
</properties>
</persistence-unit>
</persistence>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.0.xsd">
<context:annotation-config/>
<!--
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.core.LocalInitialContextFactory. All the discovered
EJBs are imported into this context and available for injection here.
-->
<bean name="classPathApplication" class="org.apache.openejb.spring.ClassPathApplication"/>
<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>
<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>
<!--property name="moviesEjb">
<ref bean="MoviesLocal" />
</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>
</beans>
package org.superbiz.spring;
import junit.framework.TestCase;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import java.util.List;
public class MoviesTest extends TestCase {
public void test() throws Exception {
//Uncomment for debug logging
//org.apache.log4j.BasicConfigurator.configure();
System.setProperty("openejb.deployments.classpath.include", ".*/spring-integration.*");
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());
}
}
------------------------------------------------------- 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. log4j:WARN See http://logging.apache.org/log4j/1.2/faq.html#noconfig for more info. Apache OpenEJB 4.0.0-beta-1 build: 20111002-04:06 http://openejb.apache.org/ INFO - openejb.home = /Users/dblevins/examples/spring-integration INFO - openejb.base = /Users/dblevins/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/examples/spring-integration/target/classes INFO - Beginning load: /Users/dblevins/examples/spring-integration/target/classes INFO - Configuring enterprise application: /Users/dblevins/examples/spring-integration/classpath.ear WARN - Method 'lookup' is not available for 'javax.annotation.Resource'. Probably using an older Runtime. 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 'java:comp/env/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 "/Users/dblevins/examples/spring-integration/classpath.ear" loaded. INFO - Assembling app: /Users/dblevins/examples/spring-integration/classpath.ear INFO - PersistenceUnit(name=movie-unit, provider=org.hibernate.ejb.HibernatePersistence) - provider time 648ms INFO - Jndi(name=CineplexImplLocal) --> Ejb(deployment-id=CineplexImpl) INFO - Jndi(name=global/classpath.ear/spring-integration/CineplexImpl!org.superbiz.spring.Cineplex) --> Ejb(deployment-id=CineplexImpl) INFO - Jndi(name=global/classpath.ear/spring-integration/CineplexImpl) --> Ejb(deployment-id=CineplexImpl) INFO - Jndi(name=MoviesLocal) --> Ejb(deployment-id=Movies) INFO - Jndi(name=global/classpath.ear/spring-integration/Movies!org.superbiz.spring.Movies) --> Ejb(deployment-id=Movies) INFO - Jndi(name=global/classpath.ear/spring-integration/Movies) --> 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 - Started Ejb(deployment-id=Movies, ejb-name=Movies, container=Default Stateful Container) INFO - Started Ejb(deployment-id=CineplexImpl, ejb-name=CineplexImpl, container=Default Stateless Container) INFO - Deployed Application(path=/Users/dblevins/examples/spring-integration/classpath.ear) INFO - Exported EJB Movies with interface org.superbiz.spring.Movies to Spring bean MoviesLocal INFO - Exported EJB Movies with interface org.superbiz.spring.Movies to Spring bean global/classpath.ear/spring-integration/Movies!org.superbiz.spring.Movies INFO - Exported EJB CineplexImpl with interface org.superbiz.spring.Cineplex to Spring bean CineplexImplLocal INFO - Exported EJB CineplexImpl with interface org.superbiz.spring.Cineplex to Spring bean global/classpath.ear/spring-integration/CineplexImpl!org.superbiz.spring.Cineplex Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 2.407 sec Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0