[hibernate-commits] Hibernate SVN: r18848 - in core/trunk/cache-infinispan: src/test/java/org/hibernate/test/cache/infinispan/tm and 1 other directory.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Mon Feb 22 11:37:23 EST 2010


Author: galder.zamarreno at jboss.com
Date: 2010-02-22 11:37:22 -0500 (Mon, 22 Feb 2010)
New Revision: 18848

Added:
   core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java
Modified:
   core/trunk/cache-infinispan/pom.xml
Log:
[HHH-4640] (Add test with JNDI bound JBoss Transactions Transaction Manager) Done.

Modified: core/trunk/cache-infinispan/pom.xml
===================================================================
--- core/trunk/cache-infinispan/pom.xml	2010-02-21 17:36:27 UTC (rev 18847)
+++ core/trunk/cache-infinispan/pom.xml	2010-02-22 16:37:22 UTC (rev 18848)
@@ -22,6 +22,8 @@
       <version.hsqldb>1.8.0.2</version.hsqldb>
       <version.cglib>2.2</version.cglib>
       <version.javassist>3.4.GA</version.javassist>
+      <version.org.jboss.naming>5.0.3.GA</version.org.jboss.naming>
+      <version.xapool>1.5.0</version.xapool>       
       <skipUnitTests>true</skipUnitTests>
       <!-- 
          Following is the default jgroups mcast address.  If you find the testsuite runs very slowly, there
@@ -77,6 +79,34 @@
             <version>${version.javassist}</version>
             <scope>test</scope>
         </dependency>
+
+        <dependency>
+          <groupId>org.jboss.naming</groupId>
+          <artifactId>jnp-client</artifactId>
+          <scope>test</scope>
+          <version>${version.org.jboss.naming}</version>
+        </dependency>
+
+        <dependency>
+          <groupId>org.jboss.naming</groupId>
+          <artifactId>jnpserver</artifactId>
+          <scope>test</scope>
+          <version>${version.org.jboss.naming}</version>
+        </dependency>
+
+        <dependency>
+          <groupId>com.experlog</groupId>
+          <artifactId>xapool</artifactId>
+          <scope>test</scope>
+          <version>${version.xapool}</version>
+        </dependency>
+
+        <dependency>
+          <groupId>jboss.jbossts</groupId>
+          <artifactId>jbossjta</artifactId>
+          <version>4.9.0.GA</version>
+          <scope>test</scope>
+        </dependency>
     </dependencies>
 
     <build>

