Jon, this is great!

Very interesting technique on getting the OpenEJB TransactionManager plugged into Spring. I suppose that is one of the tweaks that are required for anything that's a subclass of AbstractTransactionalSpringContextTests?

Hopefully I can get the doc updated in the next day or two.

Thank you very much!

-David


On Jun 16, 2008, at 4:52 PM, Jon Carrera wrote:



Here are the results i got after trying out all spring abstract support
classes for JUnit :




Spring Test Superclass
Test result
Problem


org.springframework.test.AbstractDependencyInjectionSpringContextTests
Pass
 


org.springframework.test.AbstractTransactionalSpringContextTests
Pass
 


org.springframework.test.AbstractSingleSpringContextTests
Pass
 


org .springframework .test.AbstractTransactionalDataSourceSpringContextTests
Pass
 


org .springframework .test.annotation.AbstractAnnotationAwareTransactionalTests
Pass
 


org.springframework.test.jpa.AbstractJpaTests
Fail
ClassNotFoundException - Apparently a problem with the class loader
OrmXmlOverridingShadowingClassLoader




Here's my sample test case:



public class UserEaoTest extends AbstractTransactionalSpringContextTests {

        private GenericEao userEao;

        protected String[] getConfigLocations() {
       setAutowireMode(AUTOWIRE_BY_NAME);

       return new String[] {
               "classpath*:/applicationContext-eao.xml"
           };
   }

        public void testCRUD() throws Exception{
                User user = new User();
                user.setName("John");
                user.setLastName("Doe");
                user.setStatus(new Short("1"));

                //Test create
                user = userEao.save(user);
                assertNotNull("Create failed...", user.getUserId());

                Long userId = user.getUserId();
                user = null;

                //Test read
                try {
                        user = userEao.get(userId);
                } catch (RuntimeException e) {
                        fail("Read failed...");
                }
                assertNotNull(user);

                //Test update
                user.setStatus(new Short("2"));
                userEao.save(user);
                assertEquals("Update failed...", 
userEao.get(userId).getStatus(),new
Short("2"));

                //Test delete
                user = null;
                userEao.remove(userId);
                try {
                        user = userEao.get(userId);
                } catch (RuntimeException e) {
                        assertNull(user);
                }
        }

        //Injected by Spring
        public void setUserEao(GenericEao userEao) {
                this.userEao = userEao;
        }
}



The test case unit-tests a simple EAO that is managed by spring. Notice that
depending on the spring abstract superclass, the test case may require
subtle changes.



The spring application context file has the following definitions:



        <!-- Initializes openEjb context-->
        <bean id="openEjbContext"
                
class="net.quarksoft.arquetipo.eao.support.OpenEjbFactoryBean">
                <property name="jndiEnvironment">
                        <props>
                                <prop 
key="myDs">new://Resource?type=DataSource</prop>
<prop key="myDs.JdbcDriver">com.mysql.jdbc.Driver</ prop>
                                <prop key="myDs.JdbcUrl">
                                
jdbc:mysql://localhost/midastest? createDatabaseIfNotExist =true&useUnicode=true&characterEncoding=utf-8
                                </prop>
                                <prop 
key="myDs.UserName">root</prop>
                                <prop key="myDs.Password"></prop>
                        </props>
                </property>
        </bean>

<!-- Obtains EntityManagerFactory from OpenEjb context via a custom bean
factory -->
        <bean id="entityManagerFactory"
class ="net.quarksoft.arquetipo.eao.support.EntityManagerFactoryBean">
                        <property name="context" ref="openEjbContext" />
        </bean>

<!-- Obtains TransactionManager from OpenEjb context via a custom bean
factory-->
        <bean id="transactionManagerFactory"
class = "net .quarksoft.arquetipo.eao.support.TransactionManagerFactory"></ bean>

        <!-- Wraps OpenEjb's TransactionManager with spring's
JtaTransactionManager so that it can be injected to spring's abstract
transactional tests -->
        <bean id="transactionManager"
class="org.springframework.transaction.jta.JtaTransactionManager">
                        <property name="transactionManager"
ref="transactionManagerFactory"></property>
        </bean>

        <!-- bean post-processor for JPA annotations -->
        <bean
class = "org .springframework .orm.jpa.support.PersistenceAnnotationBeanPostProcessor"
/>

        <!-- My persistent bean definition -->
        <bean id="userEao"
                        
class="net.quarksoft.arquetipo.eao.jpa.GenericEaoJpa">
<constructor-arg value="net.quarksoft.arquetipo.model.User" / >
        </bean>



These are the custom bean factories used to obtain the required resources
from OpenEjb context:



