[hibernate-commits] Hibernate SVN: r20082 - in search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration: jbossjta and 1 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri Jul 30 06:07:26 EDT 2010


Author: epbernard
Date: 2010-07-30 06:07:26 -0400 (Fri, 30 Jul 2010)
New Revision: 20082

Added:
   search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/
   search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/
   search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/DataSourceByNameProvider.java
   search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/H2dataSourceProvider.java
   search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/JBossTSStandaloneTransactionManagerLookup.java
   search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/PersistenceUnitInfoBuilder.java
   search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/ReadOnlyPersistenceUnitInfo.java
   search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/XADataSourceWrapper.java
Log:
HSEARCH-562 Add JTA test with JBoss TS: Add infrastructural code for JBossTS

In particular:
 - PersistenceUnitInfo builder to use Hibernate's EMF creation "in container"
 - XADatasourceWrapper that does not use JNDI but use a static lookup mechanism
 - create datasource holder for H2
 - create JBossTSStandaloneTransactionManagerLookup (to be contributed to Hibernate Core?)

Added: search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/DataSourceByNameProvider.java
===================================================================
--- search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/DataSourceByNameProvider.java	                        (rev 0)
+++ search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/DataSourceByNameProvider.java	2010-07-30 10:07:26 UTC (rev 20082)
@@ -0,0 +1,28 @@
+package org.hibernate.search.test.integration.jbossjta.infra;
+
+import java.sql.SQLException;
+import javax.sql.XADataSource;
+
+import com.arjuna.ats.internal.jdbc.DynamicClass;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class DataSourceByNameProvider implements DynamicClass {
+	private final XADataSource datasource;
+	private final String name;
+
+	public DataSourceByNameProvider(String name, XADataSource datasource) {
+		this.name = name;
+		this.datasource = datasource;
+	}
+
+	public XADataSource getDataSource(String dbName) throws SQLException {
+		if ( name.equals( dbName ) ) {
+			return datasource;
+		}
+		else {
+			throw new IllegalArgumentException( "Datasource not found: " + dbName );
+		}
+	}
+}
\ No newline at end of file

Added: search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/H2dataSourceProvider.java
===================================================================
--- search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/H2dataSourceProvider.java	                        (rev 0)
+++ search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/H2dataSourceProvider.java	2010-07-30 10:07:26 UTC (rev 20082)
@@ -0,0 +1,33 @@
+package org.hibernate.search.test.integration.jbossjta.infra;
+
+import java.sql.SQLException;
+import javax.sql.XADataSource;
+
+import com.arjuna.ats.internal.jdbc.DynamicClass;
+import org.h2.jdbcx.JdbcDataSource;
+
+/**
+ * Bind a H2 DataSource to the name "h2"
+ *
+ * @author Emmanuel Bernard
+ */
+public class H2dataSourceProvider implements DynamicClass {
+	private static String DATASOURCE_NAME = "h2";
+	private static DynamicClass dynamicClass;
+
+	static {
+		final JdbcDataSource dataSource = new JdbcDataSource();
+		dataSource.setURL( "jdbc:h2:file:h2db" );
+		dataSource.setUser( "sa" );
+		dataSource.setPassword( "" );
+		dynamicClass = new DataSourceByNameProvider( DATASOURCE_NAME, dataSource );
+	}
+
+	public String getDataSourceName() {
+		return DATASOURCE_NAME;
+	}
+
+	public XADataSource getDataSource(String dbName) throws SQLException {
+		return dynamicClass.getDataSource( dbName );
+	}
+}

