You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by ti...@apache.org on 2011/09/08 17:15:30 UTC
svn commit: r1166736 - in /aries/trunk/jpa:
jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/
jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/
jpa-container-testbundle-eclipselink/src/main/resources/META-INF/ ...
Author: timothyjward
Date: Thu Sep 8 15:15:29 2011
New Revision: 1166736
URL: http://svn.apache.org/viewvc?rev=1166736&view=rev
Log:
ARIES-741: Support for auto-enlistment of XADataSource objects from JNDI or DataSourceFactory
Added:
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/ConnectionKey.java
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/ConnectionWrapper.java
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/OSGiTransactionManager.java
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/XADatasourceEnlistingWrapper.java
Modified:
aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerDataSourceFactoryTest.java
aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/JPAContextTest.java
aries/trunk/jpa/jpa-container-testbundle-eclipselink/src/main/resources/META-INF/persistence.xml
aries/trunk/jpa/jpa-container-testbundle-eclipselink/src/main/resources/OSGI-INF/blueprint/config.xml
aries/trunk/jpa/jpa-container-testbundle/src/main/resources/META-INF/persistence.xml
aries/trunk/jpa/jpa-container-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml
aries/trunk/jpa/jpa-container/pom.xml
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleManager.java
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/DataSourceFactoryDataSource.java
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/DelayedLookupDataSource.java
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/JndiDataSource.java
aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/PersistenceUnitInfoImpl.java
aries/trunk/jpa/jpa-container/src/main/resources/org/apache/aries/jpa/container/nls/jpaContainerMessages.properties
Modified: aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerDataSourceFactoryTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerDataSourceFactoryTest.java?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerDataSourceFactoryTest.java (original)
+++ aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/container/itest/JPAContainerDataSourceFactoryTest.java Thu Sep 8 15:15:29 2011
@@ -31,11 +31,13 @@ import javax.persistence.EntityManagerFa
import javax.sql.ConnectionPoolDataSource;
import javax.sql.DataSource;
import javax.sql.XADataSource;
+import javax.transaction.UserTransaction;
import org.apache.aries.itest.AbstractIntegrationTest;
import org.apache.aries.jpa.container.PersistenceUnitConstants;
import org.apache.aries.jpa.container.itest.entities.Car;
import org.apache.derby.jdbc.EmbeddedDataSource;
+import org.apache.derby.jdbc.EmbeddedXADataSource;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
@@ -95,6 +97,58 @@ public class JPAContainerDataSourceFacto
assertNull(refs);
}
+ @Test
+ public void testDataSourceFactoryXALifecycle() throws Exception {
+ //Wait for startup
+ context().getService(EntityManagerFactory.class, "(&(osgi.unit.name=test-unit)(" + PersistenceUnitConstants.CONTAINER_MANAGED_PERSISTENCE_UNIT + "=true))");
+
+ //Now go
+ ServiceReference[] refs = context().getServiceReferences(
+ EntityManagerFactory.class.getName(), "(&(osgi.unit.name=dsf-xa-test-unit)(" + PersistenceUnitConstants.CONTAINER_MANAGED_PERSISTENCE_UNIT + "=true))");
+
+ assertNull(refs);
+
+ Hashtable<String, Object> props = new Hashtable();
+ props.put(DataSourceFactory.OSGI_JDBC_DRIVER_CLASS, "org.apache.derby.jdbc.EmbeddedDriver");
+
+ ServiceRegistration reg = context().registerService(DataSourceFactory.class.getName(),
+ new DerbyDataSourceFactory(), props);
+
+
+ EntityManagerFactory emf = context().getService(EntityManagerFactory.class,
+ "(&(osgi.unit.name=dsf-xa-test-unit)(" + PersistenceUnitConstants.CONTAINER_MANAGED_PERSISTENCE_UNIT + "=true))");
+
+
+ EntityManager em = emf.createEntityManager();
+
+ //Use a JTA tran to show integration
+ UserTransaction ut = context().getService(UserTransaction.class);
+
+ ut.begin();
+ em.joinTransaction();
+ Car c = new Car();
+ c.setNumberPlate("123456");
+ c.setColour("blue");
+ em.persist(c);
+
+ ut.commit();
+
+ em.close();
+
+ em = emf.createEntityManager();
+
+ assertEquals("blue", em.find(Car.class, "123456").getColour());
+
+ reg.unregister();
+
+ refs = context().getServiceReferences(
+ EntityManagerFactory.class.getName(), "(&(osgi.unit.name=dsf-xa-test-unit)(" + PersistenceUnitConstants.CONTAINER_MANAGED_PERSISTENCE_UNIT + "=true))");
+
+ assertNull(refs);
+ }
+
+
+
private static class DerbyDataSourceFactory implements DataSourceFactory {
public DataSource createDataSource(Properties props) throws SQLException {
@@ -112,8 +166,10 @@ public class JPAContainerDataSourceFacto
public XADataSource createXADataSource(Properties props)
throws SQLException {
- // TODO Auto-generated method stub
- return null;
+ EmbeddedXADataSource ds = new EmbeddedXADataSource();
+ ds.setDatabaseName("memory:TEST");
+ ds.setCreateDatabase("create");
+ return ds;
}
public Driver createDriver(Properties props) throws SQLException {
Modified: aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/JPAContextTest.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/JPAContextTest.java?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/JPAContextTest.java (original)
+++ aries/trunk/jpa/jpa-container-itest/src/test/java/org/apache/aries/jpa/context/itest/JPAContextTest.java Thu Sep 8 15:15:29 2011
@@ -38,6 +38,11 @@ import javax.persistence.Query;
import javax.persistence.TransactionRequiredException;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaQuery;
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
import javax.transaction.UserTransaction;
import org.apache.aries.itest.AbstractIntegrationTest;
@@ -194,6 +199,13 @@ public abstract class JPAContextTest ext
EntityManagerFactory emf = getProxyEMF("bp-test-unit");
+ doNonTxEmIsCleared(emf);
+
+ }
+
+ private void doNonTxEmIsCleared(EntityManagerFactory emf)
+ throws NotSupportedException, SystemException, HeuristicMixedException,
+ HeuristicRollbackException, RollbackException {
final EntityManager managedEm = emf.createEntityManager();
UserTransaction ut = context().getService(UserTransaction.class);
@@ -240,6 +252,16 @@ public abstract class JPAContextTest ext
assertEquals(2, c.getNumberOfSeats());
assertEquals(2000, c.getEngineSize());
assertEquals("red", c.getColour());
+ }
+
+ @Test
+ public void testNonTxEmIsClearedUsingXADataSourceWrapper() throws Exception {
+
+ registerClient("bp-xa-test-unit");
+
+ EntityManagerFactory emf = getProxyEMF("bp-xa-test-unit");
+
+ doNonTxEmIsCleared(emf);
}
Modified: aries/trunk/jpa/jpa-container-testbundle-eclipselink/src/main/resources/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container-testbundle-eclipselink/src/main/resources/META-INF/persistence.xml?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container-testbundle-eclipselink/src/main/resources/META-INF/persistence.xml (original)
+++ aries/trunk/jpa/jpa-container-testbundle-eclipselink/src/main/resources/META-INF/persistence.xml Thu Sep 8 15:15:29 2011
@@ -47,4 +47,19 @@
<property name="eclipselink.ddl-generation.output-mode" value="database" />
</properties>
</persistence-unit>
+
+ <persistence-unit name="bp-xa-test-unit" transaction-type="JTA">
+ <description>Test persistence unit for the JPA Container and Context iTests</description>
+ <jta-data-source>blueprint:comp/xa</jta-data-source>
+ <non-jta-data-source>blueprint:comp/nonjta</non-jta-data-source>
+ <class>org.apache.aries.jpa.container.itest.entities.Car</class>
+ <exclude-unlisted-classes>true</exclude-unlisted-classes>
+ <properties>
+ <!-- These properties are creating the database on the fly. We are using them to avoid the tests having
+ to create a database -->
+ <property name="eclipselink.target-database" value="Derby"/>
+ <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/>
+ <property name="eclipselink.ddl-generation.output-mode" value="database" />
+ </properties>
+ </persistence-unit>
</persistence>
Modified: aries/trunk/jpa/jpa-container-testbundle-eclipselink/src/main/resources/OSGI-INF/blueprint/config.xml
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container-testbundle-eclipselink/src/main/resources/OSGI-INF/blueprint/config.xml?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container-testbundle-eclipselink/src/main/resources/OSGI-INF/blueprint/config.xml (original)
+++ aries/trunk/jpa/jpa-container-testbundle-eclipselink/src/main/resources/OSGI-INF/blueprint/config.xml Thu Sep 8 15:15:29 2011
@@ -23,15 +23,16 @@
</bean>
- <service interface="javax.sql.XADataSource">
+ <service interface="javax.sql.XADataSource" ref="xa">
<service-properties>
<entry key="transactional" value="true"/>
</service-properties>
- <bean class="org.apache.derby.jdbc.EmbeddedXADataSource">
- <property name="databaseName" value="memory:testDB"/>
- <property name="createDatabase" value="create"/>
- </bean>
</service>
+
+ <bean id="xa" class="org.apache.derby.jdbc.EmbeddedXADataSource">
+ <property name="databaseName" value="memory:testDB"/>
+ <property name="createDatabase" value="create"/>
+ </bean>
<reference id="jta" availability="optional" interface="javax.sql.DataSource"
filter="(transactional=true)"/>
Modified: aries/trunk/jpa/jpa-container-testbundle/src/main/resources/META-INF/persistence.xml
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/META-INF/persistence.xml?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container-testbundle/src/main/resources/META-INF/persistence.xml (original)
+++ aries/trunk/jpa/jpa-container-testbundle/src/main/resources/META-INF/persistence.xml Thu Sep 8 15:15:29 2011
@@ -47,6 +47,20 @@
</properties>
</persistence-unit>
+ <persistence-unit name="bp-xa-test-unit" transaction-type="JTA">
+ <description>Test persistence unit for the JPA Container and Context iTests</description>
+ <jta-data-source>blueprint:comp/xa</jta-data-source>
+ <non-jta-data-source>blueprint:comp/nonjta</non-jta-data-source>
+ <class>org.apache.aries.jpa.container.itest.entities.Car</class>
+ <exclude-unlisted-classes>true</exclude-unlisted-classes>
+ <properties>
+ <!-- These properties are creating the database on the fly. We are using them to avoid the tests having
+ to create a database -->
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ <property name="openjpa.jdbc.DBDictionary" value="derby"/>
+ </properties>
+ </persistence-unit>
+
<persistence-unit name="dsf-test-unit" transaction-type="RESOURCE_LOCAL">
<description>Test persistence unit for the JPA Container DataSourceFactory iTests</description>
<class>org.apache.aries.jpa.container.itest.entities.Car</class>
@@ -60,4 +74,18 @@
<property name="openjpa.jdbc.DBDictionary" value="derby"/>
</properties>
</persistence-unit>
+
+ <persistence-unit name="dsf-xa-test-unit" transaction-type="JTA">
+ <description>Test persistence unit for the JPA Container DataSourceFactory iTests</description>
+ <class>org.apache.aries.jpa.container.itest.entities.Car</class>
+ <exclude-unlisted-classes>true</exclude-unlisted-classes>
+ <properties>
+ <!-- These properties are creating the database on the fly. We are using them to avoid the tests having
+ to create a database -->
+ <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
+ <property name="javax.persistence.jdbc.url" value="jdbc:derby:memory:TEST;create=true"/>
+ <property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
+ <property name="openjpa.jdbc.DBDictionary" value="derby"/>
+ </properties>
+ </persistence-unit>
</persistence>
Modified: aries/trunk/jpa/jpa-container-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml (original)
+++ aries/trunk/jpa/jpa-container-testbundle/src/main/resources/OSGI-INF/blueprint/config.xml Thu Sep 8 15:15:29 2011
@@ -23,15 +23,16 @@
</bean>
- <service interface="javax.sql.XADataSource">
+ <service interface="javax.sql.XADataSource" ref="xa">
<service-properties>
<entry key="transactional" value="true"/>
</service-properties>
- <bean class="org.apache.derby.jdbc.EmbeddedXADataSource">
+ </service>
+
+ <bean id="xa" class="org.apache.derby.jdbc.EmbeddedXADataSource">
<property name="databaseName" value="memory:testDB"/>
<property name="createDatabase" value="create"/>
</bean>
- </service>
<reference id="jta" availability="optional" interface="javax.sql.DataSource"
filter="(transactional=true)"/>
Modified: aries/trunk/jpa/jpa-container/pom.xml
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/pom.xml?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/pom.xml (original)
+++ aries/trunk/jpa/jpa-container/pom.xml Thu Sep 8 15:15:29 2011
@@ -46,6 +46,7 @@
javax.persistence.spi;version="[1.0.0,2.1.0)",
javax.persistence.criteria;version="[1.1.0,2.1.0)";resolution:=optional,
javax.persistence.metamodel;version="[1.1.0,2.1.0)";resolution:=optional,
+ !javax.transaction,
org.apache.aries.jpa.container;version="[0.1.0,1.1.0)",
org.apache.aries.jpa.container.parsing;version="[0.1.0,1.1.0)",
org.apache.aries.quiesce.manager;version="[0.2,1.0)";resolution:=optional,
@@ -56,6 +57,9 @@
org.osgi.service.jdbc;version="[1,2)";resolution:=optional,
*
</aries.osgi.import>
+ <aries.osgi.dynamic>
+ javax.transaction;version="[1.1,2)"
+ </aries.osgi.dynamic>
<aries.osgi.activator>
org.apache.aries.jpa.container.impl.PersistenceBundleManager
</aries.osgi.activator>
@@ -157,6 +161,11 @@
<type>jar</type>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.geronimo.specs</groupId>
+ <artifactId>geronimo-jta_1.1_spec</artifactId>
+ <version>1.1.1</version>
+ </dependency>
</dependencies>
</project>
Modified: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleManager.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleManager.java?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleManager.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/impl/PersistenceBundleManager.java Thu Sep 8 15:15:29 2011
@@ -44,6 +44,7 @@ import org.apache.aries.jpa.container.pa
import org.apache.aries.jpa.container.parsing.PersistenceDescriptorParser;
import org.apache.aries.jpa.container.parsing.PersistenceDescriptorParserException;
import org.apache.aries.jpa.container.parsing.impl.PersistenceDescriptorParserImpl;
+import org.apache.aries.jpa.container.tx.impl.OSGiTransactionManager;
import org.apache.aries.jpa.container.unit.impl.ManagedPersistenceUnitInfoFactoryImpl;
import org.apache.aries.util.AriesFrameworkUtil;
import org.apache.aries.util.VersionRange;
@@ -142,6 +143,10 @@ public class PersistenceBundleManager im
if (serviceTracker != null) {
serviceTracker.close();
}
+
+ OSGiTransactionManager otm = OSGiTransactionManager.get();
+ if(otm != null)
+ otm.destroy();
}
public Object addingBundle(Bundle bundle, BundleEvent event)
{
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/ConnectionKey.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/ConnectionKey.java?rev=1166736&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/ConnectionKey.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/ConnectionKey.java Thu Sep 8 15:15:29 2011
@@ -0,0 +1,81 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.jpa.container.tx.impl;
+
+import javax.transaction.Transaction;
+
+public class ConnectionKey {
+
+ private final String username;
+
+ private final String password;
+
+ private final Transaction transaction;
+
+ public ConnectionKey(String username, String password, Transaction transaction) {
+ this.username = username;
+ this.password = password;
+ this.transaction = transaction;
+ }
+
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((username == null) ? 0 : username.hashCode());
+ result = prime * result + ((password == null) ? 0 : password.hashCode());
+ result = prime * result + ((transaction == null) ? 0 : transaction.hashCode());
+ return result;
+ }
+
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ ConnectionKey other = (ConnectionKey) obj;
+ if (username == null) {
+ if (other.username != null) {
+ return false;
+ }
+ } else if (!username.equals(other.username)) {
+ return false;
+ }
+ if (password == null) {
+ if (other.password != null) {
+ return false;
+ }
+ } else if (!password.equals(other.password)) {
+ return false;
+ }
+ if (transaction == null) {
+ if (other.transaction != null) {
+ return false;
+ }
+ } else if (!transaction.equals(other.transaction)) {
+ return false;
+ }
+ return true;
+ }
+
+}
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/ConnectionWrapper.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/ConnectionWrapper.java?rev=1166736&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/ConnectionWrapper.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/ConnectionWrapper.java Thu Sep 8 15:15:29 2011
@@ -0,0 +1,306 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.jpa.container.tx.impl;
+
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.CallableStatement;
+import java.sql.Clob;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.NClob;
+import java.sql.PreparedStatement;
+import java.sql.SQLClientInfoException;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.SQLXML;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.Struct;
+import java.util.Map;
+import java.util.Properties;
+
+import javax.transaction.xa.XAResource;
+
+import org.apache.aries.jpa.container.impl.NLS;
+
+/**
+ * This class is a wrapper around a {@link Connection} that performs
+ * enlistment/delistment of an {@link XAResource} from a transaction.
+ *
+ * @see XADatasourceEnlistingWrapper
+ */
+public class ConnectionWrapper implements Connection {
+
+ private Connection connection;
+
+ private boolean closed;
+
+ private boolean enlisted;
+
+ public ConnectionWrapper(Connection connection, boolean enlisted) {
+ this.enlisted = enlisted;
+ this.connection = connection;
+ }
+
+ public void close() throws SQLException {
+ if (!closed) {
+ try {
+ // don't close connection if enlisted in a transaction
+ // the connection will be closed in once the transaction completes
+ if (!enlisted) {
+ connection.close();
+ }
+ } finally {
+ closed = true;
+ }
+ }
+ }
+
+ // cannot be used while enrolled in a transaction
+
+ public void commit() throws SQLException {
+ if (enlisted) {
+ throw new SQLException(NLS.MESSAGES.getMessage("datasource.enlised.commit"));
+ }
+ connection.commit();
+ }
+
+ public void rollback() throws SQLException {
+ if (enlisted) {
+ throw new SQLException(NLS.MESSAGES.getMessage("datasource.enlised.rollback"));
+ }
+ connection.rollback();
+ }
+
+ public void rollback(Savepoint savepoint) throws SQLException {
+ if (enlisted) {
+ throw new SQLException(NLS.MESSAGES.getMessage("datasource.enlised.rollback"));
+ }
+ connection.rollback(savepoint);
+ }
+
+ public Savepoint setSavepoint() throws SQLException {
+ if (enlisted) {
+ throw new SQLException(NLS.MESSAGES.getMessage("datasource.enlised.savepoint"));
+ }
+ return connection.setSavepoint();
+ }
+
+ public Savepoint setSavepoint(String name) throws SQLException {
+ if (enlisted) {
+ throw new SQLException(NLS.MESSAGES.getMessage("datasource.enlised.savepoint"));
+ }
+ return connection.setSavepoint(name);
+ }
+
+ // rest of the methods
+
+ public void clearWarnings() throws SQLException {
+ connection.clearWarnings();
+ }
+
+ public Array createArrayOf(String typeName, Object[] elements)
+ throws SQLException {
+ return connection.createArrayOf(typeName, elements);
+ }
+
+ public Blob createBlob() throws SQLException {
+ return connection.createBlob();
+ }
+
+ public Clob createClob() throws SQLException {
+ return connection.createClob();
+ }
+
+ public NClob createNClob() throws SQLException {
+ return connection.createNClob();
+ }
+
+ public SQLXML createSQLXML() throws SQLException {
+ return connection.createSQLXML();
+ }
+
+ public Statement createStatement() throws SQLException {
+ return connection.createStatement();
+ }
+
+ public Statement createStatement(int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return connection.createStatement(resultSetType, resultSetConcurrency,
+ resultSetHoldability);
+ }
+
+ public Statement createStatement(int resultSetType, int resultSetConcurrency)
+ throws SQLException {
+ return connection.createStatement(resultSetType, resultSetConcurrency);
+ }
+
+ public Struct createStruct(String typeName, Object[] attributes)
+ throws SQLException {
+ return connection.createStruct(typeName, attributes);
+ }
+
+ public boolean getAutoCommit() throws SQLException {
+ return connection.getAutoCommit();
+ }
+
+ public String getCatalog() throws SQLException {
+ return connection.getCatalog();
+ }
+
+ public Properties getClientInfo() throws SQLException {
+ return connection.getClientInfo();
+ }
+
+ public String getClientInfo(String name) throws SQLException {
+ return connection.getClientInfo(name);
+ }
+
+ public int getHoldability() throws SQLException {
+ return connection.getHoldability();
+ }
+
+ public DatabaseMetaData getMetaData() throws SQLException {
+ return connection.getMetaData();
+ }
+
+ public int getTransactionIsolation() throws SQLException {
+ return connection.getTransactionIsolation();
+ }
+
+ public Map<String, Class<?>> getTypeMap() throws SQLException {
+ return connection.getTypeMap();
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return connection.getWarnings();
+ }
+
+ public boolean isClosed() throws SQLException {
+ return connection.isClosed();
+ }
+
+ public boolean isReadOnly() throws SQLException {
+ return connection.isReadOnly();
+ }
+
+ public boolean isValid(int timeout) throws SQLException {
+ return connection.isValid(timeout);
+ }
+
+ public boolean isWrapperFor(Class<?> iface) throws SQLException {
+ return connection.isWrapperFor(iface);
+ }
+
+ public String nativeSQL(String sql) throws SQLException {
+ return connection.nativeSQL(sql);
+ }
+
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return connection.prepareCall(sql, resultSetType, resultSetConcurrency,
+ resultSetHoldability);
+ }
+
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException {
+ return connection.prepareCall(sql, resultSetType, resultSetConcurrency);
+ }
+
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ return connection.prepareCall(sql);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException {
+ return connection.prepareStatement(sql, resultSetType,
+ resultSetConcurrency, resultSetHoldability);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException {
+ return connection.prepareStatement(sql, resultSetType,
+ resultSetConcurrency);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+ throws SQLException {
+ return connection.prepareStatement(sql, autoGeneratedKeys);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
+ throws SQLException {
+ return connection.prepareStatement(sql, columnIndexes);
+ }
+
+ public PreparedStatement prepareStatement(String sql, String[] columnNames)
+ throws SQLException {
+ return connection.prepareStatement(sql, columnNames);
+ }
+
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ return connection.prepareStatement(sql);
+ }
+
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ connection.releaseSavepoint(savepoint);
+ }
+
+ public void setAutoCommit(boolean autoCommit) throws SQLException {
+ connection.setAutoCommit(autoCommit);
+ }
+
+ public void setCatalog(String catalog) throws SQLException {
+ connection.setCatalog(catalog);
+ }
+
+ public void setClientInfo(Properties properties)
+ throws SQLClientInfoException {
+ connection.setClientInfo(properties);
+ }
+
+ public void setClientInfo(String name, String value)
+ throws SQLClientInfoException {
+ connection.setClientInfo(name, value);
+ }
+
+ public void setHoldability(int holdability) throws SQLException {
+ connection.setHoldability(holdability);
+ }
+
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ connection.setReadOnly(readOnly);
+ }
+
+ public void setTransactionIsolation(int level) throws SQLException {
+ connection.setTransactionIsolation(level);
+ }
+
+ public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
+ connection.setTypeMap(map);
+ }
+
+ public <T> T unwrap(Class<T> iface) throws SQLException {
+ return connection.unwrap(iface);
+ }
+}
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/OSGiTransactionManager.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/OSGiTransactionManager.java?rev=1166736&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/OSGiTransactionManager.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/OSGiTransactionManager.java Thu Sep 8 15:15:29 2011
@@ -0,0 +1,121 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.jpa.container.tx.impl;
+
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.transaction.HeuristicMixedException;
+import javax.transaction.HeuristicRollbackException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.NotSupportedException;
+import javax.transaction.RollbackException;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+
+import org.apache.aries.jpa.container.impl.NLS;
+import org.apache.aries.util.tracker.SingleServiceTracker;
+import org.apache.aries.util.tracker.SingleServiceTracker.SingleServiceListener;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Used to avoid a dependency on javax.transaction.TransactionManager
+ */
+public class OSGiTransactionManager implements SingleServiceListener {
+
+ private static final AtomicReference<OSGiTransactionManager> INSTANCE =
+ new AtomicReference<OSGiTransactionManager>();
+
+ private final SingleServiceTracker<TransactionManager> tracker;
+
+ public static void init(BundleContext ctx) {
+
+ try {
+ Class<TransactionManager> txMgrClass = (Class<TransactionManager>) Class.forName(
+ "javax.transaction.TransactionManager", false,
+ OSGiTransactionManager.class.getClassLoader());
+
+ OSGiTransactionManager otm = new OSGiTransactionManager(txMgrClass, ctx);
+ if(!!!INSTANCE.compareAndSet(null, otm))
+ otm.destroy();
+ } catch (ClassNotFoundException cnfe) {
+ //No op
+ }
+ }
+
+ public static OSGiTransactionManager get() {
+ return INSTANCE.get();
+ }
+
+ private OSGiTransactionManager(Class<TransactionManager> txMgrClass, BundleContext ctx) {
+ tracker = new SingleServiceTracker<TransactionManager>(ctx, txMgrClass, this);
+ tracker.open();
+ }
+
+ private TransactionManager getTransactionManager() {
+ TransactionManager txMgr = tracker.getService();
+
+ if(txMgr == null)
+ throw new IllegalStateException(NLS.MESSAGES.getMessage("unable.to.get.tx.mgr"));
+
+ return txMgr;
+ }
+
+ public void destroy() {
+ tracker.close();
+ }
+
+ public int getStatus() throws SystemException {
+ return getTransactionManager().getStatus();
+ }
+
+ public void resume(Transaction arg0) throws IllegalStateException,
+ InvalidTransactionException, SystemException {
+ getTransactionManager().resume(arg0);
+ }
+
+ public void setRollbackOnly() throws IllegalStateException, SystemException {
+ getTransactionManager().setRollbackOnly();
+ }
+
+ public Object getTransaction() throws SystemException {
+ // TODO Auto-generated method stub
+ return getTransactionManager().getTransaction();
+ }
+
+ @Override
+ public void serviceFound() {
+ // TODO Auto-generated method stub
+
+ }
+
+
+ @Override
+ public void serviceLost() {
+ // TODO Auto-generated method stub
+
+ }
+
+
+ @Override
+ public void serviceReplaced() {
+ // TODO Auto-generated method stub
+
+ }
+}
Added: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/XADatasourceEnlistingWrapper.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/XADatasourceEnlistingWrapper.java?rev=1166736&view=auto
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/XADatasourceEnlistingWrapper.java (added)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/tx/impl/XADatasourceEnlistingWrapper.java Thu Sep 8 15:15:29 2011
@@ -0,0 +1,200 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.aries.jpa.container.tx.impl;
+
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import javax.sql.DataSource;
+import javax.sql.XAConnection;
+import javax.sql.XADataSource;
+import javax.transaction.Status;
+import javax.transaction.Synchronization;
+import javax.transaction.SystemException;
+import javax.transaction.Transaction;
+import javax.transaction.TransactionManager;
+import javax.transaction.xa.XAResource;
+
+import org.apache.aries.jpa.container.impl.NLS;
+import org.osgi.framework.FrameworkUtil;
+
+/**
+ * This class allows JDBC XA data sources to participate in global transactions,
+ * via the {@link ConnectionWrapper} that is returned. The only service provided
+ * is enlistment/delistment of the associated {@link XAResource} in transactions.
+ * Important consideration such as connection pooling and error handling are
+ * completely ignored.
+ *
+ */
+public class XADatasourceEnlistingWrapper implements DataSource, Serializable {
+ /** The serial version UID */
+ private static final long serialVersionUID = -3200389791205501228L;
+
+ private final XADataSource wrappedDS;
+
+ private transient Map<Object, Connection> connectionMap =
+ new ConcurrentHashMap<Object, Connection>();
+
+ public XADatasourceEnlistingWrapper(XADataSource toWrap) {
+ wrappedDS = toWrap;
+ OSGiTransactionManager.init(FrameworkUtil.getBundle(
+ XADatasourceEnlistingWrapper.class).getBundleContext());
+ }
+
+ public Connection getConnection() throws SQLException {
+ Transaction transaction = getTransaction();
+ if (transaction != null) {
+ Object key = transaction;
+ Connection connection = connectionMap.get(key);
+ if (connection == null) {
+ XAConnection xaConnection = wrappedDS.getXAConnection();
+ connection = xaConnection.getConnection();
+ enlist(transaction, xaConnection.getXAResource(), key);
+ connectionMap.put(key, connection);
+ }
+ return getEnlistedConnection(connection, true);
+ } else {
+ return getEnlistedConnection(wrappedDS.getXAConnection().getConnection(), false);
+ }
+ }
+
+ public Connection getConnection(String username, String password) throws SQLException {
+ Transaction transaction = getTransaction();
+ if (transaction != null) {
+ Object key = new ConnectionKey(username, password, transaction);
+ Connection connection = connectionMap.get(key);
+ if (connection == null) {
+ XAConnection xaConnection = wrappedDS.getXAConnection(username, password);
+ connection = xaConnection.getConnection();
+ enlist(transaction, xaConnection.getXAResource(), key);
+ connectionMap.put(key, connection);
+ }
+ return getEnlistedConnection(connection, true);
+ } else {
+ return getEnlistedConnection(wrappedDS.getXAConnection(username, password).getConnection(), false);
+ }
+ }
+
+ private Transaction getTransaction() throws SQLException {
+ try {
+ return (OSGiTransactionManager.get().getStatus() == Status.STATUS_ACTIVE) ?
+ (Transaction)OSGiTransactionManager.get().getTransaction() : null;
+ } catch (SystemException e) {
+ throw new SQLException(NLS.MESSAGES.getMessage("unable.to.get.tx"), e);
+ }
+ }
+
+ private void enlist(Transaction transaction, XAResource xaResource, Object key) throws SQLException {
+ try {
+ transaction.enlistResource(xaResource);
+ transaction.registerSynchronization(new TransactionListener(key));
+ } catch (Exception e) {
+ try {
+ OSGiTransactionManager.get().setRollbackOnly();
+ } catch (IllegalStateException e1) {
+ e1.printStackTrace();
+ } catch (SystemException e1) {
+ e1.printStackTrace();
+ }
+ }
+ }
+
+ private class TransactionListener implements Synchronization {
+
+ private final Object key;
+
+ public TransactionListener(Object key) {
+ this.key = key;
+ }
+
+ public void afterCompletion(int status) {
+ Connection connection = connectionMap.remove(key);
+ if (connection != null) {
+ try {
+ connection.close();
+ } catch (SQLException e) {
+ // ignore
+ }
+ }
+ }
+
+ public void beforeCompletion() {
+ }
+
+ }
+
+ public PrintWriter getLogWriter() throws SQLException
+ {
+ return wrappedDS.getLogWriter();
+ }
+
+ public int getLoginTimeout() throws SQLException
+ {
+ return wrappedDS.getLoginTimeout();
+ }
+
+ public void setLogWriter(PrintWriter out) throws SQLException
+ {
+ wrappedDS.setLogWriter(out);
+ }
+
+ public void setLoginTimeout(int seconds) throws SQLException
+ {
+ wrappedDS.setLoginTimeout(seconds);
+ }
+
+ private Connection getEnlistedConnection(Connection connection, boolean enlisted) throws SQLException
+ {
+ return new ConnectionWrapper(connection, enlisted);
+ }
+
+
+ @Override
+ public boolean equals(Object other)
+ {
+ if (other == this) return true;
+ if (other == null) return false;
+
+ if (other.getClass() == this.getClass()) {
+ return wrappedDS.equals(((XADatasourceEnlistingWrapper)other).wrappedDS);
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return wrappedDS.hashCode();
+ }
+
+ public boolean isWrapperFor(Class<?> arg0) throws SQLException
+ {
+ return false;
+ }
+
+ public <T> T unwrap(Class<T> arg0) throws SQLException
+ {
+ return null;
+ }
+}
Modified: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/DataSourceFactoryDataSource.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/DataSourceFactoryDataSource.java?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/DataSourceFactoryDataSource.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/DataSourceFactoryDataSource.java Thu Sep 8 15:15:29 2011
@@ -42,12 +42,13 @@ public class DataSourceFactoryDataSource
private final String driverName;
private final Bundle persistenceBundle;
private final Properties props;
+ private final boolean jta;
private final AtomicReference<SingleServiceTracker<DataSourceFactory>> trackerRef =
new AtomicReference<SingleServiceTracker<DataSourceFactory>>();
public DataSourceFactoryDataSource(Bundle bundle, String driverName, String dbURL,
- String dbUserName, String dbPassword) {
+ String dbUserName, String dbPassword, boolean jta) {
this.persistenceBundle = bundle;
this.driverName = driverName;
props = new Properties();
@@ -57,6 +58,8 @@ public class DataSourceFactoryDataSource
props.setProperty(DataSourceFactory.JDBC_USER, dbUserName);
if(dbPassword != null)
props.setProperty(DataSourceFactory.JDBC_PASSWORD, dbPassword);
+
+ this.jta = jta;
}
@Override
@@ -82,7 +85,11 @@ public class DataSourceFactoryDataSource
DataSourceFactory dsf = tracker.getService();
if(dsf != null) {
try {
- ds.compareAndSet(null, dsf.createDataSource(props));
+ if(jta) {
+ ds.compareAndSet(null, wrapXADataSource(dsf.createXADataSource(props)));
+ } else {
+ ds.compareAndSet(null, dsf.createDataSource(props));
+ }
} catch (SQLException e) {
String message = NLS.MESSAGES.getMessage("datasourcefactory.sql.exception", driverName, props,
persistenceBundle.getSymbolicName(), persistenceBundle.getVersion());
Modified: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/DelayedLookupDataSource.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/DelayedLookupDataSource.java?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/DelayedLookupDataSource.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/DelayedLookupDataSource.java Thu Sep 8 15:15:29 2011
@@ -23,6 +23,10 @@ import java.sql.Connection;
import java.sql.SQLException;
import javax.sql.DataSource;
+import javax.sql.XADataSource;
+
+import org.apache.aries.jpa.container.impl.NLS;
+import org.apache.aries.jpa.container.tx.impl.XADatasourceEnlistingWrapper;
public abstract class DelayedLookupDataSource implements DataSource {
@@ -60,4 +64,19 @@ public abstract class DelayedLookupDataS
public <T> T unwrap(Class<T> iface) throws SQLException {
return getDs().unwrap(iface);
}
+
+ protected DataSource wrapXADataSource(XADataSource xaDs) throws IllegalStateException {
+ boolean b;
+ try {
+ Class.forName("javax.transaction.TransactionManager");
+ b = true;
+ } catch (ClassNotFoundException cnfe) {
+ b = false;
+ }
+
+ if(!b)
+ throw new IllegalStateException(NLS.MESSAGES.getMessage("no.xa.wrapping"));
+
+ return new XADatasourceEnlistingWrapper(xaDs);
+ }
}
Modified: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/JndiDataSource.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/JndiDataSource.java?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/JndiDataSource.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/JndiDataSource.java Thu Sep 8 15:15:29 2011
@@ -24,6 +24,7 @@ import java.util.concurrent.atomic.Atomi
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
+import javax.sql.XADataSource;
import org.apache.aries.jpa.container.impl.NLS;
import org.osgi.framework.Bundle;
@@ -38,11 +39,15 @@ public class JndiDataSource extends Dela
private AtomicReference<DataSource> ds = new AtomicReference<DataSource>();
private final String jndiName;
+ private final String unitName;
private final Bundle persistenceBundle;
+ private final boolean jta;
- public JndiDataSource (String jndi, Bundle persistenceBundle) {
+ public JndiDataSource (String jndi, String unit, Bundle persistenceBundle, boolean jta) {
jndiName = jndi;
+ unitName = unit;
this.persistenceBundle = persistenceBundle;
+ this.jta = jta;
}
@Override
@@ -56,7 +61,25 @@ public class JndiDataSource extends Dela
throw new IllegalStateException(NLS.MESSAGES.getMessage("persistence.bundle.not.active", persistenceBundle.getSymbolicName(), persistenceBundle.getVersion()));
props.put("osgi.service.jndi.bundleContext", bCtx);
InitialContext ctx = new InitialContext(props);
- ds.compareAndSet(null, (DataSource) ctx.lookup(jndiName));
+
+ Object o = ctx.lookup(jndiName);
+
+ if(o instanceof XADataSource) {
+ if(jta) {
+ ds.compareAndSet(null, wrapXADataSource((XADataSource)o));
+ } else {
+ if(o instanceof DataSource)
+ ds.compareAndSet(null, (DataSource)o);
+ else
+ throw new IllegalArgumentException(NLS.MESSAGES.getMessage("xa.datasource.non.tx", unitName,
+ persistenceBundle.getSymbolicName(), persistenceBundle.getVersion(), jndiName));
+ }
+ } else if (o instanceof DataSource) {
+ ds.compareAndSet(null, (DataSource)o);
+ } else {
+ throw new IllegalArgumentException(NLS.MESSAGES.getMessage("not.a.datasource", unitName,
+ persistenceBundle.getSymbolicName(), persistenceBundle.getVersion(), jndiName));
+ }
} catch (NamingException e) {
String message = NLS.MESSAGES.getMessage("no.data.source.found", jndiName, persistenceBundle.getSymbolicName(), persistenceBundle.getVersion());
_logger.error(message, e);
Modified: aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/PersistenceUnitInfoImpl.java
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/PersistenceUnitInfoImpl.java?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/PersistenceUnitInfoImpl.java (original)
+++ aries/trunk/jpa/jpa-container/src/main/java/org/apache/aries/jpa/container/unit/impl/PersistenceUnitInfoImpl.java Thu Sep 8 15:15:29 2011
@@ -129,7 +129,8 @@ public class PersistenceUnitInfoImpl imp
String jndiString = (String) unit.getPersistenceXmlMetadata().get(ParsedPersistenceUnit.JTA_DATASOURCE);
DataSource toReturn = null;
if(jndiString != null) {
- toReturn = new JndiDataSource(jndiString, bundle);
+ toReturn = new JndiDataSource(jndiString, getPersistenceUnitName(), bundle,
+ getTransactionType() == PersistenceUnitTransactionType.JTA);
} else if(useDataSourceFactory) {
toReturn = jtaDSFDS.get();
if(toReturn == null) {
@@ -143,7 +144,8 @@ public class PersistenceUnitInfoImpl imp
jtaDSFDS.compareAndSet(null, new DataSourceFactoryDataSource(bundle, driverName,
props.getProperty("javax.persistence.jdbc.url"),
props.getProperty("javax.persistence.jdbc.user"),
- props.getProperty("javax.persistence.jdbc.password")));
+ props.getProperty("javax.persistence.jdbc.password"),
+ getTransactionType() == PersistenceUnitTransactionType.JTA));
toReturn = jtaDSFDS.get();
}
}
@@ -184,7 +186,7 @@ public class PersistenceUnitInfoImpl imp
String jndiString = (String) unit.getPersistenceXmlMetadata().get(ParsedPersistenceUnit.NON_JTA_DATASOURCE);
DataSource toReturn = null;
if(jndiString != null) {
- toReturn = new JndiDataSource(jndiString, bundle);
+ toReturn = new JndiDataSource(jndiString, getPersistenceUnitName(), bundle, false);
} else if(useDataSourceFactory) {
toReturn = nonJtaDSFDS.get();
if(toReturn == null) {
@@ -198,7 +200,8 @@ public class PersistenceUnitInfoImpl imp
nonJtaDSFDS.compareAndSet(null, new DataSourceFactoryDataSource(bundle, driverName,
props.getProperty("javax.persistence.jdbc.url"),
props.getProperty("javax.persistence.jdbc.user"),
- props.getProperty("javax.persistence.jdbc.password")));
+ props.getProperty("javax.persistence.jdbc.password"),
+ false));
toReturn = nonJtaDSFDS.get();
}
}
Modified: aries/trunk/jpa/jpa-container/src/main/resources/org/apache/aries/jpa/container/nls/jpaContainerMessages.properties
URL: http://svn.apache.org/viewvc/aries/trunk/jpa/jpa-container/src/main/resources/org/apache/aries/jpa/container/nls/jpaContainerMessages.properties?rev=1166736&r1=1166735&r2=1166736&view=diff
==============================================================================
--- aries/trunk/jpa/jpa-container/src/main/resources/org/apache/aries/jpa/container/nls/jpaContainerMessages.properties (original)
+++ aries/trunk/jpa/jpa-container/src/main/resources/org/apache/aries/jpa/container/nls/jpaContainerMessages.properties Thu Sep 8 15:15:29 2011
@@ -186,4 +186,19 @@ using.datasource.factory=The persistence
# {0} The datasourcefactory class
# {1} The bundle symbolic name.
# {2} The bundle version.
-no.datasource.factory=No DataSourceFactory service is available for the JDBC driver class {0}. Persistence bundle {1}/{2} is trying to create that DataSource and cannot. One or more persistence units will be unusable until this DataSourceFactory is available.
\ No newline at end of file
+no.datasource.factory=No DataSourceFactory service is available for the JDBC driver class {0}. Persistence bundle {1}/{2} is trying to create that DataSource and cannot. One or more persistence units will be unusable until this DataSourceFactory is available.
+datasource.enlised.commit=This datasource is enrolled in a JTA transaction and can only be committed by the JTA transaction manager.
+datasource.enlised.rollback=This datasource is enrolled in a JTA transaction and can only be rolledback by the JTA transaction manager.
+datasource.enlised.savepoint=This datasource is enrolled in a JTA transaction and does not support savepoint.
+unable.to.get.tx=An error occurred while getting the current transaction.
+unable.to.get.tx.mgr=No TransactionManager is currently available.
+# {0} The name of the persistence unit.
+# {1} The symbolic name of the persistence bundle.
+# {2} The version of the persistence bundle.
+# {3} The jndi name of the datasource
+xa.datasource.non.tx=The persistence unit {0} in persistence bundle {1}/{2} uses a JNDI name {3} that looks up an XADataSource. The persistence unit is not JTA integrated so an XADataSource cannot be used.
+# {0} The name of the persistence unit.
+# {1} The symbolic name of the persistence bundle.
+# {2} The version of the persistence bundle.
+# {3} The jndi name of the datasource
+not.a.datasource=The persistence unit {0} in persistence bundle {1}/{2} uses a JNDI name {3} that looks up an Objet that is not a DataSource or XADataSource.
\ No newline at end of file