I will speak today about how can we integrate Spring 4 with JBoss AS 7 (JBoss EAP 6).
Step 1 : Persistence.xml
The persistence.xml creation will depend on weather the Entity Manager will be managed by the container (JBoss so JPA 2.0) or by Spring (Where we will use JPA 2.1).
- JBoss manage the EntityManager: Use of JPA 2.0 with JTA transaction Type
In this case, the Transaction Type must be JTA. JBoss EAP 6.2 (based on JBoss 7.3) comes with JPA2.0 :1 2 3 4 5 6 7 8 9 10 11 12 13 14 | <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="module_enterprise" transaction-type="JTA"> <jta-data-source>java:/myDS</jta-data-source> <properties> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.hbm2ddl.auto" value="validate"/> </properties> </persistence-unit> </persistence> |
- Spring manage the EntityManager: Use of JPA2.0 with RESOURCE_LACAL transaction type
So the steps are:
- Create a jpa-persistence.xml. In the case where you don't want that JBoss inject its own libraries, it is better to change the name of the persistence.xml ( JBoss will load JPA implicitely if it detects perssistence.xml file).
- Use RESOURCE_LOCAL and not JTA, if you don't really need to access multiple data sources
- Use "org.hibernate.jpa.HibernatePersistenceProvider" as a provider
- Add a property in the persistence.xml
<property name="jboss.as.jpa.managed" value="false"/>
In fact, according to JBoss Reference, jboss.as.jpa.managed can be set to false to disable container managed JPA access to the persistence unit. The default is true, which enables container managed JPA access to the persistence unit. This is typically set to false for Seam 2.x + Spring applications.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <!-- <persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd"> --> <persistence-unit name="module_enterprise" transaction-type="RESOURCE_LOCAL"> <provider>org.hibernate.jpa.HibernatePersistenceProvider</provider> <non-jta-data-source>java:/myDataSource</non-jta-data-source> <properties> <property name="jboss.as.jpa.managed" value="false" /> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> <property name="hibernate.show_sql" value="true" /> <property name="hibernate.hbm2ddl.auto" value="validate"/> </properties> </persistence-unit> </persistence> |
Step 2 : Spring Configuration
Same think here:
- JBoss manage the EntityManager or EntityManagerFactory and Spring have just the jndi name. Transaction Type here must be JTA. The ApplicationContext looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <?xml version="1.0" encoding="UTF-8"?> <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:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- post-processors for all standard config annotations --> <tx:annotation-driven /> <context:annotation-config /> <context:component-scan base-package="org.test"/> <jee:jndi-lookup id="myDataSource" jndi-name="java:/myDS"/> <jee:jndi-lookup id="entityManagerFactory_module" jndi-name="java:comp/env/test/myfact" expected-type="javax.persistence.EntityManagerFactory"/> <tx:jta-transaction-manager/> </beans> |
In this case, the application uses a server-deployed persistence unit. Thus the javax.persistence classes and the persistence provider (Hibernate) are contained in modules in JBoss ( in JBOSS_HOME\modules\system\layers\base\javax\persistence\api\main) and added automatically by the application while the deployment (When detecting the persistence.xml or persistence-unit, JBoss inject implicitly Hibernate).
So using the server-deployed persistence unit, you need also to declare the JNDI persistence context in the Web.xml:
NB: The persistence-unit-name specified in web.xml should be the same in perssitence.xml file ( <persistence-unit name="module_enterprise" )
1 2 3 4 5 6 7 8 9 10 11 12 | <?xml version="1.0" encoding="UTF-8"?> <web-app version="3.0" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" metadata-complete="true"> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <persistence-unit-ref> <persistence-unit-ref-name>test/myfact</persistence-unit-ref-name> <persistence-unit-name>module_enterprise</persistence-unit-name> </persistence-unit-ref> </web-app> |
Note here that the name that we have declared in the application context is java:comp/env/test/myfact, and in the web.xml, we need to put just test/myfact
If Spring cannot find the Default JBoss transaction Manager, you can guide it like explained in this post.
- Spring manage the EntityManager.
Using JPA2.0, we can enable the JPA in JBoss and use the first possibility. But as we have disabled JPA in JBoss, Spring is now responsible of creating th Transaction and the EntityManagerFactory.
My applicationContext looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | <?xml version="1.0" encoding="UTF-8"?> <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:jee="http://www.springframework.org/schema/jee" xmlns:tx="http://www.springframework.org/schema/tx" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd"> <!-- post-processors for all standard config annotations --> <tx:annotation-driven /> <context:annotation-config /> <context:component-scan base-package="org.test"/> <jee:jndi-lookup id="myDataSource" jndi-name="java:/myDataSource"/> <bean id="emfEnterprise" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="dataSource" ref="myDataSource" /> <property name="jpaVendorAdapter" ref="jpaAdapter" /> <property name="persistenceUnitName" value="module_enterprise"/> <property name="persistenceXmlLocation" value="classpath*:META-INF/jpa-persistence.xml"/> </bean> <bean id="mddEnterpriseTxManager" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="emfEnterprise" /> </bean> <bean id="jpaAdapter" class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter"> <property name="showSql" value="true" /> <property name="generateDdl" value="true" /> <property name="databasePlatform" value="org.hibernate.dialect.PostgreSQLDialect" /> </bean> </beans> |
That's all, so now you are able to integrate JBoss with Spring either by allowing JBoss manage your persistence unit or by letting only Spring doing this and EXCLUDE JBOSS JPA and Hibernate modules.
Tweet
thanks for the tutorial; will it be also possible to share some sample code? really appreciate your helping mind :)
ReplyDeleteYou just saved a lot of time, THANKS
ReplyDelete