Implement a stand-alone JTA JPA/Hibernate application without a J2EE server using Infinispan 2nd level cache and JBoss Transaction Manager

WARNING - TOPIC NOT WRITTEN - TOPIC ID: 1705

This topic has not yet been written. The content below is from the topic description.
1.- JBossTM:      The example with JBoss Transactions Transaction Manager was the most complex to implement,      as JBoss's TransactionManager and UserTransaction objects are not declared serializable whilst it's JNDI-server      isn't able to bind non serializable objects out of the box. Special use of NonSerializableFactory is needed, requiring      some additional custom code:     import hello.A;  // a persistent class import java.io.Serializable; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.Name; import javax.naming.NameNotFoundException; import javax.naming.Reference; import javax.naming.StringRefAddr; import javax.persistence.EntityManager; import javax.persistence.Persistence; import javax.transaction.TransactionManager; import javax.transaction.UserTransaction; import org.enhydra.jdbc.standard.StandardXADataSource; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.ejb.HibernateEntityManagerFactory; import org.hibernate.transaction.JBossTransactionManagerLookup; import org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup; import org.jboss.util.naming.NonSerializableFactory; import org.jnp.interfaces.NamingContext; import org.jnp.server.Main; import org.jnp.server.NamingServer; public class JTAStandaloneExampleJBossTM  {         static JBossStandaloneJTAManagerLookup _ml =  new JBossStandaloneJTAManagerLookup();         public static void main(String[] args) {         try {             // Create an in-memory jndi             NamingServer namingServer = new NamingServer();             NamingContext.setLocal(namingServer);             Main namingMain = new Main();             namingMain.setInstallGlobalService(true);             namingMain.setPort(-1);             namingMain.start();                         Properties props = new Properties();             props.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory");             props.put("java.naming.factory.url.pkgs", "org.jboss.naming:org.jnp.interfaces");                        InitialContext ictx = new InitialContext( props );                           // as JBossTransactionManagerLookup extends JNDITransactionManagerLookup we must also register the TransactionManager             bind("java:/TransactionManager", _ml.getTransactionManager(), _ml.getTransactionManager().getClass(), ictx);                         // also the UserTransaction must be registered on jndi: org.hibernate.transaction.JTATransactionFactory#getUserTransaction() requires this             bind(new JBossTransactionManagerLookup().getUserTransactionName(),_ml.getUserTransaction(),_ml.getUserTransaction().getClass(), ictx);                         ExtendedXADataSource xads = new ExtendedXADataSource();              xads.setDriverName("org.hsqldb.jdbcDriver");             xads.setDriverName("com.p6spy.engine.spy.P6SpyDriver"); // comment this line if you don't want p6spy-logging             xads.setUrl("jdbc:hsqldb:hsql://localhost");                //xads.setTransactionManager(_ml.getTransactionManager()); useless here as this information is not serialized                                                                                ictx.bind("java:/MyDatasource", xads);                      final HibernateEntityManagerFactory emf =  (HibernateEntityManagerFactory) Persistence.createEntityManagerFactory("helloworld");                             UserTransaction userTransaction = _ml.getUserTransaction();             userTransaction.setTransactionTimeout(300000);             //SessionFactory sf = (SessionFactory) ictx.lookup("java:/hibernate/MySessionFactory"); // if hibernate.session_factory_name set             final SessionFactory sf = emf.getSessionFactory();             userTransaction.begin();             EntityManager em = emf.createEntityManager();                         // do here your persistent work             A a = new A();             a.name= "firstvalue";             em.persist(a);             em.flush();     // do manually flush here as apparently FLUSH_BEFORE_COMPLETION seems not work, bug ?             System.out.println("\nCreated and flushed instance a with id : " + a.oid + "  a.name set to:" + a.name);             System.out.println("Calling userTransaction.commit() (Please check if the commit is effectively executed!)");             userTransaction.commit();                                    ictx.close();             namingMain.stop();             emf.close();                         } catch (Exception e) {             e.printStackTrace();         }         System.exit(0);     }        public static class ExtendedXADataSource extends StandardXADataSource { // XAPOOL                 @Override         public Connection getConnection() throws SQLException {                         if (getTransactionManager() == null) { // although already set before, it results null again after retrieving the datasource by jndi                  TransactionManager tm;  // this is because the TransactionManager information is not serialized.                 try {                     tm = _ml.getTransactionManager();                 } catch (Exception e) {                     throw new SQLException(e);                 }                 setTransactionManager(tm);  //  resets the TransactionManager on the datasource retrieved by jndi,                                             //  this makes the datasource JTA-aware             }                         // According to Enhydra documentation, here we must return the connection of our XAConnection             // see http://cvs.forge.objectweb.org/cgi-bin/viewcvs.cgi/xapool/xapool/examples/xapooldatasource/DatabaseHelper.java?sortby=rev             return super.getXAConnection().getConnection();         }     }         /**      * Helper method that binds the a non serializable object to the JNDI tree.      *      * @param jndiName Name under which the object must be bound      * @param who Object to bind in JNDI      * @param classType Class type under which should appear the bound object      * @param ctx Naming context under which we bind the object      * @throws Exception Thrown if a naming exception occurs during binding      */     private static void bind(String jndiName, Object who, Class classType, Context ctx) throws Exception {        // Ah ! This service isn't serializable, so we use a helper class        NonSerializableFactory.bind(jndiName, who);        Name n = ctx.getNameParser("").parse(jndiName);        while (n.size() > 1) {           String ctxName = n.get(0);           try {              ctx = (Context) ctx.lookup(ctxName);           } catch (NameNotFoundException e) {              System.out.println("Creating subcontext:" + ctxName);              ctx = ctx.createSubcontext(ctxName);           }           n = n.getSuffix(1);        }        // The helper class NonSerializableFactory uses address type nns, we go on to        // use the helper class to bind the service object in JNDI        StringRefAddr addr = new StringRefAddr("nns", jndiName);        Reference ref = new Reference(classType.getName(), addr, NonSerializableFactory.class.getName(), null);        ctx.rebind(n.get(0), ref);     }         private static void unbind(String jndiName, Context ctx) throws Exception {        NonSerializableFactory.unbind(jndiName);        ctx.unbind(jndiName);     } }   The content of the corresponding complete persistence.xml:            java:/MyDatasource                                                                                                                                                             Â