Added: core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java
===================================================================
--- core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java	                        (rev 0)
+++ core/trunk/cache-infinispan/src/test/java/org/hibernate/test/cache/infinispan/tm/JBossStandaloneJtaExampleTest.java	2010-02-22 16:37:22 UTC (rev 18848)
@@ -0,0 +1,269 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Middleware LLC or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Middleware LLC.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
+package org.hibernate.test.cache.infinispan.tm;
+
+import junit.framework.TestCase;
+import org.enhydra.jdbc.standard.StandardXADataSource;
+import org.hibernate.Session;
+import org.hibernate.SessionFactory;
+import org.hibernate.cfg.Configuration;
+import org.hibernate.cfg.Environment;
+import org.hibernate.mapping.Collection;
+import org.hibernate.mapping.PersistentClass;
+import org.hibernate.stat.Statistics;
+import org.hibernate.test.cache.infinispan.functional.Item;
+import org.infinispan.transaction.lookup.JBossStandaloneJTAManagerLookup;
+import org.infinispan.util.logging.Log;
+import org.infinispan.util.logging.LogFactory;
+import org.jboss.util.naming.NonSerializableFactory;
+import org.jnp.interfaces.NamingContext;
+import org.jnp.server.Main;
+import org.jnp.server.NamingServer;
+
+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.transaction.Status;
+import javax.transaction.TransactionManager;
+import javax.transaction.UserTransaction;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Iterator;
+import java.util.Properties;
+
+/**
+ * This is an example test based on http://community.jboss.org/docs/DOC-14617 that shows how to interact with
+ * Hibernate configured with Infinispan second level cache provider using JTA transactions.
+ *
+ * In this test, an XADataSource wrapper is in use where we have associated our transaction manager to it so that
+ * commits/rollbacks are propagated to the database as well.
+ *
+ * @author Galder Zamarreño
+ * @since 3.5
+ */
+public class JBossStandaloneJtaExampleTest extends TestCase {
+   private static final Log log = LogFactory.getLog(JBossStandaloneJtaExampleTest.class);
+   private static final JBossStandaloneJTAManagerLookup lookup = new JBossStandaloneJTAManagerLookup();
+   Context ctx;
+   Main jndiServer;
+
+   @Override
+   protected void setUp() throws Exception {
+      super.setUp();
+      jndiServer = startJndiServer();
+      ctx = createJndiContext();
+      bindTransactionManager();
+      bindUserTransaction();
+      bindDataSource();
+   }
+
+   @Override
+   protected void tearDown() throws Exception {
+      super.tearDown();
+      ctx.close();
+      jndiServer.stop();
+   }
+
+   public void testPersistAndLoadUnderJta() throws Exception {
+      Item item;
+      SessionFactory sessionFactory = buildSessionFactory();
+      UserTransaction ut = (UserTransaction) ctx.lookup("UserTransaction");
+      ut.begin();
+      try {
+         Session session = sessionFactory.openSession();
+         session.getTransaction().begin();
+         item = new Item("anItem", "An item owned by someone");
+         session.persist(item);
+         session.getTransaction().commit();
+         session.close();
+      } catch(Exception e) {
+         ut.setRollbackOnly();
+         throw e;
+      } finally {
+         if (ut.getStatus() == Status.STATUS_ACTIVE)
+            ut.commit();
+         else
+            ut.rollback();
+      }
+
+      ut = (UserTransaction) ctx.lookup("UserTransaction");
+      ut.begin();
+      try {
+         Session session = sessionFactory.openSession();
+         session.getTransaction().begin();
+         Item found = (Item) session.load(Item.class, item.getId());
+         Statistics stats = session.getSessionFactory().getStatistics();
+         log.info(stats.toString());
+         assertEquals(item.getDescription(), found.getDescription());
+         assertEquals(0, stats.getSecondLevelCacheMissCount());
+         assertEquals(1, stats.getSecondLevelCacheHitCount());
+         session.delete(found);
+         session.getTransaction().commit();
+         session.close();
+      } catch(Exception e) {
+         ut.setRollbackOnly();
+         throw e;
+      } finally {
+         if (ut.getStatus() == Status.STATUS_ACTIVE)
+            ut.commit();
+         else
+            ut.rollback();
+      }
+   }
+
+   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 = lookup.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();
+      }
+
+      @Override
+      public <T> T unwrap(Class<T> iface) throws SQLException {
+         return null;  // JDK6 stuff
+      }
+
+      @Override
+      public boolean isWrapperFor(Class<?> iface) throws SQLException {
+         return false;  // JDK6 stuff
+      }
+   }
+
+   private Main startJndiServer() throws Exception {
+      // Create an in-memory jndi
+      NamingServer namingServer = new NamingServer();
+      NamingContext.setLocal(namingServer);
+      Main namingMain = new Main();
+      namingMain.setInstallGlobalService(true);
+      namingMain.setPort(-1);
+      namingMain.start();
+      return namingMain;
+   }
+
+   private Context createJndiContext() throws Exception {
+      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");
+      return new InitialContext(props);
+   }
+
+   private void bindTransactionManager() throws Exception {
+      // as JBossTransactionManagerLookup extends JNDITransactionManagerLookup we must also register the TransactionManager
+      bind("java:/TransactionManager", lookup.getTransactionManager(), lookup.getTransactionManager().getClass(), ctx);
+   }
+
+   private void bindUserTransaction() throws Exception {
+      // also the UserTransaction must be registered on jndi: org.hibernate.transaction.JTATransactionFactory#getUserTransaction() requires this
+      bind("UserTransaction", lookup.getUserTransaction(), lookup.getUserTransaction().getClass(), ctx);
+   }
+
+   private void bindDataSource() throws Exception {
+      ExtendedXADataSource xads = new ExtendedXADataSource();
+      xads.setDriverName("org.hsqldb.jdbcDriver");
+      xads.setUrl("jdbc:hsqldb:mem:/example");
+      ctx.bind("java:/MyDatasource", xads);
+   }
+
+   /**
+    * 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 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 void unbind(String jndiName, Context ctx) throws Exception {
+      NonSerializableFactory.unbind(jndiName);
+      ctx.unbind(jndiName);
+   }
+
+   private SessionFactory buildSessionFactory() {
+      Configuration cfg = new Configuration();
+      cfg.setProperty(Environment.DIALECT, "org.hibernate.dialect.HSQLDialect");
+      cfg.setProperty(Environment.HBM2DDL_AUTO, "create-drop");
+      cfg.setProperty(Environment.DATASOURCE, "java:/MyDatasource");
+      cfg.setProperty(Environment.JNDI_CLASS, "org.jnp.interfaces.NamingContextFactory");
+      cfg.setProperty(Environment.TRANSACTION_MANAGER_STRATEGY, "org.hibernate.transaction.JBossTransactionManagerLookup");
+      cfg.setProperty(Environment.TRANSACTION_STRATEGY, "org.hibernate.transaction.JTATransactionFactory");
+      cfg.setProperty(Environment.CURRENT_SESSION_CONTEXT_CLASS, "jta");
+      cfg.setProperty(Environment.RELEASE_CONNECTIONS, "auto");
+      cfg.setProperty(Environment.USE_SECOND_LEVEL_CACHE, "true");
+      cfg.setProperty(Environment.USE_QUERY_CACHE, "true");
+      cfg.setProperty(Environment.CACHE_REGION_FACTORY, "org.hibernate.cache.infinispan.InfinispanRegionFactory");
+      String[] mappings = new String[]{"org/hibernate/test/cache/infinispan/functional/Item.hbm.xml"};
+      for (String mapping : mappings) {
+         cfg.addResource(mapping, Thread.currentThread().getContextClassLoader());
+      }
+      Iterator iter = cfg.getClassMappings();
+      while (iter.hasNext()) {
+         PersistentClass clazz = (PersistentClass) iter.next();
+         cfg.setCacheConcurrencyStrategy(clazz.getEntityName(), "transactional");
+      }
+      iter = cfg.getCollectionMappings();
+      while (iter.hasNext()) {
+         Collection coll = (Collection) iter.next();
+         cfg.setCollectionCacheConcurrencyStrategy(coll.getRole(), "transactional");
+      }
+      return cfg.buildSessionFactory();      
+   }
+}



More information about the hibernate-commits mailing list