/**
* Custom spring factory to initialize OpenEjb context
*
*/
public class OpenEjbFactoryBean implements FactoryBean {

        private Properties properties = new Properties();

        public OpenEjbFactoryBean() {
            properties.put(Context.INITIAL_CONTEXT_FACTORY,
"org.apache.openejb.client.LocalInitialContextFactory");
        }

        public Properties getJndiEnvironment() {
            return properties;
        }

        public void setJndiEnvironment(Properties properties) {
            this.properties.putAll(properties);
        }

        public Object getObject() {
            try {
                return new InitialContext(properties);
            } catch (NamingException e) {
                throw new RuntimeException(e);
            }
        }

        public Class getObjectType(){
            return Context.class;
        }

        public boolean isSingleton() {
            return true;
        }
    }



/**
* Obtains an instance of EntityManagerFactory from the openEjb context
*/
public class EntityManagerFactoryBean implements FactoryBean {
        private Context context;

        public Object getObject() {
                try {
                        ResourceLocal bean = (ResourceLocal) context
                                        .lookup("ResourceBeanLocal");
                        return bean.getEntityManagerFactory();
                } catch (NamingException e) {
                        throw new RuntimeException(e);
                }
        }

        public Class getObjectType() {
                return EntityManagerFactory.class;
        }

        public boolean isSingleton() {
                return true;
        }

        public Context getContext() {
       return context;
   }

   public void setContext(Context context) {
       this.context = context;
   }

}



/**
* Obtains an instance of javax.transaction.TransactionManager from
* the OpenEjb context
*/
public class TransactionManagerFactory implements FactoryBean {

        public Object getObject() throws Exception {
                return org.apache.openejb.OpenEJB.getTransactionManager();
        }

        public Class getObjectType() {
                return TransactionManager.class;
        }

        public boolean isSingleton() {
                return true;
        }

}



The persistence.xml definition:



        <persistence-unit name="ApplicationEntityManager"
                transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</ provider>
                <jta-data-source>myDs</jta-data-source>
                <class>myapp.model.User</class>
                <properties>
                        <property name="hibernate.dialect"
                                value="org.hibernate.dialect.HSQLDialect" />
                        <property 
name="hibernate.transaction.manager_lookup_class"

value="org.apache.openejb.hibernate.TransactionManagerLookup"/>
                </properties>
        </persistence-unit>



Finally, the persistent Entity and the generic implementation of the EAO:



@Entity
@Table(name = "user")
public class User implements Serializable{

        private static final long serialVersionUID = -8787893234778745429L;

        private Long userId;
        private String name;
        private String lastName;
        private Short status;

        @Column(name = "lastName", length = 30)
        public String getLastName() {
                return lastName;
        }
        public void setLastName(String lastName) {
                this.lastName = lastName;
        }

        @Column(name = "name", length = 30)
        public String getName() {
                return name;
        }
        public void setName(String name) {
                this.name = name;
        }

        @Column(name = "status")
        public Short getStatus() {
                return status;
        }
        public void setStatus(Short status) {
                this.status = status;
        }

        @Id
        @GeneratedValue (strategy=GenerationType.AUTO)
        @Column(name = "userId")
        public Long getUserId() {
                return userId;
        }
        public void setUserId(Long userId) {
                this.userId = userId;
        }
}




public class GenericEaoJpa implements GenericEao {
        protected final Log log = LogFactory.getLog(getClass());
   private Class persistentClass;

 //Injected by spring postprocessor
   @PersistenceContext
   private EntityManager entityManager;

        public GenericEaoJpa(Class  persistentClass) {
                super();
                this.persistentClass = persistentClass;
        }

        public boolean exists(Serializable id) {
                E entity = entityManager.find(persistentClass, id);
                return entity == null? false:true;
        }

        public E get(PK id) {
                E entity = entityManager.find(persistentClass, id);
                if (entity == null) {
log.warn("Uh oh, '" + this.persistentClass + "' object with id
'" + id + "' not found...");
throw new ObjectRetrievalFailureException(this.persistentClass,
id);
       }

       return entity;
        }

        public List getAll() {
                return entityManager.createQuery("select " +
persistentClass.getName()).getResultList();
        }

        public void remove(PK id) {
                E entity = get(id);
                entityManager.remove(entity);

        }

        public E save(E entity) {
                entityManager.persist(entity);
                return entity;
        }
}



Hope this helps.



-Jon

--
View this message in context: 
http://www.nabble.com/Help-with-OpenEJB3-and-Spring-IoC-tp17674222p17875549.html
Sent from the OpenEJB User mailing list archive at Nabble.com.

Reply via email to