User: azakkerman
Date: 01/05/22 15:12:57
Added: src/main/org/jboss/tm/plugins/tyrex CoordinatorInvoker.java
CoordinatorRemote.java
CoordinatorRemoteInterface.java
ResourceInvoker.java ResourceRemote.java
ResourceRemoteInterface.java
TransactionManagerService.java
TransactionManagerServiceMBean.java
TyrexTransactionPropagationContextManager.java
TyrexTxPropagationContext.java
Log:
Initial commit of Tyrex distributed transaction manager support in JBoss. Support
added for using JBoss with any TM that supports javax.transaction.TransactionManager
interface.
Revision Changes Path
1.1
jboss/src/main/org/jboss/tm/plugins/tyrex/CoordinatorInvoker.java
Index: CoordinatorInvoker.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.tm.plugins.tyrex;
// We need this to make a proxy for the OMG Coordinator for the remote site
import java.lang.reflect.Proxy;
import java.lang.reflect.Method;
// OMG CORBA related stuff (used by Tyrex for transaction context propagation)
import org.omg.CosTransactions.Coordinator;
import org.omg.CosTransactions.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import java.io.Externalizable;
import java.io.IOException;
import org.jboss.logging.Logger;
/**
* This is the InvocationHandler for the Proxy to the originator's Coordinator.
* We allow only register_resource() method to be called to register the
* subordinate transaction as a Resource with the Coordinator.
*
* @see org.omg.CosTransactions.Coordinator#register_resource,
* java.lang.reflect.Proxy,
* java.lang.reflect.InvocationHandler,
* CoordinatorRemote,
* ResourceRemote
* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
* @version $Revision: 1.1 $
*/
class CoordinatorInvoker implements InvocationHandler, Externalizable {
private static Method register_resource;
static {
try {
register_resource = Coordinator.class.getMethod("register_resource",
new Class[]
{Resource.class});
}
catch (Exception e) {
e.printStackTrace();
}
}
private CoordinatorRemoteInterface remoteCoordinator;
public CoordinatorInvoker() {
// for externalization to work
}
protected CoordinatorInvoker (Coordinator coord) {
try {
remoteCoordinator = new CoordinatorRemote(coord);
} catch (Exception e) {
e.printStackTrace();
Logger.warning("CoordinatorInvoker could not instantiate properly, there
will be problems with this transaction!");
}
}
public void writeExternal(java.io.ObjectOutput out) throws IOException {
out.writeObject(remoteCoordinator);
}
public void readExternal(java.io.ObjectInput in) throws IOException,
ClassNotFoundException{
remoteCoordinator = (CoordinatorRemoteInterface) in.readObject();
}
public Object invoke (Object proxy, Method method, Object[] args)
throws Throwable {
if (method.equals(register_resource)) {
// Wrap the Resource in a serializable Proxy and ship it with the
// call to the CoordinatorRemote
Resource serializableResource =
(Resource) Proxy.newProxyInstance (getClass().getClassLoader(),
new Class[] {Resource.class},
new ResourceInvoker((Resource)
args[0])); // args should be not null
// DEBUG Logger.debug("TyrexTxPropagationContex: Created Proxy
for Resource, calling Proxy for Coordinator");
// call our Coordinator
remoteCoordinator.register_resource(serializableResource);
// register_resource in our remoteCoordinator is a 'void' method call
// we ignore the RecoveryCoordinator for now
return null;
}
else {
// all this trickery was only for the purpose of the remote
// Tyrex instance being able to register it's transaction as a
// resource, so we do not support any other methods besides
"register_resource"
throw new Exception("CoordinatorInvoker Proxy was called through an
unknown method");
}
}
}
1.1 jboss/src/main/org/jboss/tm/plugins/tyrex/CoordinatorRemote.java
Index: CoordinatorRemote.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.tm.plugins.tyrex;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.lang.reflect.Proxy;
import org.omg.CosTransactions.Coordinator;
import org.omg.CosTransactions._CoordinatorImplBase;
import org.omg.CosTransactions.RecoveryCoordinator;
import org.omg.CosTransactions.Resource;
import org.omg.CosTransactions.Inactive;
import org.jboss.logging.Logger;
/**
* RMI Remote Proxy that enables the remote Transaction Manager
* to register the subordinate transaction as a resource
* with the originator's Coordinator
*
* @see CoordinatorRemoteInterface, CoordinatorInvoker, ResourceRemote
* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
* @version $Revision: 1.1 $
*/
public class CoordinatorRemote extends java.rmi.server.UnicastRemoteObject
implements CoordinatorRemoteInterface {
private org.omg.CosTransactions._CoordinatorImplBase localCoordinator;
protected CoordinatorRemote(Coordinator coord) throws RemoteException {
localCoordinator = (org.omg.CosTransactions._CoordinatorImplBase) coord;
}
public void register_resource(Resource serializableResource) throws Inactive,
RemoteException {
// DEBUG Logger.debug("CoordinatorRemote: Registering resource");
RecoveryCoordinator recoveryCoord =
localCoordinator.register_resource(serializableResource);
// ignore the recovery coordinator for now
// DEBUG Logger.debug("CoordinatorRemote: Resource registered");
}
}
1.1
jboss/src/main/org/jboss/tm/plugins/tyrex/CoordinatorRemoteInterface.java
Index: CoordinatorRemoteInterface.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.tm.plugins.tyrex;
import java.rmi.Remote;
import java.lang.reflect.Proxy;
import java.rmi.RemoteException;
import org.omg.CosTransactions.Resource;
import org.omg.CosTransactions.Inactive;
/**
* Subset of the org.omg.CosTransactions.Coordinator interface
* necessary to register a remote subordinate transaction
*
* @see org.omg.CosTransactions.Coordinator,
* org.omg.CosTransactions.Resource,
* CoordinatorRemote
* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
* @version $Revision: 1.1 $
*/
public interface CoordinatorRemoteInterface extends Remote {
public void register_resource(Resource serializableResource) throws Inactive,
RemoteException;
}
1.1 jboss/src/main/org/jboss/tm/plugins/tyrex/ResourceInvoker.java
Index: ResourceInvoker.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.tm.plugins.tyrex;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import org.omg.CosTransactions.Coordinator;
import org.omg.CosTransactions.Resource;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationHandler;
import java.io.Externalizable;
import java.io.IOException;
import org.jboss.logging.Logger;
/**
* This is the InvocationHandler for the Proxy we hand over to the
* originator's Coordinator to control our subordinate transaction
*
* @see org.omg.CosTransactions.Resource,
* java.lang.reflect.Proxy,
* java.lang.reflect.InvocationHandler,
* ResourceRemote,
* CoordinatorRemote
* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
* @version $Revision: 1.1 $
*/
public class ResourceInvoker implements InvocationHandler, Externalizable {
private static Method prepare;
private static Method rollback;
private static Method commit;
private static Method commit_one_phase;
private static Method forget;
static {
try {
// get all the methods through which we may get called
prepare = Resource.class.getMethod("prepare", null);
rollback = Resource.class.getMethod("rollback", null);
commit = Resource.class.getMethod("commit", null);
commit_one_phase = Resource.class.getMethod("commit_one_phase", null);
forget = Resource.class.getMethod("forget", null);
}
catch (Exception e) {
e.printStackTrace();
}
}
private ResourceRemoteInterface remoteResource;
public ResourceInvoker() {
// for externalization to work
}
public ResourceInvoker(Resource res) {
try {
remoteResource = new ResourceRemote(res);
} catch (Exception e) {
e.printStackTrace();
remoteResource = null;
Logger.warning("ResourceInvoker did not initialize properly! Ther will be
problems with this transaction!");
}
}
public void writeExternal(java.io.ObjectOutput out) throws IOException {
out.writeObject(remoteResource);
}
public void readExternal(java.io.ObjectInput in) throws IOException,
ClassNotFoundException {
this.remoteResource = (ResourceRemoteInterface) in.readObject();
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
// Just call the appropriate method on our RemoteCoordinator
if (method.equals(prepare)) {
// DEBUG Logger.debug("ResourceInvoker: calling prepare()");
remoteResource.prepare();
return null;
}
else if (method.equals(rollback)) {
// DEBUG Logger.debug("ResourceInvoker: calling rollback()");
remoteResource.rollback();
return null;
}
else if (method.equals(commit)) {
// DEBUG Logger.debug("ResourceInvoker: calling commit()");
remoteResource.commit();
return null;
}
else if (method.equals(commit_one_phase)) {
// DEBUG Logger.debug("ResourceInvoker: calling commit_one_phase()");
remoteResource.commit_one_phase();
return null;
}
else if (method.equals(forget)) {
// DEBUG Logger.debug("ResourceInvoker: calling forget()");
remoteResource.forget();
return null;
}
else {
throw new Exception("ResourceInvoker: called through an unknown method!");
}
}
}
1.1 jboss/src/main/org/jboss/tm/plugins/tyrex/ResourceRemote.java
Index: ResourceRemote.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.tm.plugins.tyrex;
import java.rmi.RemoteException;
import org.omg.CosTransactions.HeuristicCommit;
import org.omg.CosTransactions.HeuristicMixed;
import org.omg.CosTransactions.HeuristicHazard;
import org.omg.CosTransactions.HeuristicRollback;
import org.omg.CosTransactions.NotPrepared;
import org.omg.CosTransactions.Vote;
import org.omg.CosTransactions.Resource;
import org.omg.CosTransactions._ResourceImplBase;
import org.jboss.logging.Logger;
/**
* RMI Remote Proxy that enables the Coordinator on the originating
* side to control the subordinate transaction
*
* @see ResourceRemoteInterface, ResourceInvoker, CoordinatorRemote
* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
* @version $Revision: 1.1 $
*/
public class ResourceRemote extends java.rmi.server.UnicastRemoteObject implements
ResourceRemoteInterface {
private _ResourceImplBase localResource;
protected ResourceRemote(Resource resource) throws RemoteException{
localResource = (_ResourceImplBase) resource;
}
public Vote prepare() throws HeuristicMixed, HeuristicHazard, RemoteException {
//DEBUG Logger.debug("ResourceRemote: preparing ...");
return localResource.prepare();
}
public void rollback() throws HeuristicCommit, HeuristicMixed, HeuristicHazard,
RemoteException {
//DEBUG Logger.debug("ResourceRemote: rolling back ...");
localResource.rollback();
//DEBUG Logger.debug("ResourceRemote: rolled back.");
}
public void commit() throws NotPrepared, HeuristicRollback,
HeuristicMixed, HeuristicHazard, RemoteException {
//DEBUG Logger.debug("ResourceRemote: committing ...");
localResource.commit();
//DEBUG Logger.debug("ResourceRemote: committed.");
}
public void commit_one_phase() throws HeuristicHazard, RemoteException {
//DEBUG Logger.debug("ResourceRemote: One phase committing ...");
localResource.commit_one_phase();
//DEBUG Logger.debug("ResourceRemote: committed.");
}
public void forget() throws RemoteException{
//DEBUG Logger.debug("ResourceRemote: forgetting ...");
localResource.forget();
//DEBUG Logger.debug("ResourceRemote: forgot.");
}
}
1.1
jboss/src/main/org/jboss/tm/plugins/tyrex/ResourceRemoteInterface.java
Index: ResourceRemoteInterface.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.tm.plugins.tyrex;
import java.rmi.Remote;
import java.rmi.RemoteException;
import org.omg.CosTransactions.HeuristicCommit;
import org.omg.CosTransactions.HeuristicMixed;
import org.omg.CosTransactions.HeuristicHazard;
import org.omg.CosTransactions.HeuristicRollback;
import org.omg.CosTransactions.NotPrepared;
import org.omg.CosTransactions.Vote;
/**
* Subset of org.omg.CosTransactions.Resource interface
* that is necessary for the originator's Coordinator to control
* the subordinate remote transaction's completion/rollback
*
* @see org.omg.CosTransactions.Resource, ResourceRemote
* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
* @version $Revision: 1.1 $
*/
interface ResourceRemoteInterface extends Remote {
public Vote prepare() throws HeuristicMixed, HeuristicHazard, RemoteException;
public void rollback() throws HeuristicCommit, HeuristicMixed, HeuristicHazard,
RemoteException;
public void commit() throws NotPrepared, HeuristicRollback,
HeuristicMixed, HeuristicHazard, RemoteException;
public void commit_one_phase() throws HeuristicHazard, RemoteException;
public void forget() throws RemoteException;
}
1.1
jboss/src/main/org/jboss/tm/plugins/tyrex/TransactionManagerService.java
Index: TransactionManagerService.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.tm.plugins.tyrex;
import java.io.File;
import java.net.URL;
import java.rmi.server.UnicastRemoteObject;
import java.rmi.RemoteException;
import java.rmi.ServerException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Hashtable;
import javax.naming.InitialContext;
import javax.naming.Context;
import javax.naming.Reference;
import javax.naming.Name;
import javax.naming.NamingException;
import javax.naming.NameParser;
import javax.naming.spi.ObjectFactory;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.transaction.TransactionManager;
import tyrex.tm.TransactionDomain;
import org.omg.CosTransactions.PropagationContext;
import org.omg.CosTransactions.TransactionFactory;
import org.omg.CosTSPortability.Sender;
import org.omg.CosTSPortability.Receiver;
import org.jboss.logging.Logger;
import org.jboss.util.ServiceMBeanSupport;
/**
* This is a JMX service which manages the Tyrex TransactionManager
(tyrex.exolab.org).
* The service creates it and binds a Reference to it into JNDI. It also initializes
* the object that manages Tyrex TransactionPropagationContext.
*
* @see TyrexTransactionPropagationContextManager, tyrex.tm.TransactionDomain
* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
* @version $Revision: 1.1 $
*/
public class TransactionManagerService
extends ServiceMBeanSupport
implements TransactionManagerServiceMBean, ObjectFactory
{
// Constants -----------------------------------------------------
public static String JNDI_NAME = "java:/TransactionManager";
public static String JNDI_TPC_SENDER = "java:/TPCSender";
public static String JNDI_TPC_RECEIVER = "java:/TPCReceiver";
public static String JNDI_IMPORTER =
"java:/TransactionPropagationContextImporter";
public static String JNDI_EXPORTER =
"java:/TransactionPropagationContextExporter";
// Attributes ----------------------------------------------------
MBeanServer server;
String config_file = "domain.xml";
// Static --------------------------------------------------------
static TransactionDomain txDomain = null;
static TransactionManager tm = null;
static TransactionFactory txFactory = null; //implements Sender and Receiver as
well
static TyrexTransactionPropagationContextManager tpcManager = null;
// ServiceMBeanSupport overrides ---------------------------------
public String getName()
{
return "Tyrex Transaction manager";
}
protected ObjectName getObjectName(MBeanServer server, ObjectName name)
throws javax.management.MalformedObjectNameException
{
this.server = server;
return new ObjectName(OBJECT_NAME);
}
protected void startService()
throws Exception
{
// Create txDomain singleton if we did not do it yet.
if (txDomain == null) {
txDomain = tyrex.tm.TransactionDomain.createDomain( config_file );
txDomain.recover();
tm = txDomain.getTransactionManager();
txFactory = txDomain.getTransactionFactory();
}
// Bind reference to TM in JNDI
// Tyrex TM does not implement the tx importer and exporter
// interfaces. These are handled through a different class.
bindRef(JNDI_NAME, "javax.transaction.TransactionManager");
bindRef(JNDI_TPC_SENDER, "org.omg.CosTSPortability.Sender");
bindRef(JNDI_TPC_RECEIVER, "org.omg.CosTSPortability.Receiver");
// This Manager implements the importer and exporter interfaces
// but relies on the org.omg.CosTSPortability Sender and Receiver
// to be bound in the JNDI as TPCSender and TPCReceiver
// so we can initialize it only after we bind these names to JNDI
if (tpcManager == null) {
tpcManager = new TyrexTransactionPropagationContextManager();
}
bindRef(JNDI_IMPORTER, "org.jboss.tm.TransactionPropagationContextImporter");
bindRef(JNDI_EXPORTER, "org.jboss.tm.TransactionPropagationContextFactory");
}
protected void stopService()
{
try {
// Remove TM
Context ctx = new InitialContext();
ctx.unbind(JNDI_NAME);
ctx.unbind(JNDI_TPC_SENDER);
ctx.unbind(JNDI_TPC_RECEIVER);
ctx.unbind(JNDI_IMPORTER);
ctx.unbind(JNDI_EXPORTER);
} catch (Exception e) {
log.exception(e);
}
}
public String getConfigFileName() {
return this.config_file;
}
public void setConfigFileName(String name) {
this.config_file = name;
}
// ObjectFactory implementation ----------------------------------
public Object getObjectInstance(Object obj, Name name,
Context nameCtx, Hashtable environment)
throws Exception
{
NameParser parser;
Name tmName = null;
Name senderName = null;
Name receiverName = null;
Name exporterName = null;
Name importerName = null;
if (nameCtx != null) {
parser = nameCtx.getNameParser(nameCtx.getNameInNamespace());
} else {
Context ctx = new InitialContext();
parser = ctx.getNameParser(ctx.getNameInNamespace());
}
try {
tmName = parser.parse("TransactionManager");
senderName = parser.parse("TPCSender");
receiverName = parser.parse("TPCReceiver");
exporterName = parser.parse("TransactionPropagationContextImporter");
importerName = parser.parse("TransactionPropagationContextExporter");
}
catch (NamingException e) {
e.printStackTrace();
}
// DEBUG Logger.debug("Obtaining object instance for: " + name);
// DEBUG
/*
Logger.debug("My composite names: " + tmName +
", " + senderName +
", " + receiverName +
", " + exporterName +
", " + importerName);
*/
if (name.endsWith(tmName)) {
// Return the transaction manager
return tm;
}
else if (name.endsWith(senderName) ||
name.endsWith(receiverName)) {
return txFactory;
}
else if (name.endsWith(exporterName) ||
name.endsWith(importerName)) {
return tpcManager;
}
else {
Logger.warning("TransactionManagerService: requested an unknown object:" +
name);
return null;
}
}
// Private -------------------------------------------------------
private void bindRef(String jndiName, String className)
throws Exception
{
Reference ref = new Reference(className, getClass().getName(), null);
new InitialContext().bind(jndiName, ref);
}
}
1.1
jboss/src/main/org/jboss/tm/plugins/tyrex/TransactionManagerServiceMBean.java
Index: TransactionManagerServiceMBean.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.tm.plugins.tyrex;
/**
* MBean interface for the Tyrex TransactionManager
* (not all calls are implemented)
*
* @see TransactionManagerService
* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
* @version $Revision: 1.1 $
*/
public interface TransactionManagerServiceMBean
extends org.jboss.util.ServiceMBean
{
// Constants -----------------------------------------------------
public static final String OBJECT_NAME = ":service=TransactionManager";
// Public --------------------------------------------------------
public String getConfigFileName();
public void setConfigFileName(String name);
}
1.1
jboss/src/main/org/jboss/tm/plugins/tyrex/TyrexTransactionPropagationContextManager.java
Index: TyrexTransactionPropagationContextManager.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.tm.plugins.tyrex;
import javax.naming.Name;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.Reference;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import org.jboss.logging.Logger;
import tyrex.tm.TransactionDomain;
import org.omg.CosTransactions.PropagationContextHolder;
import org.omg.CosTransactions.PropagationContext;
import org.omg.CosTSPortability.Sender;
import org.omg.CosTSPortability.Receiver;
/**
* This object implements the TransactionPropagationContext importer and
* exporter for JBoss.
*
* @see TransactionManagerService
* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
* @version $Revision: 1.1 $
*/
public class TyrexTransactionPropagationContextManager implements
org.jboss.tm.TransactionPropagationContextFactory,
org.jboss.tm.TransactionPropagationContextImporter
{
// -- Constants -------------------------------------------------------
private static String JNDI_TPC_SENDER = "java:/TPCSender";
private static String JNDI_TPC_RECEIVER = "java:/TPCReceiver";
private static String JNDI_TM = "java:/TransactionManager";
// -- Private stuff ---------------------------------------------------
private Sender sender = null;
private Receiver receiver = null;
private TransactionManager tm = null;
// -- Constructors ----------------------------------------------------
protected TyrexTransactionPropagationContextManager() {
try {
Context ctx = new InitialContext();
this.sender = (Sender) ctx.lookup(JNDI_TPC_SENDER);
this.receiver = (Receiver) ctx.lookup(JNDI_TPC_RECEIVER);
this.tm = (TransactionManager) ctx.lookup(JNDI_TM);
} catch (Exception e) {
e.printStackTrace();
}
}
// ------------ TransactionPropagationContextFactory methods ------------
/**
* Return a transaction propagation context associated with
* transaction that the calling thread came in with
*/
public Object getTransactionPropagationContext() {
Object tpc = null;
try {
if (tm.getTransaction() != null) {
PropagationContextHolder tpcHolder = new PropagationContextHolder();
sender.sending_request(0,tpcHolder);
// now modify the tpc that is inside this tpcHolder and package it
// into a serializable entity
tpc = new TyrexTxPropagationContext(tpcHolder.value);
// DEBUG Logger.debug("Exporting a transaction");
} else {
// this tpc represents a null transaction and will be propagated to remote
side
tpc = new TyrexTxPropagationContext();
// DEBUG Logger.debug("Exporting null transaction");
}
} catch (Exception e) {
// DEBUG
Logger.warning ("TyrexTransactionPropagationContextManager: unable to create
propagation ctx!");
e.printStackTrace();
} finally {
return tpc;
}
}
/**
* Return a transaction propagation context for the transaction
* given as an argument, or <code>null</code>
* if the argument is <code>null</code> or of a type unknown to
* this factory.
*/
public Object getTransactionPropagationContext(Transaction tx) {
Transaction oldTx = null;
Object tpc = null;
try {
oldTx = tm.getTransaction();
if ( (tx == null) || (tx.equals(oldTx)) ) {
// we are being called in the context of this transaction
tpc = getTransactionPropagationContext();
}
else {
tm.suspend();
tm.resume(tx);
tpc = getTransactionPropagationContext();
tm.suspend();
tm.resume(oldTx);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
return tpc;
}
}
// ------------- TransactionPropagationContextImporter methods -----------
public Transaction importTransactionPropagationContext(Object tpc) {
if (tpc instanceof TyrexTxPropagationContext) {
Transaction oldTx;
try {
// DEBUG Logger.debug ("TyrexTransactionPropagationContextManager:
importing tpc.");
oldTx = tm.suspend(); //cleanup the incoming thread
PropagationContext omgTpc = ((TyrexTxPropagationContext)
tpc).getPropagationContext();
Transaction newTx = null; // if omgTpc is null, then newTx will remain null
if (omgTpc != null) {
receiver.received_request(0, omgTpc);
// transaction gets resumed during the call
// to txFactory, since we need just the transaction object,
// get it and then suspend the transaction
newTx = tm.getTransaction();
tm.suspend();
// now restart the original transaction
if (oldTx != null)
tm.resume(oldTx);
} else {
//DEBUG Logger.debug("Importing null transaction");
}
// DEBUG Logger.debug ("TyrexTransactionPropagationContextManager:
transaction imported.");
return newTx;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
else {
Logger.warning("TyrexTransactionPropagationContextManager: unknown Tx
PropagationContex");
return null;
}
}
}
1.1
jboss/src/main/org/jboss/tm/plugins/tyrex/TyrexTxPropagationContext.java
Index: TyrexTxPropagationContext.java
===================================================================
/*
* JBoss, the OpenSource EJB server
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jboss.tm.plugins.tyrex;
import java.io.Externalizable;
import java.io.ObjectOutput;
import java.io.ObjectInput;
import java.io.IOException;
import org.jboss.logging.Logger;
// OMG CORBA related stuff (used by Tyrex for transaction context propagation)
import org.omg.CosTransactions.PropagationContext;
import org.omg.CosTransactions.TransIdentity;
import org.omg.CosTransactions.Coordinator;
import org.omg.CosTransactions.Resource;
import org.omg.CosTransactions.otid_t;
// We need this to make a proxy for the OMG Coordinator for the remote site
import java.lang.reflect.Proxy;
/**
* This class wraps the OMG PropagationContext to be able to pass it
* via RMI. Currently we are only taking care of top-level transaction
* (no nested transactions) by sending via RMI only
* - timeout value
* - otid (@see org.omg.CosTransactions.otid_t - representation of Xid)
* - Coordinator's Proxy
*
*
* @see org.omg.CosTransactions.PropagationContext,
* org.omg.CosTransactions.otid_t,
* org.omg.CosTransactions.Coordinator,
* java.lang.reflect.Proxy
* @author <a href="mailto:[EMAIL PROTECTED]">Anatoly Akkerman</a>
* @version $Revision: 1.1 $
*/
public class TyrexTxPropagationContext implements Externalizable {
public TyrexTxPropagationContext() {
// public, no args constructor for externalization to work
this.isNull = true;
}
protected TyrexTxPropagationContext (PropagationContext tpc) {
this.isNull = false; // this is not a null Propagation Context
this.timeout = tpc.timeout;
this.coord = (Coordinator) Proxy.newProxyInstance(getClass().getClassLoader(),
new Class[] {Coordinator.class},
new CoordinatorInvoker(tpc.current.coord));
this.otid = tpc.current.otid;
// DEBUG Logger.debug("TyrexTxPropagationContext: created new tpc");
}
// this is called on the remote side
protected PropagationContext getPropagationContext() {
if ( !isNull && (tpc == null) ) {
// create once
tpc = new PropagationContext( this.timeout,
new TransIdentity(this.coord,
null,
this.otid),
new TransIdentity[0], // no parents, but not null
null);
}
// DEBUG Logger.debug("TyrexTxPropagationContext recreated
PropagationContext");
return tpc;
}
public void writeExternal(ObjectOutput out) throws IOException {
try {
out.writeBoolean(this.isNull);
if (! isNull) {
out.writeInt(this.timeout);
// DEBUG Logger.debug("TPC: wrote timeout");
out.writeObject((Proxy) this.coord);
// DEBUG Logger.debug("TPC: wrote CoordinatorProxy");
out.writeObject(this.otid); // otid implements IDLEntity which extends
Serializable
// DEBUG Logger.debug("TPC: wrote otid");
}
} catch (Exception e) {
Logger.warning("Unable to externalize tpc!");
e.printStackTrace();
throw new IOException(e.toString());
}
}
public void readExternal(ObjectInput in) throws IOException,
ClassNotFoundException {
try {
this.isNull = in.readBoolean();
if (!isNull) {
this.timeout = in.readInt();
// DEBUG Logger.debug("TPC: read timeout");
this.coord = (Coordinator) in.readObject();
// DEBUG Logger.debug("TPC: read coordinator");
this.otid = (otid_t) in.readObject();
// DEBUG Logger.debug("TPC: read otid");
}
} catch (Exception e) {
e.printStackTrace();
throw new IOException (e.toString());
}
}
/*
* The fields of PropagationContext that we want to send to the remote side
*/
protected int timeout;
// this is a Proxy for the local transaction coordinator
// since we need to serialize the Coordinator and it is not serializable
protected Coordinator coord;
protected otid_t otid;
// this is a special field that gets propagated to the remote side to
// indicate that this is a null propagation context (i.e. it represents a
// null transaction). Simply using a null TyrexTxPropagationContext in RMI
// calls crashes because of NullPointerException in serialization of a
// method invocation
protected boolean isNull;
// cached copy of tpc, so that we need to create it only once
// on the remote side
protected PropagationContext tpc = null;
}
_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-development