venerdì 31 agosto 2012

applicazione war con due entity manager contemporanemente

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 {

}






Nessun commento: