Implement a stand-alone JTA JPA/Hibernate application without a J2EE server using Infinispan 2nd level cache and JBoss Transaction Manager
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                                                                                                                                            Â