Author: kwsutter Date: Thu Oct 26 10:08:05 2006 New Revision: 468064 URL: http://svn.apache.org/viewvc?view=rev&rev=468064 Log: First step in resolving OPENJPA-63. This change removes the usage of internal WebSphere transaction-related APIs and replaces it with the public ExtendedJTATransaction interface usage.
Added: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/ee/WASManagedRuntime.java incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/WASTransformer.java incubator/openjpa/trunk/openjpa-kernel/src/test/ incubator/openjpa/trunk/openjpa-kernel/src/test/java/ incubator/openjpa/trunk/openjpa-kernel/src/test/java/org/ incubator/openjpa/trunk/openjpa-kernel/src/test/java/org/apache/ incubator/openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/ incubator/openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/util/ incubator/openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/util/TestWASTransformer.java Modified: incubator/openjpa/trunk/openjpa-kernel/pom.xml incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/ee/AutomaticManagedRuntime.java incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/ee/localizer.properties Modified: incubator/openjpa/trunk/openjpa-kernel/pom.xml URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/pom.xml?view=diff&rev=468064&r1=468063&r2=468064 ============================================================================== --- incubator/openjpa/trunk/openjpa-kernel/pom.xml (original) +++ incubator/openjpa/trunk/openjpa-kernel/pom.xml Thu Oct 26 10:08:05 2006 @@ -1,110 +1,123 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" - xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - <groupId>org.apache.openjpa</groupId> - <artifactId>openjpa-kernel</artifactId> - <packaging>jar</packaging> - <name>OpenJPA Kernel</name> - <description>OpenJPA Kernel</description> - <url>http://incubator.apache.org/projects/openjpa</url> - <parent> - <groupId>org.apache.openjpa</groupId> - <artifactId>openjpa</artifactId> - <version>0.9.6-incubating-SNAPSHOT</version> - </parent> - <dependencies> - <dependency> - <groupId>org.apache.openjpa</groupId> - <artifactId>openjpa-lib</artifactId> - <version>${pom.version}</version> - <scope>compile</scope> - </dependency> - <dependency> - <groupId>org.apache.geronimo.specs</groupId> - <artifactId>geronimo-jms_1.1_spec</artifactId> - <version>1.0.1</version> - <scope>compile</scope> - </dependency> - <dependency> - <groupId>org.apache.geronimo.specs</groupId> - <artifactId>geronimo-j2ee-connector_1.5_spec</artifactId> - <version>1.0.1</version> - <scope>compile</scope> - </dependency> - <dependency> - <groupId>org.apache.geronimo.specs</groupId> - <artifactId>geronimo-jta_1.0.1B_spec</artifactId> - <version>1.0.1</version> - <scope>compile</scope> - </dependency> - <dependency> - <groupId>commons-pool</groupId> - <artifactId>commons-pool</artifactId> - <version>1.3</version> - <scope>compile</scope> - </dependency> - </dependencies> - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-compiler-plugin</artifactId> - <configuration> - <source>1.3</source> - <target>1.3</target> - </configuration> - </plugin> - <plugin> - <groupId>org.codehaus.mojo</groupId> - <artifactId>javacc-maven-plugin</artifactId> - <executions> - <execution> - <id>jjtree-jpql</id> - <phase>generate-sources</phase> - <configuration> - <sourceDirectory> - ${basedir}/src/main/jjtree/org/apache/openjpa/kernel/jpql</sourceDirectory> - <outputDirectory> - ${project.build.directory}/generated-sources/jjtree/org/apache/openjpa/kernel/jpql</outputDirectory> - <buildNodeFiles>false</buildNodeFiles> - </configuration> - <goals> - <goal>jjtree</goal> - </goals> - </execution> - <execution> - <id>javacc-jpql</id> - <phase>generate-sources</phase> - <configuration> - <sourceDirectory> - ${project.build.directory}/generated-sources/jjtree/org/apache/openjpa/kernel/jpql</sourceDirectory> - <outputDirectory> - ${project.build.directory}/generated-sources/javacc/org/apache/openjpa/kernel/jpql</outputDirectory> - </configuration> - <goals> - <goal>javacc</goal> - </goals> - </execution> - </executions> - </plugin> - <plugin> - <artifactId>maven-antrun-plugin</artifactId> - <executions> - <execution> - <phase>process-sources</phase> - <configuration> - <tasks> - <delete - file="${project.build.directory}/generated-sources/javacc/org/apache/openjpa/kernel/jpql/ParseException.java"/> - </tasks> - </configuration> - <goals> - <goal>run</goal> - </goals> - </execution> - </executions> - </plugin> - </plugins> - </build> -</project> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa-kernel</artifactId> + <packaging>jar</packaging> + <name>OpenJPA Kernel</name> + <description>OpenJPA Kernel</description> + <url>http://incubator.apache.org/projects/openjpa</url> + <parent> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa</artifactId> + <version>0.9.6-incubating-SNAPSHOT</version> + </parent> + <dependencies> + <dependency> + <groupId>org.apache.openjpa</groupId> + <artifactId>openjpa-lib</artifactId> + <version>${pom.version}</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-jms_1.1_spec</artifactId> + <version>1.0.1</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-j2ee-connector_1.5_spec</artifactId> + <version>1.0.1</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>org.apache.geronimo.specs</groupId> + <artifactId>geronimo-jta_1.0.1B_spec</artifactId> + <version>1.0.1</version> + <scope>compile</scope> + </dependency> + <dependency> + <groupId>commons-pool</groupId> + <artifactId>commons-pool</artifactId> + <version>1.3</version> + <scope>compile</scope> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <configuration> + <source>1.3</source> + <target>1.3</target> + </configuration> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>javacc-maven-plugin</artifactId> + <executions> + <execution> + <id>jjtree-jpql</id> + <phase>generate-sources</phase> + <configuration> + <sourceDirectory> + ${basedir}/src/main/jjtree/org/apache/openjpa/kernel/jpql</sourceDirectory> + <outputDirectory> + ${project.build.directory}/generated-sources/jjtree/org/apache/openjpa/kernel/jpql</outputDirectory> + <buildNodeFiles>false</buildNodeFiles> + </configuration> + <goals> + <goal>jjtree</goal> + </goals> + </execution> + <execution> + <id>javacc-jpql</id> + <phase>generate-sources</phase> + <configuration> + <sourceDirectory> + ${project.build.directory}/generated-sources/jjtree/org/apache/openjpa/kernel/jpql</sourceDirectory> + <outputDirectory> + ${project.build.directory}/generated-sources/javacc/org/apache/openjpa/kernel/jpql</outputDirectory> + </configuration> + <goals> + <goal>javacc</goal> + </goals> + </execution> + </executions> + </plugin> + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <phase>process-sources</phase> + <configuration> + <tasks> + <delete + file="${project.build.directory}/generated-sources/javacc/org/apache/openjpa/kernel/jpql/ParseException.java"/> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + <execution> + <id>add-was-interfaces</id> + <phase>process-classes</phase> + <configuration> + <tasks> + <java + classname="org.apache.openjpa.util.WASTransformer" classpathref="maven.runtime.classpath" /> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/ee/AutomaticManagedRuntime.java URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/ee/AutomaticManagedRuntime.java?view=diff&rev=468064&r1=468063&r2=468064 ============================================================================== --- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/ee/AutomaticManagedRuntime.java (original) +++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/ee/AutomaticManagedRuntime.java Thu Oct 26 10:08:05 2006 @@ -1,173 +1,193 @@ -/* - * Copyright 2006 The Apache Software Foundation. - * - * Licensed 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.openjpa.ee; - -import java.util.LinkedList; -import java.util.List; -import javax.transaction.TransactionManager; - -import org.apache.openjpa.lib.conf.Configurable; -import org.apache.openjpa.lib.conf.Configuration; -import org.apache.openjpa.lib.util.Localizer; -import org.apache.openjpa.util.InvalidStateException; - -/** - * Implementation of the [EMAIL PROTECTED] ManagedRuntime} interface that searches - * through a set of known JNDI locations and method invocations to locate the - * appropriate mechanism for obtaining a TransactionManager. - * Built in support is provided for the following Application Servers: - * <ul> - * <li>Bluestone</li> - * <li>HP Application Server</li> - * <li>JBoss</li> - * <li>JRun</li> - * <li>OpenEJB</li> - * <li>Oracle Application Server</li> - * <li>Orion</li> - * <li>SunONE</li> - * <li>Weblogic</li> - * <li>Websphere</li> - * </ul> - * - * @author Marc Prud'hommeaux - */ -public class AutomaticManagedRuntime - implements ManagedRuntime, Configurable { - - private static final String [] JNDI_LOCS = new String []{ - "javax.transaction.TransactionManager", // weblogic - "java:/TransactionManager", // jboss & jrun - "java:/DefaultDomain/TransactionManager", // jrun too - "java:comp/pm/TransactionManager", // orion & oracle - "java:comp/TransactionManager", // generic - "java:pm/TransactionManager", // borland - }; - private static final String [] METHODS = new String[]{ - "com.arjuna.jta.JTA_TransactionManager.transactionManager", // hp - "com.bluestone.jta.SaTransactionManagerFactory.SaGetTransactionManager", - "com.ibm.ejs.jts.jta.JTSXA.getTransactionManager", - "com.ibm.ejs.jts.jta.TransactionManagerFactory.getTransactionManager", - "com.ibm.ws.Transaction.TransactionManagerFactory." - + "getTransactionManager", // WS 5.1 - "org.openejb.OpenEJB.getTransactionManager", - "com.sun.jts.jta.TransactionManagerImpl.getTransactionManagerImpl", - "com.inprise.visitransact.jta.TransactionManagerImpl." - + "getTransactionManagerImpl", // borland - }; - private static final ManagedRuntime WLS; - private static final ManagedRuntime SUNONE; - - private static Localizer _loc = Localizer.forPackage - (AutomaticManagedRuntime.class); - - static { - ManagedRuntime mr = null; - try { - mr = new WLSManagedRuntime(); - } catch (Throwable t) { - } - WLS = mr; - - mr = null; - try { - mr = new SunOneManagedRuntime(); - } catch (Throwable t) { - } - SUNONE = mr; - } - - private Configuration _conf = null; - private ManagedRuntime _runtime = null; - - public TransactionManager getTransactionManager() - throws Exception { - if (_runtime != null) - return _runtime.getTransactionManager(); - - List errors = new LinkedList(); - TransactionManager tm = null; - - if (WLS != null) { - try { - tm = WLS.getTransactionManager(); - } catch (Throwable t) { - errors.add(t); - } - if (tm != null) { - _runtime = WLS; - return tm; - } - } - - // try to find a jndi runtime - JNDIManagedRuntime jmr = new JNDIManagedRuntime(); - for (int i = 0; i < JNDI_LOCS.length; i++) { - jmr.setTransactionManagerName(JNDI_LOCS[i]); - try { - tm = jmr.getTransactionManager(); - } catch (Throwable t) { - errors.add(t); - } - if (tm != null) { - _runtime = jmr; - return tm; - } - } - - // look for a method runtime - InvocationManagedRuntime imr = new InvocationManagedRuntime(); - for (int i = 0; i < METHODS.length; i++) { - imr.setConfiguration(_conf); - imr.setTransactionManagerMethod(METHODS[i]); - try { - tm = imr.getTransactionManager(); - } catch (Throwable t) { - errors.add(t); - } - if (tm != null) { - _runtime = imr; - return tm; - } - } - - if (SUNONE != null) { - try { - tm = SUNONE.getTransactionManager(); - } catch (Throwable t) { - errors.add(t); - } - if (tm != null) { - _runtime = SUNONE; - return tm; - } - } - - Throwable[] t = (Throwable []) errors.toArray( - new Throwable [errors.size()]); - throw new InvalidStateException(_loc.get("tm-not-found")). - setFatal(true).setNestedThrowables(t); - } - - public void setConfiguration(Configuration conf) { - _conf = conf; - } - - public void startConfiguration() { - } - - public void endConfiguration() { - } -} +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.openjpa.ee; + +import java.util.LinkedList; +import java.util.List; +import javax.transaction.TransactionManager; + +import org.apache.openjpa.lib.conf.Configurable; +import org.apache.openjpa.lib.conf.Configuration; +import org.apache.openjpa.lib.util.Localizer; +import org.apache.openjpa.util.InvalidStateException; + +/** + * Implementation of the [EMAIL PROTECTED] ManagedRuntime} interface that searches + * through a set of known JNDI locations and method invocations to locate the + * appropriate mechanism for obtaining a TransactionManager. + * Built in support is provided for the following Application Servers: + * <ul> + * <li>Bluestone</li> + * <li>HP Application Server</li> + * <li>JBoss</li> + * <li>JRun</li> + * <li>OpenEJB</li> + * <li>Oracle Application Server</li> + * <li>Orion</li> + * <li>SunONE</li> + * <li>Weblogic</li> + * <li>Websphere</li> + * </ul> + * + * @author Marc Prud'hommeaux + */ +public class AutomaticManagedRuntime + implements ManagedRuntime, Configurable { + + private static final String [] JNDI_LOCS = new String []{ + "javax.transaction.TransactionManager", // weblogic + "java:/TransactionManager", // jboss & jrun + "java:/DefaultDomain/TransactionManager", // jrun too + "java:comp/pm/TransactionManager", // orion & oracle + "java:comp/TransactionManager", // generic + "java:pm/TransactionManager", // borland + }; + private static final String [] METHODS = new String[]{ + "com.arjuna.jta.JTA_TransactionManager.transactionManager", // hp + "com.bluestone.jta.SaTransactionManagerFactory.SaGetTransactionManager", + "org.openejb.OpenEJB.getTransactionManager", + "com.sun.jts.jta.TransactionManagerImpl.getTransactionManagerImpl", + "com.inprise.visitransact.jta.TransactionManagerImpl." + + "getTransactionManagerImpl", // borland + }; + private static final ManagedRuntime WLS; + private static final ManagedRuntime SUNONE; + private static final ManagedRuntime WAS; + + private static Localizer _loc = Localizer.forPackage + (AutomaticManagedRuntime.class); + + static { + ManagedRuntime mr = null; + try { + mr = new WLSManagedRuntime(); + } catch (Throwable t) { + } + WLS = mr; + + mr = null; + try { + mr = new SunOneManagedRuntime(); + } catch (Throwable t) { + } + SUNONE = mr; + + mr = null; + try { + mr = new WASManagedRuntime(); + } + catch(Throwable t) { + + } + WAS= mr; + + } + + private Configuration _conf = null; + private ManagedRuntime _runtime = null; + + public TransactionManager getTransactionManager() + throws Exception { + if (_runtime != null) + return _runtime.getTransactionManager(); + + List errors = new LinkedList(); + TransactionManager tm = null; + + if (WLS != null) { + try { + tm = WLS.getTransactionManager(); + } catch (Throwable t) { + errors.add(t); + } + if (tm != null) { + _runtime = WLS; + return tm; + } + } + + if (WAS != null) { + try { + ((Configurable)WAS).setConfiguration(_conf); + tm = WAS.getTransactionManager(); + } catch (Throwable t) { + errors.add(t); + } + if (tm != null) { + _runtime = WAS; + return tm; + } + } + + // try to find a jndi runtime + JNDIManagedRuntime jmr = new JNDIManagedRuntime(); + for (int i = 0; i < JNDI_LOCS.length; i++) { + jmr.setTransactionManagerName(JNDI_LOCS[i]); + try { + tm = jmr.getTransactionManager(); + } catch (Throwable t) { + errors.add(t); + } + if (tm != null) { + _runtime = jmr; + return tm; + } + } + + // look for a method runtime + InvocationManagedRuntime imr = new InvocationManagedRuntime(); + for (int i = 0; i < METHODS.length; i++) { + imr.setConfiguration(_conf); + imr.setTransactionManagerMethod(METHODS[i]); + try { + tm = imr.getTransactionManager(); + } catch (Throwable t) { + errors.add(t); + } + if (tm != null) { + _runtime = imr; + return tm; + } + } + + if (SUNONE != null) { + try { + tm = SUNONE.getTransactionManager(); + } catch (Throwable t) { + errors.add(t); + } + if (tm != null) { + _runtime = SUNONE; + return tm; + } + } + + Throwable[] t = (Throwable []) errors.toArray( + new Throwable [errors.size()]); + throw new InvalidStateException(_loc.get("tm-not-found")). + setFatal(true).setNestedThrowables(t); + } + + public void setConfiguration(Configuration conf) { + _conf = conf; + } + + public void startConfiguration() { + } + + public void endConfiguration() { + } +} Added: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/ee/WASManagedRuntime.java URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/ee/WASManagedRuntime.java?view=auto&rev=468064 ============================================================================== --- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/ee/WASManagedRuntime.java (added) +++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/ee/WASManagedRuntime.java Thu Oct 26 10:08:05 2006 @@ -0,0 +1,458 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.openjpa.ee; + +import java.lang.reflect.Method; + +import javax.naming.Context; +import javax.naming.InitialContext; +import javax.naming.NamingException; +import javax.transaction.HeuristicMixedException; +import javax.transaction.HeuristicRollbackException; +import javax.transaction.InvalidTransactionException; +import javax.transaction.NotSupportedException; +import javax.transaction.RollbackException; +import javax.transaction.Status; +import javax.transaction.Synchronization; +import javax.transaction.SystemException; +import javax.transaction.Transaction; +import javax.transaction.xa.XAResource; + +import org.apache.openjpa.conf.OpenJPAConfiguration; +import org.apache.openjpa.lib.conf.Configurable; +import org.apache.openjpa.lib.conf.Configuration; +import org.apache.openjpa.lib.log.Log; +import org.apache.openjpa.lib.util.Localizer; +import org.apache.openjpa.util.InvalidStateException; +import org.apache.openjpa.util.NoTransactionException; + +/** + * [EMAIL PROTECTED] ManagedRuntime} implementation that allows synchronization with a + * WebSphere managed transaction. + * + * <P> + * WebSphere Application Server does not expose the TransactionManager to an + * application. Instead it provides a proprietary interface to register for + * synchronization and obtain transaction ids. + * + * <P> + * WASManagedRuntime provides the wrapper classes needed to interact with the + * WAS proprietary interface and the OpenJPA kernel. + * + * @author Michael Dick, Kevin Sutter + */ +public class WASManagedRuntime implements ManagedRuntime, Configurable { + + private static Localizer _loc = + Localizer.forPackage(WASManagedRuntime.class); + + protected Object _extendedTransaction = null; + + protected Method _getGlobalId = null; + + protected Method _getLocalId = null; + + protected Method _registerSync = null; + + OpenJPAConfiguration _conf = null; + + Log _log = null; + + /** + * Lookup the extendedTransaction object from JNDI. + * + * @throws NamingException + */ + private void getExtendedTransaction() throws NamingException { + + if (_extendedTransaction == null) { + Context ctx = new InitialContext(); + try { + _extendedTransaction = + ctx.lookup("java:comp/websphere/ExtendedJTATransaction"); + + } finally { + ctx.close(); + } + } + } + + /** + * Caches the WebSphere proprietary methods for ExtendedJTATransaction. + */ + private void getWebSphereMethods() throws Exception { + ClassLoader loader = + _conf.getClassResolverInstance().getClassLoader(getClass(), null); + + Class extendedJTATransaction = + Class.forName( + "com.ibm.websphere.jtaextensions.ExtendedJTATransaction", true, + loader); + + _registerSync = + extendedJTATransaction.getMethod( + "registerSynchronizationCallbackForCurrentTran", + new Class[] { Class.forName( + "com.ibm.websphere.jtaextensions.SynchronizationCallback", + true, loader) }); + + _getGlobalId = extendedJTATransaction.getMethod("getGlobalId", null); + + _getLocalId = extendedJTATransaction.getMethod("getLocalId", null); + } + + /** + * Gets an extendedJTATransaction from JNDI and creates a transaction + * wrapper + */ + public javax.transaction.TransactionManager getTransactionManager() + throws Exception { + getExtendedTransaction(); + return new WASTransaction(); + } + + /** + * Transaction wrapper for WebSphere. WebSphere exposes a subset of the + * Transaction and TransactionManager interfaces to the customer. Any + * methods which are not exposed by WebSphere will throw an + * IllegalStateException to the caller. + * + * <P> + * Methods supporded by WAS are + * <UL> + * <LI>RegisterSynchronization </LI> + * <LI>GetStatus</LI> + * </UL> + */ + class WASTransaction implements javax.transaction.TransactionManager, + javax.transaction.Transaction { + + public int getStatus() throws SystemException { + int rval = Status.STATUS_UNKNOWN; + + try { + if (getId() != null) { + rval = Status.STATUS_ACTIVE; + } else { + + if (_log != null && _log.isErrorEnabled()) { + _log.error(_loc.get("was-no-transaction")); + } + + throw new NoTransactionException(_loc + .get("was-no-transaction")); + } + } catch (Exception e) { + + if (_log != null && _log.isErrorEnabled()) { + _log.error(_loc.get("was-no-transaction"), e); + } + throw new NoTransactionException(_loc.get("was-no-transaction")) + .setCause(e); + } + return rval; + } + + /** + * Provides a Transaction wrapper. The transaction wrapper mayb only be + * used to determine the status of the current transaction. WebSphere + * does not allow direct control of container transactions. + * + * @return A WebSphere transaction wrapper. + */ + public Transaction getTransaction() throws SystemException { + return this; + } + + /** + * Register for synchronization with a WebSphere managed transaction via + * the extendedJTATransaction interface. + */ + public void registerSynchronization(Synchronization arg0) + throws IllegalStateException, RollbackException, SystemException { + + if (_extendedTransaction != null) { + try { + if (_registerSync == null) { + getWebSphereMethods(); + } + _registerSync.invoke(_extendedTransaction, + new Object[] { new WASSynchronization(arg0) }); + } catch (Exception e) { + if (_log != null && _log.isErrorEnabled()) { + _log.error(_loc.get("was-reflection-exception"), e); + } + + throw new InvalidStateException(_loc + .get("was-reflection-exception")).setCause(e); + } + } else { + if (_log != null && _log.isErrorEnabled()) { + _log.error(_loc.get("was-lookup-error")); + } + + throw new InvalidStateException(_loc.get("was-lookup-error")); + } + } + + /** + * Determines the ID of the current WebSphere managed transaction using + * the extendedJTATransaction interface + * + * @return If a GlobalTransaction is active a byte[] ID will be + * returned. If a LocalTransaction is active an int ID will be + * returned. + * + * @throws Exception + */ + private Object getId() throws Exception { + Object rval; + + rval = getGlobalId(); + + if (rval == null) { + rval = getLocalId(); + } + + if (rval instanceof Integer && ((Integer) rval).intValue() == 0) { + /* + * If there's no globalId or localId we're running outside of a + * transaction and need to throw an error. + */ + if (_log != null && _log.isErrorEnabled()) { + _log.error(_loc.get("was-no-transaction")); + } + throw new NoTransactionException(_loc.get("was-no-transaction")); + } + return rval; + } + + /** + * Gets the GlobalTransaction ID of the WebSphere managed transaction. + * If no Global Transaction is active null will be returned. + * + * @return Null if a global transaction is not active or if an error + * occurs. byte[] id if a global transaction is active. + */ + private byte[] getGlobalId() { + + byte[] rval = null; + + try { + if(_getGlobalId == null) { + getWebSphereMethods(); + } + rval = (byte[]) _getGlobalId.invoke(_extendedTransaction, null); + } catch (Exception e) { + if (_log != null && _log.isErrorEnabled()) { + _log.error(_loc.get("was-reflection-exception"), e); + } + + throw new InvalidStateException(_loc + .get("was-reflection-exception")).setCause(e); + } + + return rval; + } + + /** + * Gets the LocalTransaction ID of the WebSphere managed transaction. If + * a LocalTransaction is not active 0 will be returned. + * + * @return LocalTransaction ID. 0 if a LocalTransaction is not active or + * if an error occurs. + */ + private Integer getLocalId() { + Integer rval; + + try { + if(_getLocalId == null) { + getWebSphereMethods(); + } + rval = (Integer) _getLocalId.invoke(_extendedTransaction, null); + } catch (Exception e) { + if (_log != null && _log.isErrorEnabled()) { + _log.error(_loc.get("was-reflection-exception"), e); + } + throw new InvalidStateException(_loc + .get("was-reflection-exception")).setCause(e); + } + return rval; + } + + /** + * Unimplemented, WAS does not provide this level of control. Throws an + * IllegalStateException + */ + public void begin() throws NotSupportedException, SystemException { + throw new InvalidStateException(_loc.get("was-unsupported-op", + "begin")); + } + + /** + * Unimplemented, WAS does not provide this level of control. Throws an + * IllegalStateException + */ + public void commit() throws HeuristicMixedException, + HeuristicRollbackException, IllegalStateException, + RollbackException, SecurityException, SystemException { + throw new InvalidStateException(_loc.get("was-unsupported-op", + "commit")); + } + + /** + * Unimplemented, WAS does not provide this level of control. Throws an + * IllegalStateException + */ + public void resume(Transaction arg0) throws IllegalStateException, + InvalidTransactionException, SystemException { + throw new InvalidStateException(_loc.get("was-unsupported-op", + "resume")); + } + + /** + * Unimplemented, WAS does not provide this level of control. Throws an + * IllegalStateException + */ + public void rollback() throws IllegalStateException, SecurityException, + SystemException { + throw new InvalidStateException(_loc.get("was-unsupported-op", + "rollback")); + } + + /** + * Unimplemented, WAS does not provide this level of control. Throws an + * IllegalStateException + */ + public void setRollbackOnly() throws IllegalStateException, + SystemException { + throw new InvalidStateException(_loc.get("was-unsupported-op", + "setRollbackOnly")); + } + + /** + * Unimplemented, WAS does not provide this level of control. Throws an + * IllegalStateException + */ + public void setTransactionTimeout(int arg0) throws SystemException { + throw new InvalidStateException(_loc.get("was-unsupported-op", + "setTransactionTimeout")); + } + + /** + * Unimplemented, WAS does not provide this level of control. Throws an + * IllegalStateException + */ + public Transaction suspend() throws SystemException { + throw new InvalidStateException(_loc.get("was-unsupported-op", + "suspend")); + } + + /** + * Unimplemented, WAS does not provide this level of control. Throws an + * IllegalStateException + */ + public boolean delistResource(XAResource arg0, int arg1) + throws IllegalStateException, SystemException { + throw new InvalidStateException(_loc.get("was-unsupported-op", + "delistResource")); + } + + /** + * Unimplemented, WAS does not provide this level of control. Throws an + * IllegalStateException + */ + public boolean enlistResource(XAResource arg0) + throws IllegalStateException, RollbackException, SystemException { + throw new InvalidStateException(_loc.get("was-unsupported-op", + "enlistResource")); + } + } + + /** + * WASSynchronization wrapper. This class translates the WAS proprietary + * synchronization callback methods to javax.transaction.Synchronization + * methods. + * + * <P> + * This class implements the + * com.ibm.websphere.jtaextensions.SynchronizationCallback interface. Since + * SynchronizationCallback is not available at compile time we use Serp to + * add the interface to the class after all classes have been compiled. + * + * <P> + * SynchronizationCallback is expected to be available whenever this class + * is instantiated, therefore this class should only be used when running in + * WebSphere. + * + * @see org.apache.openjpa.util.WASTransformer + */ + static class WASSynchronization { + Synchronization _sync = null; + + WASSynchronization(Synchronization sync) { + _sync = sync; + } + + /** + * AfterCompletion wrapper. Translates the WAS proprietary call to a + * javax.transaction.Synchronization call. + */ + public void afterCompletion(int localTransactionId, + byte[] globalTransactionId, boolean committed) { + if (_sync != null) { + if (committed) { + _sync.afterCompletion(Status.STATUS_COMMITTED); + } else { + _sync.afterCompletion(Status.STATUS_UNKNOWN); + } + } + } + + /** + * BeforeCompletion wrapper. Translates WAS proprietary call to a + * javax.transaction.Synchronization call. + */ + public void beforeCompletion(int arg0, byte[] arg1) { + if (_sync != null) { + _sync.beforeCompletion(); + } + } + } + + /** + * Caches a copy of the configuration. The configuration is used to obtain + * the logger and classloader. + */ + public void setConfiguration(Configuration conf) { + _conf = (OpenJPAConfiguration) conf; + _log = _conf.getLog(OpenJPAConfiguration.LOG_RUNTIME); + } + + /** + * EndConfiguration stub. + */ + public void endConfiguration() { + // Nothing to do + } + + /** + * StartConfiguration stub. + */ + public void startConfiguration() { + // Nothing to do + } +} Added: incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/WASTransformer.java URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/WASTransformer.java?view=auto&rev=468064 ============================================================================== --- incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/WASTransformer.java (added) +++ incubator/openjpa/trunk/openjpa-kernel/src/main/java/org/apache/openjpa/util/WASTransformer.java Thu Oct 26 10:08:05 2006 @@ -0,0 +1,57 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.openjpa.util; + +import serp.bytecode.BCClass; +import serp.bytecode.Project; + +/** + * WASTransformer uses Serp to add WebSphere proprietary interface to + * WASManagedRuntime$WASSynchronization. The interface is added at build time. + * The WebSphere extensions classes must be found on the classpath whenever an + * instance of WASManagedRuntime$WASSynchronization is instantiated. + * + * @author Michael Dick + * + */ +public class WASTransformer { + + /** + * Class that will be modified + */ + public static final String _class = + "org.apache.openjpa.ee.WASManagedRuntime$WASSynchronization"; + + /** + * Interface which will be added + */ + public static final String _interface = + "com.ibm.websphere.jtaextensions.SynchronizationCallback"; + + public static void main(String[] args) { + + Project project = new Project(); + + BCClass bcClass = project.loadClass(_class); + + bcClass.declareInterface(_interface); + try { + bcClass.write(); + } catch (Exception e) { + System.err.println(e); + } + } +} Modified: incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/ee/localizer.properties URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/ee/localizer.properties?view=diff&rev=468064&r1=468063&r2=468064 ============================================================================== --- incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/ee/localizer.properties (original) +++ incubator/openjpa/trunk/openjpa-kernel/src/main/resources/org/apache/openjpa/ee/localizer.properties Thu Oct 26 10:08:05 2006 @@ -1,8 +1,31 @@ -tm-not-found: Could not perform automatic lookup of EJB container''s \ - javax.transaction.TransactionManager implementation. Please ensure that \ - you are running the application from within an EJB 1.1 compliant EJB \ - container, and then set the org.apache.openjpa.ManagedRuntime property to the \ - appropriate value to obtain the TransactionManager. -expected-reference: Expected object to be of type Reference, but instead was \ - "{0}". -not-supported: This operation is not supported. +tm-not-found: Could not perform automatic lookup of EJB container''s \ + javax.transaction.TransactionManager implementation. Please ensure that \ + you are running the application from within an EJB 1.1 compliant EJB \ + container, and then set the org.apache.openjpa.ManagedRuntime property to the \ + appropriate value to obtain the TransactionManager. +expected-reference: Expected object to be of type Reference, but instead was \ + "{0}". +not-supported: This operation is not supported. +was-unsupported-op: Unable to execute {0} on a WebSphere managed transaction. \ + WebSphere does not support direct manipulation of managed transactions. +was-no-transaction: Unable to detect a WebSphere transaction context. \ Please ensure \ + that you are running the application from within WebSphere Application Server \ + (version 5.0.2 or newer) and the application has not spun a thread. \ + If the application does manage its own threads the behavior is undefined. +was-reflection-exception: An error occured reflecting WebSphere proprietary \ + interfaces. Please ensure that you are running the application from within \ + WebSphere Application Server (version 5.0.2 or newer). +was-lookup-error: An error occurred looking up the WebSphere extended JTA \ + service. Please ensure that you are running the application from within WebSphere \ + Application Server (version 5.0.2 or newer).was-unsupported-op: Unable to execute {0} on a WebSphere managed transaction. \ + WebSphere does not support direct manipulation of managed transactions. +was-no-transaction: Unable to detect a WebSphere transaction context. \ Please ensure \ + that you are running the application from within WebSphere Application Server \ + (version 5.0.2 or newer) and the application has not spun a thread. \ + If the application does manage its own threads the behavior is undefined. +was-reflection-exception: An error occured reflecting WebSphere proprietary \ + interfaces. Please ensure that you are running the application from within \ + WebSphere Application Server (version 5.0.2 or newer). +was-lookup-error: An error occurred looking up the WebSphere extended JTA \ + service. Please ensure that you are running the application from within WebSphere \ + Application Server (version 5.0.2 or newer). \ No newline at end of file Added: incubator/openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/util/TestWASTransformer.java URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/util/TestWASTransformer.java?view=auto&rev=468064 ============================================================================== --- incubator/openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/util/TestWASTransformer.java (added) +++ incubator/openjpa/trunk/openjpa-kernel/src/test/java/org/apache/openjpa/util/TestWASTransformer.java Thu Oct 26 10:08:05 2006 @@ -0,0 +1,54 @@ +/* + * Copyright 2006 The Apache Software Foundation. + * + * Licensed 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.openjpa.util; + +import junit.framework.TestCase; + +import org.apache.openjpa.util.WASTransformer; + +/** + * Test class for WASTransformer. + * + */ +public class TestWASTransformer extends TestCase { + + /** + * This test will verify that the WASManagedRuntime$WASSynchronization + * class was properly modified by the maven build process (reference + * the top level pom.xml). This testcase will not execute properly + * within Eclipse since the Eclipse target directory (probably) hasn't + * been modified via the maven build. + * + * @throws ClassNotFoundException + * @author Michael Dick + */ + public void testInterfaceAdded()throws ClassNotFoundException { + + boolean caughtExpectedException = false; + + Class syncClass = null; + + try { + syncClass = Class.forName(WASTransformer._class); + } catch (NoClassDefFoundError e) { + if (e.getMessage().contains(WASTransformer._interface)) { + caughtExpectedException = true; + } + } + assertNull(syncClass); + assertTrue(caughtExpectedException); + } +}