ambiente: jboss-7.1.1
applicazione: war con due entity, due session bean repository, un service rest che opera usando entrambi i session bean.
caricare il driver mysql tra i moduli di jboss7
(scarica da qui: https://github.com/fiorenzino/dual-jpa.git)
ricordarsi di:
1) persistence.xml aggiungere i nomi delle classi che deve gestire ciascun em
2) persistence.xml non usare <property name="hibernate.hbm2ddl.auto" value="update" /> altrimenti crea le tabelle in entrambi i db (consiglio di crearle prima di deployare)
esempio di entity:
@Entity
public class UserA implements Serializable {
private Long id;
private String name;
....
@Entity
public class UserB implements Serializable {
private Long id;
private String name;
....
esempio di persistence.xml:
<?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="PuA">
<jta-data-source>java:jboss/datasources/ExampleA</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
</properties>
<class>it.coopservice.test.model.UserA</class>
</persistence-unit>
<persistence-unit name="PuB">
<jta-data-source>java:jboss/datasources/ExampleB</jta-data-source>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQLDialect" />
<property name="hibernate.show_sql" value="true" />
<property name="hibernate.format_sql" value="true" />
</properties>
<class>it.coopservice.test.model.UserB</class>
</persistence-unit>
</persistence>
3) nei repository iniettare gli entity manager specificando la persistence unit:
esempio di session bean:
@Stateless
@LocalBean
public class SessionA implements Serializable {
@PersistenceContext(unitName = "PuA")
protected EntityManager em;
...
@Stateless
@LocalBean
public class SessionB implements Serializable {
@PersistenceContext(unitName = "PuB")
protected EntityManager em;
...
4) nello standalone.xml mappare i datasource usando driver XA (altrimenti non sarà possibile effettuare operazioni nella stessa transazione su entrambi i datasource:
esempio di datasource in standalone.xml:
<datasources>
<xa-datasource jndi-name="java:jboss/datasources/ExampleA" pool-name="ExampleAD" enabled="true" use-ccm="false">
<xa-datasource-property name="URL">jdbc:mysql://localhost:3306/exampleA</xa-datasource-property>
<driver>com.mysql</driver>
<xa-pool>
<is-same-rm-override>false</is-same-rm-override>
<interleaving>false</interleaving>
<pad-xid>false</pad-xid>
<wrap-xa-resource>true</wrap-xa-resource>
</xa-pool>
<security>
<user-name>root</user-name>
<password>flower</password>
</security>
<recovery>
<recover-credential>
<user-name>root</user-name>
<password>flower</password>
</recover-credential>
</recovery>
</xa-datasource>
<xa-datasource jndi-name="java:jboss/datasources/ExampleB" pool-name="ExampleBD" enabled="true" use-ccm="false">
<xa-datasource-property name="URL">jdbc:mysql://localhost:3306/exampleB</xa-datasource-property>
<driver>com.mysql</driver>
<xa-pool>
<is-same-rm-override>false</is-same-rm-override>
<interleaving>false</interleaving>
<pad-xid>false</pad-xid>
<wrap-xa-resource>true</wrap-xa-resource>
</xa-pool>
<security>
<user-name>root</user-name>
<password>flower</password>
</security>
<recovery>
<recover-credential>
<user-name>root</user-name>
<password>flower</password>
</recover-credential>
</recovery>
</xa-datasource>
</datasources>
<drivers>
<driver name="com.mysql" module="com.mysql">
<xa-datasource-class>com.mysql.jdbc.jdbc2.optional.MysqlXADataSource</xa-datasource-class>
</driver>
</drivers>
a questo punto sara' possibile usare un service che si inettta entrambi i session bean delegati a ciascun respository e fare operazioni transazionali:
esempio di service che opera su entrambi i session beans:
@Stateless
@LocalBean
public class ServiceAB implements Serializable {
@Inject
SessionA sessionA;
@Inject
SessionB sessionB;
public String createAB(String nameA, String nameB) {
UserA userA = new UserA(nameA);
Long idA = sessionA.persist(userA);
UserB userB = new UserB(nameB);
Long idB = sessionB.persist(userB);
return "a:" + idA + " - b:" + idB;
}
}
esempio di servizio rest per fare i test :
@Path("/v1/test")
@Stateless
@LocalBean
public class Rest implements Serializable {
@Inject
SessionA sessionA;
@Inject
SessionB sessionB;
@Inject
ServiceAB serviceAB;
@GET
@Path("/addA/{name}")
@Produces(MediaType.TEXT_PLAIN)
public Long addA(@PathParam("name") String name) {
UserA userA = new UserA();
userA.setName(name);
return sessionA.persist(userA);
}
@GET
@Path("/addB/{name}")
@Produces(MediaType.TEXT_PLAIN)
public Long addB(@PathParam("name") String name) {
UserB userB = new UserB();
userB.setName(name);
return sessionB.persist(userB);
}
@GET
@Path("/addAB/{nameA}/{nameB}")
@Produces(MediaType.TEXT_PLAIN)
public String addAB(@PathParam("nameA") String nameA,
@PathParam("nameB") String nameB) {
return serviceAB.createAB(nameA, nameB);
}
}
ricordarsi di aggiungere un rest activator:
@ApplicationPath("/rest")
public class JaxRsActivator extends javax.ws.rs.core.Application {
}