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
As we need to let Spring manage the persisitence unit and e want to use RESOURCE_LOCAL transaction type, we need to exclude JPA and Hibernate coming from JBoss.
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.