Added: search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/JBossTSStandaloneTransactionManagerLookup.java
===================================================================
--- search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/JBossTSStandaloneTransactionManagerLookup.java	                        (rev 0)
+++ search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/JBossTSStandaloneTransactionManagerLookup.java	2010-07-30 10:07:26 UTC (rev 20082)
@@ -0,0 +1,29 @@
+package org.hibernate.search.test.integration.jbossjta.infra;
+
+import java.util.Properties;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple;
+import org.jboss.tm.TransactionManagerFactory;
+
+import org.hibernate.HibernateException;
+import org.hibernate.transaction.TransactionManagerLookup;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class JBossTSStandaloneTransactionManagerLookup implements TransactionManagerLookup {
+	public TransactionManager getTransactionManager(Properties props) throws HibernateException {
+		//TODO use reflection
+		return new TransactionManagerImple();
+	}
+
+	public String getUserTransactionName() {
+		return null;
+	}
+
+	public Object getTransactionIdentifier(Transaction transaction) {
+		return transaction;
+	}
+}

Added: search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/PersistenceUnitInfoBuilder.java
===================================================================
--- search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/PersistenceUnitInfoBuilder.java	                        (rev 0)
+++ search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/PersistenceUnitInfoBuilder.java	2010-07-30 10:07:26 UTC (rev 20082)
@@ -0,0 +1,109 @@
+package org.hibernate.search.test.integration.jbossjta.infra;
+
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import javax.persistence.SharedCacheMode;
+import javax.persistence.ValidationMode;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.sql.DataSource;
+
+public class PersistenceUnitInfoBuilder {
+	private String persistenceUnitName;
+	private String persistenceProviderClassName;
+	private PersistenceUnitTransactionType transactionType;
+	private DataSource jtaDataSource;
+	private URL persistenceUnitRootUrl;
+	private List<String> managedClassNames;
+	private boolean excludeUnlistedClasses;
+	private SharedCacheMode sharedCacheMode;
+	private ValidationMode validationMode;
+	private Properties properties;
+	private String persistenceXMLSchemaVersion;
+	private ClassLoader classLoader;
+
+	public PersistenceUnitInfoBuilder() {
+		classLoader = Thread.currentThread().getContextClassLoader();
+		persistenceUnitRootUrl = classLoader.getResource( "persistence.xml" );
+		managedClassNames = new ArrayList<String>();
+		properties = new Properties( );
+	}
+
+	public PersistenceUnitInfoBuilder setPersistenceUnitName(String persistenceUnitName) {
+		this.persistenceUnitName = persistenceUnitName;
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder setPersistenceProviderClassName(String persistenceProviderClassName) {
+		this.persistenceProviderClassName = persistenceProviderClassName;
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder setTransactionType(PersistenceUnitTransactionType transactionType) {
+		this.transactionType = transactionType;
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder setJtaDataSource(DataSource jtaDataSource) {
+		this.jtaDataSource = jtaDataSource;
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder setPersistenceUnitRootUrl(URL persistenceUnitRootUrl) {
+		this.persistenceUnitRootUrl = persistenceUnitRootUrl;
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder addManagedClassNames(String managedClassName) {
+		this.managedClassNames.add( managedClassName );
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder setExcludeUnlistedClasses(boolean excludeUnlistedClasses) {
+		this.excludeUnlistedClasses = excludeUnlistedClasses;
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder setSharedCacheMode(SharedCacheMode sharedCacheMode) {
+		this.sharedCacheMode = sharedCacheMode;
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder setValidationMode(ValidationMode validationMode) {
+		this.validationMode = validationMode;
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder addProperty(String key, String value) {
+		this.properties.setProperty( key, value );
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder setPersistenceXMLSchemaVersion(String persistenceXMLSchemaVersion) {
+		this.persistenceXMLSchemaVersion = persistenceXMLSchemaVersion;
+		return this;
+	}
+
+	public PersistenceUnitInfoBuilder setClassLoader(ClassLoader classLoader) {
+		this.classLoader = classLoader;
+		return this;
+	}
+
+	public ReadOnlyPersistenceUnitInfo create() {
+		return new ReadOnlyPersistenceUnitInfo(
+				persistenceUnitName,
+				persistenceProviderClassName,
+				transactionType,
+				jtaDataSource,
+				persistenceUnitRootUrl,
+				managedClassNames,
+				excludeUnlistedClasses,
+				sharedCacheMode,
+				validationMode,
+				properties,
+				persistenceXMLSchemaVersion,
+				classLoader
+		);
+	}
+}
\ No newline at end of file

Added: search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/ReadOnlyPersistenceUnitInfo.java
===================================================================
--- search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/ReadOnlyPersistenceUnitInfo.java	                        (rev 0)
+++ search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/ReadOnlyPersistenceUnitInfo.java	2010-07-30 10:07:26 UTC (rev 20082)
@@ -0,0 +1,112 @@
+package org.hibernate.search.test.integration.jbossjta.infra;
+
+import java.net.URL;
+import java.util.Collections;
+import java.util.List;
+import java.util.Properties;
+import javax.persistence.SharedCacheMode;
+import javax.persistence.ValidationMode;
+import javax.persistence.spi.ClassTransformer;
+import javax.persistence.spi.PersistenceUnitInfo;
+import javax.persistence.spi.PersistenceUnitTransactionType;
+import javax.sql.DataSource;
+
+/**
+ * @author Emmanuel Bernard
+ */
+public class ReadOnlyPersistenceUnitInfo implements PersistenceUnitInfo {
+	private final String persistenceUnitName;
+	private final String persistenceProviderClassName;
+	private final PersistenceUnitTransactionType transactionType;
+	private final DataSource jtaDataSource;
+	private final URL persistenceUnitRootUrl;
+	private final List<String> managedClassNames;
+	private final boolean excludeUnlistedClasses;
+	private final SharedCacheMode sharedCacheMode;
+	private final ValidationMode validationMode;
+	private final Properties properties;
+	private final String persistenceXMLSchemaVersion;
+	private final ClassLoader classLoader;
+
+	public ReadOnlyPersistenceUnitInfo(String persistenceUnitName, String persistenceProviderClassName, PersistenceUnitTransactionType transactionType, DataSource jtaDataSource, URL persistenceUnitRootUrl, List<String> managedClassNames, boolean excludeUnlistedClasses, SharedCacheMode sharedCacheMode, ValidationMode validationMode, Properties properties, String persistenceXMLSchemaVersion, ClassLoader classLoader) {
+		this.persistenceUnitName = persistenceUnitName;
+		this.persistenceProviderClassName = persistenceProviderClassName;
+		this.transactionType = transactionType;
+		this.jtaDataSource = jtaDataSource;
+		this.persistenceUnitRootUrl = persistenceUnitRootUrl;
+		this.managedClassNames = managedClassNames;
+		this.excludeUnlistedClasses = excludeUnlistedClasses;
+		this.sharedCacheMode = sharedCacheMode;
+		this.validationMode = validationMode;
+		this.properties = properties;
+		this.persistenceXMLSchemaVersion = persistenceXMLSchemaVersion;
+		this.classLoader = classLoader;
+	}
+
+	public String getPersistenceUnitName() {
+		return persistenceUnitName;
+	}
+
+	public String getPersistenceProviderClassName() {
+		return persistenceProviderClassName;
+	}
+
+	public PersistenceUnitTransactionType getTransactionType() {
+		return transactionType;
+	}
+
+	public DataSource getJtaDataSource() {
+		return jtaDataSource;
+	}
+
+	public DataSource getNonJtaDataSource() {
+		return null;
+	}
+
+	public List<String> getMappingFileNames() {
+		return Collections.EMPTY_LIST;
+	}
+
+	public List<URL> getJarFileUrls() {
+		return Collections.EMPTY_LIST;
+	}
+
+	public URL getPersistenceUnitRootUrl() {
+		return persistenceUnitRootUrl;
+	}
+
+	public List<String> getManagedClassNames() {
+		return managedClassNames;
+	}
+
+	public boolean excludeUnlistedClasses() {
+		return excludeUnlistedClasses;
+	}
+
+	public SharedCacheMode getSharedCacheMode() {
+		return sharedCacheMode;
+	}
+
+	public ValidationMode getValidationMode() {
+		return validationMode;
+	}
+
+	public Properties getProperties() {
+		return properties;
+	}
+
+	public String getPersistenceXMLSchemaVersion() {
+		return persistenceXMLSchemaVersion;
+	}
+
+	public ClassLoader getClassLoader() {
+		return classLoader;
+	}
+
+	public void addTransformer(ClassTransformer transformer) {
+	}
+
+	public ClassLoader getNewTempClassLoader() {
+		return null;
+	}
+}

Added: search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/XADataSourceWrapper.java
===================================================================
--- search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/XADataSourceWrapper.java	                        (rev 0)
+++ search/trunk/hibernate-search-integrationtest/src/test/java/org/hibernate/search/test/integration/jbossjta/infra/XADataSourceWrapper.java	2010-07-30 10:07:26 UTC (rev 20082)
@@ -0,0 +1,194 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * 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, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * 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,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA  02110-1301, USA.
+ *
+ * (C) 2008,
+ * @author JBoss Inc.
+ */
+package org.hibernate.search.test.integration.jbossjta.infra;
+
+import javax.sql.XADataSource;
+import javax.sql.XAConnection;
+import javax.sql.DataSource;
+import javax.naming.Context;
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.io.PrintWriter;
+import java.util.Properties;
+
+import com.arjuna.ats.jdbc.TransactionalDriver;
+import com.arjuna.ats.jdbc.common.jdbcPropertyManager;
+//import com.arjuna.common.util.propertyservice.PropertyManager;
+
+
+/**
+ * This class provides a DataSource based approach to
+ * management of transaction aware database connections.
+ * <p/>
+ * It's a XADataSource from which they can obtain a XAResource.
+ * Hence it implements both DataSource and XADataSource.
+ *
+ * @author Jonathan Halliday jonathan.halliday at redhat.com
+ * @author Emmanuel Bernard
+ * @since 2008-05
+ */
+public class XADataSourceWrapper implements XADataSource, DataSource {
+	private XADataSource _theXADataSource;
+	private final TransactionalDriver _theTransactionalDriver = new TransactionalDriver();
+	private String _name;
+	private Properties defaultProperties = new Properties();
+
+	/**
+	 * Create a wrapper around the provided XADataSource implementation,
+	 * which should be registered in tomcat's global JNDI with the specified name.
+	 * Note: the registration is not done here, it's someone elses problem.
+	 * See TransactionalResourceFactory for example usage.
+	 *
+	 * @param name should be the fully qualifed JNDI name of the XADataSource, in
+	 * tomcat's global JNDI, not a webapp specific JNDI context.
+	 * @param theDataSource
+	 */
+	public XADataSourceWrapper(String name, XADataSource theDataSource) {
+		_theXADataSource = theDataSource;
+		_name = name;
+	}
+
+	public void setProperty(String key, String value) {
+		defaultProperties.setProperty( key, value );
+	}
+
+	/**
+	 * Obtain a direct reference to the wrapped object. This is not
+	 * recommended but may be necessary to e.g. call vendor specific methods.
+	 *
+	 * @return
+	 */
+	public XADataSource getUnwrappedXADataSource() {
+		return _theXADataSource;
+	}
+
+	///////////////////////
+
+	// Implementation of the DataSource API is done by reusing the arjuna
+	// TransactionalDriver. Its already got all the smarts for checking tx
+	// context, enlisting resources etc so we just delegate to it.
+	// All we need is some fudging to make the JNDI name stuff behave.
+
+	/**
+	 * Obtain a connection to the database.
+	 * Note: Pooling behaviour depends on the vendor's underlying XADataSource implementation.
+	 *
+	 * @return
+	 *
+	 * @throws SQLException
+	 */
+	public Connection getConnection() throws SQLException {
+		String url = TransactionalDriver.arjunaDriver + _name;
+		// although we are not setting any properties, the driver will barf if we pass 'null'.
+		Properties properties = new Properties(defaultProperties);
+		return getTransactionalConnection( url, properties );
+	}
+
+	/**
+	 * Obtain a connection to the database using the supplied authentication credentials.
+	 *
+	 * @param username
+	 * @param password
+	 *
+	 * @return
+	 *
+	 * @throws SQLException
+	 */
+	public Connection getConnection(String username, String password) throws SQLException {
+		String url = TransactionalDriver.arjunaDriver + _name;
+		Properties properties = new Properties(defaultProperties);
+		properties.setProperty( TransactionalDriver.userName, username );
+		properties.setProperty( TransactionalDriver.password, password );
+		return getTransactionalConnection( url, properties );
+	}
+
+	/*
+		 * This is where most of the tomcat specific weirdness resides. You probably
+		 * want to subclass and override this method for reuse in env other than tomcat.
+		 */
+
+	protected Connection getTransactionalConnection(String url, Properties properties) throws SQLException {
+		/*
+        // For ref, the url the TransactionalDriver expects is the arjuna driver's
+        // special prefix followed by a JNDI name.
+        // via ConnectionImple the IndirectRecoverableConnection.createDataSource method
+        // attempts to look it up in JNDI. There are two problems with this:
+
+        //  First problem,
+        // it always calls InitialContext(env), never InitalContext().
+        // This we work around by copying into the arjuna config, the system
+        // properties it needs to populate the env:
+
+        // caution: ensure the tx lifecycle listener is configured in tomcat or there will be a
+        // possible race here, as recovery needs these properties too and may start first
+        jdbcPropertyManager.propertyManager.setProperty("Context.INITIAL_CONTEXT_FACTORY", System.getProperty(Context.INITIAL_CONTEXT_FACTORY));
+        jdbcPropertyManager.propertyManager.setProperty("Context.URL_PKG_PREFIXES", System.getProperty(Context.URL_PKG_PREFIXES));
+		*/
+
+		Connection connection;
+		connection = _theTransactionalDriver.connect( url, properties );
+		return connection;
+	}
+
+	///////////////////////
+
+	// Implementation of XADataSource API is just a straightforward wrap/delegate.
+	// Note that some of these methods also appear in the DataSource API.
+	// We don't really care, it's the underlying implementations problem
+	// to disambiguate them if required.
+
+	public boolean isWrapperFor(Class<?> iface) throws SQLException {
+		return iface.isAssignableFrom( XADataSource.class );
+	}
+
+	public <T> T unwrap(Class<T> iface) throws SQLException {
+		if ( isWrapperFor( iface ) ) {
+			return ( T ) getUnwrappedXADataSource();
+		}
+		else {
+			throw new SQLException( "Not a wrapper for " + iface.getCanonicalName() );
+		}
+	}
+
+	public XAConnection getXAConnection() throws SQLException {
+		return _theXADataSource.getXAConnection();
+	}
+
+	public XAConnection getXAConnection(String user, String password) throws SQLException {
+		return _theXADataSource.getXAConnection( user, password );
+	}
+
+	public PrintWriter getLogWriter() throws SQLException {
+		return _theXADataSource.getLogWriter();
+	}
+
+	public void setLogWriter(PrintWriter out) throws SQLException {
+		_theXADataSource.setLogWriter( out );
+	}
+
+	public void setLoginTimeout(int seconds) throws SQLException {
+		_theXADataSource.setLoginTimeout( seconds );
+	}
+
+	public int getLoginTimeout() throws SQLException {
+		return _theXADataSource.getLoginTimeout();
+	}
+}



More information about the hibernate-commits mailing list