[jboss-svn-commits] JBL Code SVN: r12666 - in labs/jbosstm/workspace/maciej.machulak/code/demo/app: bridge and 8 other directories.
jboss-svn-commits at lists.jboss.org
jboss-svn-commits at lists.jboss.org
Mon Jun 18 21:34:12 EDT 2007
Author: maciej.machulak
Date: 2007-06-18 21:34:12 -0400 (Mon, 18 Jun 2007)
New Revision: 12666
Added:
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/JaxWSServerHeaderContextProcessor.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BACompensatedBy.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BAService.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BAServiceType.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BATransactionAttribute.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BATransactionAttributeType.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationIdentifier.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationManagement.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationObject.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/BridgeParticipantAT.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/DummyParticipantAT.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/InboundBridge.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/JaxWSTransactionBridgeHandler.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/JaxWSTransactionSpecifierHandler.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/TxBridgeManager.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/BABridgeManager.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/CoordinatorCompletionParticipantBA.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/InboundBABridge.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/JaxWSBASpecifierHandler.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/JaxWSBusinessActivityHandler.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/ParticipantCompletionParticipantBA.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/ClassInformation.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/CompensationObject.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/MethodInformation.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/ServiceDescription.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/BAProperties.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/BATaskIdentifierFactory.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ClassBAVisitor.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ClassInformationManager.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/CompensationManager.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/CompensationService.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/JBossServiceAccessFactory.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/SOAPProcessor.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ServiceAccessFactory.java
labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/SimpleBATaskIdentifierFactory.java
Log:
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/JaxWSServerHeaderContextProcessor.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/JaxWSServerHeaderContextProcessor.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/JaxWSServerHeaderContextProcessor.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,273 @@
+package org.jboss.txbridge;
+
+import org.apache.log4j.Logger;
+
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPHandler;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+import javax.xml.namespace.QName;
+import javax.xml.soap.*;
+
+import java.util.Set;
+import java.util.HashSet;
+import java.util.Iterator;
+
+import com.arjuna.webservices.wscoor.CoordinationConstants;
+import com.arjuna.webservices.wscoor.CoordinationContextType;
+import com.arjuna.webservices.wsat.AtomicTransactionConstants;
+import com.arjuna.webservices.wsba.BusinessActivityConstants;
+import com.arjuna.mw.wst.common.CoordinationContextHelper;
+import com.arjuna.mw.wst.common.SOAPUtil;
+import com.arjuna.mw.wst.*;
+
+
+/**
+ * TODO: make this play nice alongside com.arjuna.mw.wst.service.JaxRPCHeaderContextProcessor
+ * - factor out common base class or suchlike
+ */
+public class JaxWSServerHeaderContextProcessor implements SOAPHandler
+{
+ private static Logger log = Logger.getLogger(JaxWSServerHeaderContextProcessor.class);
+
+ private String handlerName;
+
+ public String getHandlerName()
+ {
+ return handlerName;
+ }
+
+ public void setHandlerName(String handlerName)
+ {
+ this.handlerName = handlerName;
+ }
+
+ public boolean handleMessage(MessageContext msgContext)
+ {
+ Boolean outbound = (Boolean)msgContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+ if (outbound == null)
+ throw new IllegalStateException("Cannot obtain required property: " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+
+ return outbound ? handleOutbound(msgContext) : handleInbound(msgContext);
+ }
+
+
+ public boolean handleFault(MessageContext messagecontext)
+ {
+ suspendTransaction() ;
+ return true;
+ }
+
+ public void close(MessageContext messageContext)
+ {
+ }
+
+ public String toString()
+ {
+ return (handlerName != null ? handlerName : super.toString());
+ }
+
+
+
+ // The header blocks that can be processed by this Handler instance
+ private Set<QName> headers = new HashSet<QName>();
+
+ /** Gets the header blocks that can be processed by this Handler instance.
+ */
+ public Set<QName> getHeaders()
+ {
+ log.info("getHeaders");
+
+ Set<QName> headerSet = new HashSet<QName>();
+ headerSet.add(new QName(CoordinationConstants.WSCOOR_NAMESPACE, CoordinationConstants.WSCOOR_ELEMENT_COORDINATION_CONTEXT));
+
+ return headerSet;
+ }
+
+ /** Sets the header blocks that can be processed by this Handler instance.
+ */
+ public void setHeaders(Set<QName> headers)
+ {
+ this.headers = headers;
+ }
+
+
+
+ protected boolean handleInbound(MessageContext msgContext)
+ {
+ log.info("handleInbound");
+/*
+ try
+ {
+ SOAPMessage soapMessage = ((SOAPMessageContext)msgContext).getMessage();
+ SOAPHeader soapHeader = soapMessage.getSOAPHeader();
+ SOAPBody soapBody = soapMessage.getSOAPBody();
+
+ SOAPFactory soapFactory = SOAPFactory.newInstance();
+ Name headerName = soapFactory.createName("LogHandlerInbound", "ns1", "http://somens");
+ SOAPHeaderElement she = soapHeader.addHeaderElement(headerName);
+ she.setValue("true");
+
+ SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next();
+ SOAPElement soapElement = (SOAPElement)soapBodyElement.getChildElements().next();
+ String value = soapElement.getValue();
+ soapElement.setValue(value + "|LogIn");
+ }
+ catch (SOAPException e)
+ {
+ throw new WebServiceException(e);
+ }
+*/
+
+ final SOAPMessageContext soapMessageContext = (SOAPMessageContext)msgContext ;
+ final SOAPMessage soapMessage = soapMessageContext.getMessage() ;
+
+ if (soapMessage != null)
+ {
+ try
+ {
+ final SOAPEnvelope soapEnvelope = soapMessage.getSOAPPart().getEnvelope() ;
+ final SOAPHeader soapHeader = soapEnvelope.getHeader() ;
+ final SOAPHeaderElement soapHeaderElement = getHeaderElement(soapHeader, CoordinationConstants.WSCOOR_NAMESPACE, CoordinationConstants.WSCOOR_ELEMENT_COORDINATION_CONTEXT) ;
+
+ if (soapHeaderElement != null)
+ {
+ final CoordinationContextType cc = CoordinationContextHelper.deserialise(soapEnvelope, soapHeaderElement) ;
+ final String coordinationType = cc.getCoordinationType().getValue() ;
+ if (AtomicTransactionConstants.WSAT_PROTOCOL.equals(coordinationType))
+ {
+ final TxContext txContext = new com.arjuna.mwlabs.wst.at.context.TxContextImple(cc) ;
+ TransactionManagerFactory.transactionManager().resume(txContext) ;
+ clearMustUnderstand(soapHeader, soapHeaderElement) ;
+ }
+ else if (BusinessActivityConstants.WSBA_PROTOCOL_ATOMIC_OUTCOME.equals(coordinationType))
+ {
+ final TxContext txContext = new com.arjuna.mwlabs.wst.ba.context.TxContextImple(cc);
+ BusinessActivityManagerFactory.businessActivityManager().resume(txContext) ;
+ clearMustUnderstand(soapHeader, soapHeaderElement) ;
+ }
+ else
+ {
+ log.warn("handleInbound: unknown type="+coordinationType);
+ }
+ }
+ }
+ catch (final Throwable th)
+ {
+ log.warn("handleInbound: ", th);
+ }
+ }
+ return true ;
+ }
+
+
+ protected boolean handleOutbound(MessageContext msgContext)
+ {
+ log.info("handleOutbound");
+ suspendTransaction() ;
+/*
+ try
+ {
+ SOAPMessage soapMessage = ((SOAPMessageContext)msgContext).getMessage();
+ SOAPHeader soapHeader = soapMessage.getSOAPHeader();
+ SOAPBody soapBody = soapMessage.getSOAPBody();
+
+ SOAPFactory soapFactory = SOAPFactory.newInstance();
+ Name headerName = soapFactory.createName("LogHandlerOutbound", "ns1", "http://somens");
+ SOAPHeaderElement she = soapHeader.addHeaderElement(headerName);
+ she.setValue("true");
+
+ SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next();
+ SOAPElement soapElement = (SOAPElement)soapBodyElement.getChildElements().next();
+ String value = soapElement.getValue();
+ soapElement.setValue(value + "|LogOut");
+ }
+ catch (SOAPException e)
+ {
+ throw new WebServiceException(e);
+ }
+*/
+ return true;
+ }
+
+ private void suspendTransaction()
+ {
+ try
+ {
+ /*
+ * There should either be an Atomic Transaction *or* a Business Activity
+ * associated with the thread.
+ */
+ final TransactionManager transactionManager = TransactionManagerFactory.transactionManager() ;
+ final BusinessActivityManager businessActivityManager = BusinessActivityManagerFactory.businessActivityManager() ;
+
+ if (transactionManager != null)
+ {
+ transactionManager.suspend() ;
+ }
+
+ if (businessActivityManager != null)
+ {
+ businessActivityManager.suspend() ;
+ }
+ }
+ catch (final Throwable th)
+ {
+ log.warn("suspendTransaction", th);
+ }
+ }
+
+ private SOAPHeaderElement getHeaderElement(final SOAPHeader soapHeader, final String uri, final String name)
+ throws SOAPException
+ {
+ if (soapHeader != null)
+ {
+ final Iterator headerIter = SOAPUtil.getChildElements(soapHeader) ;
+ while(headerIter.hasNext())
+ {
+ final SOAPHeaderElement current = (SOAPHeaderElement)headerIter.next() ;
+ final Name currentName = current.getElementName() ;
+ if ((currentName != null) &&
+ match(name, currentName.getLocalName()) &&
+ match(uri, currentName.getURI()))
+ {
+ return current ;
+ }
+ }
+ }
+ return null ;
+ }
+
+ /**
+ * Do the two references match?
+ * @param lhs The first reference.
+ * @param rhs The second reference.
+ * @return true if the references are both null or if they are equal.
+ */
+ private boolean match(final Object lhs, final Object rhs)
+ {
+ if (lhs == null)
+ {
+ return (rhs == null) ;
+ }
+ else
+ {
+ return lhs.equals(rhs) ;
+ }
+ }
+
+ /**
+ * Clear the soap MustUnderstand.
+ * @param soapHeader The SOAP header.
+ * @param soapHeaderElement The SOAP header element.
+ */
+ private void clearMustUnderstand(final SOAPHeader soapHeader, final SOAPHeaderElement soapHeaderElement)
+ throws SOAPException
+ {
+ final Name headerName = soapHeader.getElementName() ;
+
+ final SOAPFactory factory = SOAPFactory.newInstance() ;
+ final Name attributeName = factory.createName("mustUnderstand", headerName.getPrefix(), headerName.getURI()) ;
+
+ soapHeaderElement.removeAttribute(attributeName) ;
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BACompensatedBy.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BACompensatedBy.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BACompensatedBy.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,16 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.METHOD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface BACompensatedBy
+{
+ String value();
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BAService.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BAService.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BAService.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,16 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.METHOD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface BAService
+{
+ BAServiceType value() default BAServiceType.MODIFY;
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BAServiceType.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BAServiceType.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BAServiceType.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,14 @@
+package org.jboss.txbridge.annotations;
+
+/**
+ * Author: Maciej Machulak
+ */
+public enum BAServiceType {
+ READONLY,
+ MODIFY,
+ SELFCONTAINED
+}
+
+/*
+READ_ONLY, DELETE, SELF_CONTAINED, STATE_MANAGED
+ */
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BATransactionAttribute.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BATransactionAttribute.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BATransactionAttribute.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,16 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.METHOD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface BATransactionAttribute
+{
+ BATransactionAttributeType value() default BATransactionAttributeType.PARTICIPANT_COMPLETION;
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BATransactionAttributeType.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BATransactionAttributeType.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/BATransactionAttributeType.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,10 @@
+package org.jboss.txbridge.annotations;
+
+/**
+ * Author: Maciej Machulak
+ */
+public enum BATransactionAttributeType
+{
+ PARTICIPANT_COMPLETION,
+ COORDINATOR_COMPLETION
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationIdentifier.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationIdentifier.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationIdentifier.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,15 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.FIELD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface CompensationIdentifier
+{
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationManagement.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationManagement.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationManagement.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,15 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.FIELD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface CompensationManagement
+{
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationObject.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationObject.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/annotations/CompensationObject.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,16 @@
+package org.jboss.txbridge.annotations;
+
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Author: Maciej Machulak
+ */
+ at Target(ElementType.FIELD)
+ at Retention(RetentionPolicy.RUNTIME)
+public @interface CompensationObject
+{
+ String originalMethod() default "";
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/BridgeParticipantAT.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/BridgeParticipantAT.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/BridgeParticipantAT.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,154 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2007,
+ * @author JBoss Inc.
+ */
+package org.jboss.txbridge.at;
+
+import com.arjuna.wst.*;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.XATerminatorImple;
+import org.apache.log4j.Logger;
+
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import javax.transaction.xa.XAResource;
+
+/**
+ * Provides mapping between WS-AT Participant interface
+ * and an underlying JTA subtransaction coordinator.
+ *
+ * @author jonathan.halliday at redhat.com, 2007-04-30
+ */
+public class BridgeParticipantAT implements Durable2PCParticipant
+{
+ private static Logger log = Logger.getLogger(BridgeParticipantAT.class);
+
+ private XATerminatorImple xaTerminator;
+ private Xid xid;
+
+ BridgeParticipantAT(XATerminatorImple xaTerminator, Xid xid)
+ {
+ log.info("BridgeParticipantAT(XATerminatorImple="+xaTerminator+", Xid="+xid+")");
+
+ this.xaTerminator = xaTerminator;
+ this.xid = xid;
+ }
+
+ /**
+ *
+ *
+ * Perform any work necessary to allow it to either commit or rollback
+ * the work performed by the Web service under the scope of the
+ * transaction. The implementation is free to do whatever it needs to in
+ * order to fulfill the implicit contract between it and the coordinator.
+ *
+ * @return an indication of whether it can prepare or not.
+ * @see com.arjuna.wst.Vote
+ */
+ public Vote prepare() throws WrongStateException, SystemException
+ {
+ log.info("prepare(Xid="+xid+")");
+
+ try {
+ // XAResource.XA_OK, XAResource.XA_RDONLY or exception. if RDONLY, don't call commit
+ int result = xaTerminator.prepare(xid);
+ if(result == XAResource.XA_OK) {
+ log.info("prepare on Xid="+xid+" returning Prepared");
+ return new Prepared();
+ } else {
+ log.info("prepare on Xid="+xid+" returning ReadOnly");
+ return new ReadOnly();
+ }
+
+ } catch(XAException e) {
+ log.info("prepare on Xid="+xid+" returning Aborted", e);
+ return new Aborted();
+ }
+ }
+
+ /**
+ *
+ *
+ * The participant should make permanent the work that it controls.
+ *
+ * @throws WrongStateException
+ * @throws SystemException
+ */
+ public void commit() throws WrongStateException, SystemException
+ {
+ log.info("commit(Xid="+xid+")");
+
+ try
+ {
+ xaTerminator.commit(xid, false);
+ log.info("commit on Xid="+xid+" OK");
+ }
+ catch (XAException e)
+ {
+ log.info("commit on Xid="+xid+" failed", e);
+ }
+ }
+
+ /**
+ *
+ *
+ * The participant should undo the work that it controls. The participant
+ * will then return an indication of whether or not it succeeded..
+ *
+ * @throws WrongStateException
+ * @throws SystemException
+ */
+ public void rollback() throws WrongStateException, SystemException
+ {
+ log.info("rollback(Xid="+xid+")");
+
+ try
+ {
+ xaTerminator.rollback(xid);
+ log.info("rollback on Xid="+xid+" OK");
+ }
+ catch (XAException e)
+ {
+ log.info("rollback on Xid="+xid+" failed", e);
+ }
+ }
+
+ /**
+ * During recovery the participant can enquire as to the status of the
+ * transaction it was registered with. If that transaction is no longer
+ * available (has rolled back) then this operation will be invoked by the
+ * coordination service.
+ */
+ public void unknown() throws SystemException
+ {
+ log.info("unknown(Xid="+xid+"): NOT IMPLEMENTED");
+ // used for calbacks during crash recovery. This impl is not recoverable
+ }
+
+ /**
+ * During recovery the participant can enquire as to the status of the
+ * transaction it was registered with. If an error occurs (e.g., the
+ * transaction service is unavailable) then this operation will be invoked.
+ */
+ public void error() throws SystemException
+ {
+ log.info("error(Xid="+xid+"): NOT IMPLEMENTED");
+ // used for calbacks during crash recovery. This impl is not recoverable
+ }
+}
+
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/DummyParticipantAT.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/DummyParticipantAT.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/DummyParticipantAT.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,42 @@
+package org.jboss.txbridge.at;
+
+import com.arjuna.wst.*;
+import org.apache.log4j.Logger;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class DummyParticipantAT implements Durable2PCParticipant {
+
+
+ public DummyParticipantAT() {
+ log.info("constructor");
+ }
+
+ private static Logger log = Logger.getLogger(DummyParticipantAT.class);
+
+ public Vote prepare() throws WrongStateException, SystemException {
+ log.info("prepare()");
+ return new Prepared();
+ }
+
+ public void commit() throws WrongStateException, SystemException {
+ log.info("commit()");
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void rollback() throws WrongStateException, SystemException {
+ log.info("rollback()");
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void unknown() throws SystemException {
+ log.info("unknown()");
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void error() throws SystemException {
+ log.info("error()");
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/InboundBridge.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/InboundBridge.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/InboundBridge.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,110 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2007,
+ * @author JBoss Inc.
+ */
+package org.jboss.txbridge.at;
+
+import com.arjuna.ats.internal.jta.transaction.arjunacore.subordinate.jca.TransactionImple;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.TxImporter;
+import com.arjuna.ats.jta.TransactionManager;
+
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import javax.transaction.Status;
+import javax.transaction.SystemException;
+import javax.transaction.InvalidTransactionException;
+
+
+import org.apache.log4j.Logger;
+
+/**
+ * Manages Thread association of the interposed coordinator.
+ * Typically called from handlers in the WS stack.
+ *
+ * @author jonathan.halliday at redhat.com, 2007-04-30
+ */
+public class InboundBridge
+{
+ private static Logger log = Logger.getLogger(InboundBridge.class);
+
+ private Xid xid;
+
+ InboundBridge(Xid xid) throws XAException, SystemException {
+ log.info("InboundBridge(Xid="+xid+")");
+
+ this.xid = xid;
+
+ getTransaction(); // ensures transaction is initialized
+ }
+
+ /**
+ * Associate the JTA transaction to the current Thread.
+ * Typically used by a server side inbound handler.
+ *
+ * @throws XAException
+ * @throws SystemException
+ * @throws InvalidTransactionException
+ */
+ public void start() throws XAException, SystemException, InvalidTransactionException {
+ log.info("start(Xid="+xid+")");
+
+ TransactionImple tx = getTransaction();
+
+ TransactionManager.transactionManager().resume(tx);
+ }
+
+ /**
+ * Disassociate the JTA transaction from the current Thread.
+ * Typically used by a server side outbound handler.
+ *
+ * @throws XAException
+ * @throws SystemException
+ * @throws InvalidTransactionException
+ */
+ public void stop() throws XAException, SystemException, InvalidTransactionException {
+ log.info("stop("+xid+")");
+
+ TransactionImple tx = getTransaction();
+
+ TransactionManager.transactionManager().suspend();
+ }
+
+ /**
+ * Get the JTA Transaction which corresponds to the Xid of the instance.
+ *
+ * @return
+ * @throws XAException
+ * @throws SystemException
+ */
+ private TransactionImple getTransaction()
+ throws XAException, SystemException
+ {
+ // TODO: make jta/jts pluggable - diff TxImporters hence InboundBridges ?
+ TransactionImple tx = TxImporter.importTransaction(xid);
+
+ switch (tx.getStatus())
+ {
+ case Status.STATUS_ACTIVE:
+ break;
+ default:
+ throw new IllegalStateException("Transaction not in state ACTIVE");
+ }
+ return tx;
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/JaxWSTransactionBridgeHandler.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/JaxWSTransactionBridgeHandler.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/JaxWSTransactionBridgeHandler.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,261 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2007,
+ * @author JBoss Inc.
+ */
+package org.jboss.txbridge.at;
+
+import javax.xml.ws.handler.Handler;
+import javax.xml.ws.handler.MessageContext;
+
+import org.apache.log4j.Logger;
+
+/**
+ * A handler that sits in the server side processing pipeline between the XTS header context processor
+ * and the web service. Takes the WS transaction context provided by the former and maps
+ * it to a JTA transaction context for use by the latter. Handles Thread association of
+ * the JTA context.
+ *
+ * Note: we assume that their is a web services transaction context present and
+ * that the service needs a JTA context. The handler should not be registered on
+ * methods unless both these conditions hold.
+ * TODO: make this more flexible (ws-at policy and/or lazy init of JTA context.)
+ *
+ * TODO: provide a JAX-RPC version of this handler too?
+ *
+ * @author jonathan.halliday at redhat.com, 2007-04-30
+ */
+public class JaxWSTransactionBridgeHandler implements Handler
+{
+ private static Logger log = Logger.getLogger(JaxWSTransactionBridgeHandler.class);
+
+ /**
+ * Process a message. Determins if it's inbound or outbound and dispatches accordingly.
+ *
+ * @param msgContext
+ * @return
+ */
+ public boolean handleMessage(MessageContext msgContext)
+ {
+ log.debug("handleMessage()");
+
+ Boolean outbound = (Boolean)msgContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+ if (outbound == null)
+ throw new IllegalStateException("Cannot obtain required property: " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+
+ return outbound ? handleOutbound(msgContext) : handleInbound(msgContext);
+ }
+
+ /**
+ * Tidy up the Transaction/Thread association before faults are thrown back to the client.
+ *
+ * @param messageContext
+ * @return
+ */
+ public boolean handleFault(MessageContext messageContext)
+ {
+ log.debug("handleFault()");
+ String transactionType = (String) messageContext.get("TransactionAttributeType");
+
+ if (transactionType == null)
+ {
+ log.info("transactionType is null");
+ return true;
+ }
+ else if ( transactionType.equals("MANDATORY"))
+ {
+ log.info("transactionType is mandatory");
+ suspendTransaction();
+ }
+ else if ( transactionType.equals("REQUIRED"))
+ {
+ log.info("transactionType is required");
+ suspendTransaction();
+ }
+ else if ( transactionType.equals("REQUIRES_NEW "))
+ {
+ log.info("transactionType is requires_new");
+ return true;
+ }
+ else if ( transactionType.equals("SUPPORTS"))
+ {
+ log.info("transactionType is supports");
+ suspendTransaction();
+ }
+ else if ( transactionType.equals("NOT_SUPPORTED"))
+ {
+ log.info("transactionType is not_supported");
+ return true;
+ }
+ return true;
+ }
+
+ public void close(MessageContext messageContext)
+ {
+ log.debug("close()");
+ }
+
+ /**
+ * Process inbound messages by mapping the WS transaction context
+ * to a JTA one and associating the latter to the current Thread.
+ *
+ * @param msgContext
+ * @return
+ */
+ protected boolean handleInbound(MessageContext msgContext)
+ {
+ log.debug("handleInbound()");
+ String transactionType = (String) msgContext.get("TransactionAttributeType");
+
+ // If there was no WS transaction
+ if (transactionType == null)
+ {
+ log.info("transactionType is null");
+ return true;
+ }
+
+ // If there is a WS transaction
+
+ // If the method must be executed within a transaction
+ if ( transactionType.equals("MANDATORY"))
+ {
+ log.info("transactionType is mandatory");
+ try
+ {
+ InboundBridge inboundBridge = org.jboss.txbridge.at.TxBridgeManager.getInboundBridge();
+ inboundBridge.start();
+ }
+ catch (Exception e)
+ {
+ log.error(e);
+ return false;
+ }
+ }
+ // If the method needs a transaction (either by client or its own)
+ else if ( transactionType.equals("REQUIRED"))
+ {
+ log.info("transactionType is required");
+ try
+ {
+ InboundBridge inboundBridge = org.jboss.txbridge.at.TxBridgeManager.getInboundBridge();
+ inboundBridge.start();
+ }
+ catch (Exception e)
+ {
+ log.error(e);
+ return false;
+ }
+ }
+ // If the method will start a new transaction anyway
+ else if ( transactionType.equals("REQUIRES_NEW "))
+ {
+ log.info("transactionType is requires_new");
+ return true;
+ }
+ // If the method does not care
+ else if ( transactionType.equals("SUPPORTS"))
+ {
+ log.info("transactionType is supports");
+ try
+ {
+ InboundBridge inboundBridge = org.jboss.txbridge.at.TxBridgeManager.getInboundBridge();
+ inboundBridge.start();
+ }
+ catch (Exception e)
+ {
+ log.error(e);
+ return false;
+ }
+
+ }
+ // If the method does not support a transaction
+ else if ( transactionType.equals("NOT_SUPPORTED"))
+ {
+ log.info("transactionType is not_supported");
+ try
+ {
+ org.jboss.txbridge.at.TxBridgeManager.startDummyTransaction();
+ }
+ catch (Exception e)
+ {
+ return false;
+ }
+ return true;
+ }
+ return true;
+ }
+
+ /**
+ * Tidy up the Transaction/Thread association before returning a message to the client.
+ *
+ * @param msgContext
+ * @return
+ */
+ protected boolean handleOutbound(MessageContext msgContext) {
+ log.debug("handleOutbound()");
+ String transactionType = (String) msgContext.get("TransactionAttributeType");
+
+ if (transactionType == null)
+ {
+ log.info("transactionType is null");
+ return true;
+ }
+ else if ( transactionType.equals("MANDATORY"))
+ {
+ suspendTransaction();
+ }
+ else if ( transactionType.equals("REQUIRED"))
+ {
+ log.info("transactionType is required");
+ suspendTransaction();
+ }
+ else if ( transactionType.equals("REQUIRES_NEW "))
+ {
+ log.info("transactionType is requires_new");
+ return true;
+ }
+ else if ( transactionType.equals("SUPPORTS"))
+ {
+ log.info("transactionType is supports");
+ suspendTransaction();
+ }
+ else if ( transactionType.equals("NOT_SUPPORTED"))
+ {
+ log.info("transactionType is not supported");
+ return true;
+ }
+ return true;
+ }
+
+ /**
+ * Break the association between the JTA transaction context and the calling Thread.
+ */
+ private void suspendTransaction() {
+ log.debug("suspendTransaction()");
+
+ try
+ {
+ InboundBridge inboundBridge = org.jboss.txbridge.at.TxBridgeManager.getInboundBridge();
+ inboundBridge.stop();
+ }
+ catch (Exception e)
+ {
+ log.error(e);
+ }
+ }
+}
\ No newline at end of file
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/JaxWSTransactionSpecifierHandler.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/JaxWSTransactionSpecifierHandler.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/JaxWSTransactionSpecifierHandler.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,149 @@
+package org.jboss.txbridge.at;
+
+import org.apache.log4j.Logger;
+import org.jboss.ws.core.soap.MessageContextAssociation;
+import org.jboss.ws.core.CommonMessageContext;
+import org.jboss.ws.metadata.umdm.EndpointMetaData;
+
+import javax.xml.ws.handler.Handler;
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.soap.SOAPBodyElement;
+import javax.xml.soap.SOAPBody;
+import javax.xml.soap.SOAPException;
+import javax.jws.WebMethod;
+import javax.ejb.TransactionAttribute;
+import javax.ejb.TransactionAttributeType;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ArrayList;
+import java.lang.reflect.Method;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class JaxWSTransactionSpecifierHandler implements Handler
+{
+ private static Logger log = Logger.getLogger(JaxWSTransactionSpecifierHandler.class);
+ private static List<String> cacheList = new ArrayList<String>();
+ private static HashMap<String,String> methodMappings = new HashMap<String,String>();
+ private static TransactionAttributeType defaultAttribute = TransactionAttributeType.REQUIRED;
+
+ public JaxWSTransactionSpecifierHandler()
+ {
+ }
+
+ public boolean handleMessage(MessageContext msgContext)
+ {
+ log.debug("handleMessage()");
+
+ Boolean outbound = (Boolean)msgContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+ if (outbound == null)
+ {
+ throw new IllegalStateException("Cannot obtain required property: " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+ }
+ return outbound ? handleOutbound(msgContext) : handleInbound(msgContext);
+ }
+
+ private boolean handleInbound(MessageContext msgContext)
+ {
+
+ log.debug("handleInbound()");
+
+ try
+ {
+
+ CommonMessageContext commonMessageContext = MessageContextAssociation.peekMessageContext();
+ EndpointMetaData emd = commonMessageContext.getEndpointMetaData();
+ Class clazz = emd.getServiceEndpointInterface();
+ log.info("Class name: " + clazz.getName());
+
+ if (!cacheList.contains(clazz.getName()))
+ {
+ // Get all the methods from the class
+ Method[] methodList = clazz.getDeclaredMethods();
+ log.info("Number of methods: " + methodList.length);
+
+ // Loop through all methods
+ for (Method singleMethod : methodList)
+ {
+ // Check what is the name of the method
+ log.info("Single method: " + singleMethod.getName());
+ String webMethodName = singleMethod.getName();
+
+ // Check if there is a WebMethod annotation
+ WebMethod webMethodAnnotation = singleMethod.getAnnotation(WebMethod.class);
+ if (webMethodAnnotation != null)
+ {
+ log.info("WebMethod annotation: " + webMethodAnnotation.operationName());
+ String name = webMethodAnnotation.operationName();
+ if (name != null && !name.equals(""))
+ {
+ webMethodName = name;
+ }
+ }
+
+ // Get the attribute of the transaction
+ String transactionType = defaultAttribute.toString();
+ TransactionAttribute txAttr = singleMethod.getAnnotation(TransactionAttribute.class);
+ if (txAttr != null)
+ {
+ log.info("TransactionAttribute annotation: " + txAttr.value());
+ // Check the type of the transaction attribute
+ TransactionAttributeType txType = txAttr.value();
+
+ if (txType != null)
+ {
+ transactionType = txType.toString();
+ }
+
+ }
+ // Add the method definition to the methodMapping list
+ log.info("Adding: (" + webMethodName + "," + transactionType + ")");
+ methodMappings.put(webMethodName,transactionType);
+
+ }
+ cacheList.add(clazz.getName());
+ }
+
+ // Get the soap method name
+ SOAPMessage soapMessage = ((SOAPMessageContext)msgContext).getMessage();
+ SOAPBody soapBody = soapMessage.getSOAPBody();
+ SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next();
+ String methodName = soapBodyElement.getElementName().getLocalName();
+
+ String transactionType = (String) methodMappings.get(methodName);
+ log.info("Mapping: (" + methodName + "," + transactionType + ")");
+
+ msgContext.put("TransactionAttributeType",transactionType);
+
+ }
+ catch (SOAPException soape)
+ {
+ soape.printStackTrace();
+ }
+ return true;
+ }
+
+ private boolean handleOutbound(MessageContext msgContext)
+ {
+ if (msgContext.containsKey("TransactionAttributeType"))
+ {
+ msgContext.remove("TransactionAttributeType");
+ }
+ return true;
+ }
+
+
+ public boolean handleFault(MessageContext messageContext)
+ {
+ log.debug("handleFault()");
+ return true;
+ }
+
+ public void close(MessageContext messageContext)
+ {
+ log.debug("close()");
+ }
+}
\ No newline at end of file
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/TxBridgeManager.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/TxBridgeManager.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/at/TxBridgeManager.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,127 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, Red Hat Middleware LLC, and individual contributors
+ * as indicated by the @author tags.
+ * See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ * This copyrighted material is made available to anyone wishing to use,
+ * modify, copy, or redistribute it subject to the terms and conditions
+ * of the GNU Lesser General Public License, v. 2.1.
+ * This program is distributed in the hope that it will be useful, but WITHOUT A
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ * You should have received a copy of the GNU Lesser General Public License,
+ * v.2.1 along with this distribution; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ * MA 02110-1301, USA.
+ *
+ * (C) 2007,
+ * @author JBoss Inc.
+ */
+package org.jboss.txbridge.at;
+
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.XATerminatorImple;
+import com.arjuna.ats.jta.xa.XidImple;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.mw.wst.UserTransactionFactory;
+
+import com.arjuna.mw.wst.TransactionManagerFactory;
+import com.arjuna.wst.WrongStateException;
+import com.arjuna.wst.UnknownTransactionException;
+import com.arjuna.wsc.AlreadyRegisteredException;
+
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+import org.apache.log4j.Logger;
+
+/**
+ * Maintains the mapping data that relates WS transactions to JTA transactions and related objects.
+ *
+ * The mappings are scoped to the singleton instance of this class and its lifetime.
+ * This poses problems where you have more than one instances (classloading, clusters)
+ * or where you need crash recovery. It short, it's rather limited.
+ *
+ * @author jonathan.halliday at redhat.com, 2007-04-30
+ */
+public class TxBridgeManager
+{
+ private static Logger log = Logger.getLogger(TxBridgeManager.class);
+
+ // TODO: make this play nice with the TransactionService in AS, particularly w.r.t recovery.
+ private static XATerminatorImple xaTerminatorImple = new XATerminatorImple();
+
+ private static ConcurrentMap<String, Xid> txIdMappings = new ConcurrentHashMap<String, Xid>();
+
+ private static ConcurrentMap<Xid, InboundBridge> inboundBridgeMappings = new ConcurrentHashMap<Xid, InboundBridge>();
+
+ private static String hello;
+ /**
+ * Create an InboundBridge instance that maps the current Thread's WS transaction context
+ * to a JTA context. Control of the latter is provided by the returned instance.
+ *
+ * @return
+ * @throws WrongStateException
+ * @throws UnknownTransactionException
+ * @throws com.arjuna.wst.SystemException
+ * @throws AlreadyRegisteredException
+ */
+ public static InboundBridge getInboundBridge()
+ throws XAException, WrongStateException, UnknownTransactionException,
+ com.arjuna.wst.SystemException, javax.transaction.SystemException, AlreadyRegisteredException
+ {
+ log.info("getInboundBridge()");
+
+ String externalTxId = UserTransactionFactory.userTransaction().toString();
+
+ Xid xid = txIdMappings.get(externalTxId);
+ if(xid == null) {
+ xid = createMappings(externalTxId);
+ }
+
+ return inboundBridgeMappings.get(xid);
+ }
+
+ /**
+ * Create the JTA transaction mapping and support objects for a given WS transaction context.
+ *
+ * @param externalTxId
+ * @return
+ * @throws WrongStateException
+ * @throws UnknownTransactionException
+ * @throws com.arjuna.wst.SystemException
+ * @throws AlreadyRegisteredException
+ */
+ private static synchronized Xid createMappings(String externalTxId)
+ throws XAException, WrongStateException, UnknownTransactionException,
+ com.arjuna.wst.SystemException, javax.transaction.SystemException, AlreadyRegisteredException {
+ log.info("createMappings(externalIxId="+externalTxId+")");
+
+ if(txIdMappings.containsKey(externalTxId)) {
+ return txIdMappings.get(externalTxId);
+ }
+
+ Xid xid = new XidImple(new Uid());
+ txIdMappings.put(externalTxId, xid);
+ inboundBridgeMappings.put(xid, new InboundBridge(xid));
+
+ // TODO: how do we tell if it's AT or BA?
+ // No implementation independent way, it requires parsind the otherwise opaque externalTxId.
+ // Probably better to have the caller (typically an handler) provide this info?
+
+ BridgeParticipantAT bridgeParticipantAT = new BridgeParticipantAT(xaTerminatorImple, xid);
+ TransactionManagerFactory.transactionManager().enlistForDurableTwoPhase(bridgeParticipantAT, new Uid().toString());
+
+ return xid;
+ }
+
+ public static synchronized void startDummyTransaction()
+ throws AlreadyRegisteredException, com.arjuna.wst.SystemException,
+ UnknownTransactionException, WrongStateException
+ {
+ DummyParticipantAT dummyParticipantAT = new DummyParticipantAT();
+ TransactionManagerFactory.transactionManager().enlistForDurableTwoPhase(dummyParticipantAT,new Uid().toString());
+ }
+}
\ No newline at end of file
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/BABridgeManager.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/BABridgeManager.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/BABridgeManager.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,157 @@
+package org.jboss.txbridge.ba;
+
+import org.apache.log4j.Logger;
+import org.jboss.txbridge.data.MethodInformation;
+import org.jboss.txbridge.helper.CompensationService;
+import com.arjuna.mw.wst.BusinessActivityManager;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.wsc.AlreadyRegisteredException;
+import com.arjuna.wst.SystemException;
+import com.arjuna.wst.UnknownTransactionException;
+import com.arjuna.wst.WrongStateException;
+import com.arjuna.wst.BAParticipantManager;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class BABridgeManager
+{
+ // Logger
+ private static Logger log = Logger.getLogger(BABridgeManager.class);
+
+ // Bridge manager
+ private volatile static BABridgeManager baBridgeManager;
+
+ // Business activity manager
+ BusinessActivityManager businessActivityManager;
+
+ // Compensation manager
+ CompensationService compensationService;
+
+ // Mappings: ba <-> participant
+ // ba <-> participant
+ private static ConcurrentMap<String,InboundBABridge> baBridges;
+
+
+ // Constructor
+ private BABridgeManager()
+ {
+ log.info("constructor()");
+
+ // Get business activity manager
+ businessActivityManager = BusinessActivityManager.getBusinessActivityManager();
+
+ // Initialise mappings
+ // - participants
+ baBridges = new ConcurrentHashMap<String,InboundBABridge>();
+
+
+ }
+
+ // Get instance of the bridge manager
+ public static BABridgeManager getSingletonInstance()
+ {
+ log.info("getSingletonInstance()");
+ if (baBridgeManager == null)
+ {
+ synchronized (BABridgeManager.class)
+ {
+ if (baBridgeManager == null)
+ {
+ log.info("Creating new instance...");
+ baBridgeManager = new BABridgeManager();
+ }
+ }
+ }
+ return baBridgeManager;
+ }
+
+ // Manage transaction for this method (service)
+ public synchronized void manageTransaction(MethodInformation methodInformation)
+ {
+ log.info("manageTransaction()");
+ String txId = null;
+ try
+ {
+ // Get the transaction identifier
+ txId = businessActivityManager.currentTransaction().toString();
+ log.info("Transaction identifier: " + txId);
+
+ // Start the participant
+ associateParticipantBA(txId,methodInformation);
+ }
+ catch (Exception se)
+ {
+ se.printStackTrace();
+ }
+
+ }
+
+ private synchronized void associateParticipantBA(String txId,MethodInformation methodInformation) throws AlreadyRegisteredException, SystemException, UnknownTransactionException, WrongStateException
+ {
+ log.info("associateParticipantBA()");
+
+ // Check if the transaction already has an associated bridge
+ // - if not than create one and pass him method's information
+ InboundBABridge baBridge = baBridges.get(txId);
+ if (baBridge == null)
+ {
+ // If not... create a new participant
+ baBridge = new InboundBABridge(txId);
+
+ // Remember the bridge
+ baBridges.put(txId,baBridge);
+
+ }
+ // - if yes then tell the bridge about another method
+ baBridge.start(methodInformation);
+
+ }
+
+ public synchronized void manageReturnObject(MethodInformation method, Object returnObject)
+ {
+ log.info("manageReturnObject()");
+ String txId = null;
+ try
+ {
+ txId = businessActivityManager.currentTransaction().toString();
+ InboundBABridge baBridge = baBridges.get(txId);
+ if (baBridge != null)
+ {
+ baBridge.addReturnObject(method.getOriginalMethod(),returnObject);
+ }
+ }
+ catch (SystemException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public synchronized void completeTransaction()
+ {
+ log.info("completeTransaction()");
+ String txId = null;
+ try
+ {
+ // Check the transaction identifier
+ txId = businessActivityManager.currentTransaction().toString();
+
+ // Get the participant manager
+ InboundBABridge baBridge = baBridges.get(txId);
+ if (baBridge != null)
+ {
+ baBridge.stop();
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+
+
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/CoordinatorCompletionParticipantBA.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/CoordinatorCompletionParticipantBA.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/CoordinatorCompletionParticipantBA.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,41 @@
+package org.jboss.txbridge.ba;
+
+import com.arjuna.wst.*;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class CoordinatorCompletionParticipantBA implements BusinessAgreementWithCoordinatorCompletionParticipant {
+
+ public void close() throws WrongStateException, SystemException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void cancel() throws WrongStateException, SystemException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void compensate() throws FaultedException, WrongStateException, SystemException
+ {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public String status() throws SystemException
+ {
+ return null; //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void unknown() throws SystemException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void error() throws SystemException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+
+ public void complete() throws WrongStateException, SystemException {
+ //To change body of implemented methods use File | Settings | File Templates.
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/InboundBABridge.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/InboundBABridge.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/InboundBABridge.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,198 @@
+package org.jboss.txbridge.ba;
+
+import com.arjuna.wst.BAParticipantManager;
+import com.arjuna.wst.WrongStateException;
+import com.arjuna.wst.UnknownTransactionException;
+import com.arjuna.wst.SystemException;
+import com.arjuna.mw.wst.BusinessActivityManager;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.wsc.AlreadyRegisteredException;
+
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+
+import org.jboss.txbridge.data.MethodInformation;
+import org.jboss.txbridge.annotations.BAServiceType;
+import org.jboss.txbridge.helper.CompensationService;
+import org.apache.log4j.Logger;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class InboundBABridge
+{
+ // Logger
+ Logger log = Logger.getLogger(InboundBABridge.class);
+
+ // Business activity manager
+ BusinessActivityManager businessActivityManager;
+
+ // Transaction identifier
+ private String txId;
+
+ // Identifiers of methods
+ private Map<String,MethodInformation> methodList;
+
+ // List of the participants for this transaction
+ private Map<MethodInformation,ParticipantCompletionParticipantBA> participantList;
+
+ // List of all return objects
+ private Map<MethodInformation,Object> returnObjects;
+
+ // List of all compensation objects
+ private Map<MethodInformation,Object[]> compensationObjects;
+
+ // List of all temporary objects
+ private Map<String,Object> temporaryObjects;
+
+
+ // List of all participant managers
+ private Map<BAParticipantManager,String> participantManagerList;
+
+ public InboundBABridge(String txId)
+ {
+ this.txId = txId;
+ methodList = new HashMap<String,MethodInformation>();
+ participantList = new HashMap<MethodInformation,ParticipantCompletionParticipantBA>();
+ returnObjects = new HashMap<MethodInformation,Object>();
+ compensationObjects = new HashMap<MethodInformation,Object[]>();
+ participantManagerList = new HashMap<BAParticipantManager,String>();
+ temporaryObjects = new HashMap<String,Object>();
+ businessActivityManager = BusinessActivityManager.getBusinessActivityManager();
+
+ // Register itself with the compensation service
+ CompensationService cs = CompensationService.getSingletonInstance();
+ cs.registerBridge(txId,this);
+
+ }
+
+ public void start(MethodInformation methodInfo)
+ {
+ log.info("start()");
+ try
+ {
+ ParticipantCompletionParticipantBA participant = new ParticipantCompletionParticipantBA(txId,methodInfo);
+ BAParticipantManager participantManager = businessActivityManager.enlistForBusinessAgreementWithParticipantCompletion(participant,new Uid().toString());
+
+ methodList.put(methodInfo.getOriginalMethod(),methodInfo);
+ participantList.put(methodInfo,participant);
+ participantManagerList.put(participantManager,methodInfo.getServiceType());
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public void stop()
+ {
+ log.info("stop()");
+ try
+ {
+ for ( BAParticipantManager pManager : participantManagerList.keySet())
+ {
+ log.info("Using participant manager.");
+ String serviceType = participantManagerList.get(pManager);
+ if (serviceType.equals("READONLY"))
+ {
+ log.info("Service was 'read-only'. Exiting...");
+ pManager.exit();
+ }
+ else if (serviceType.equals("MODIFY"))
+ {
+ log.info("Service was 'modify'. Completing...");
+ pManager.completed();
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ // Add new compensation object
+ public void addReturnObject(String methodName,Object object)
+ {
+ log.info("addReturnObject()");
+ MethodInformation methodInfo = methodList.get(methodName);
+ if (methodInfo != null)
+ {
+ returnObjects.put(methodInfo,object);
+ }
+ }
+
+ // Add new compensation object
+ public void addTemporaryObject(String methodName,String identifier, Object object)
+ {
+ log.info("addTemporaryObject()");
+ MethodInformation methodInfo = methodList.get(methodName);
+ if (methodInfo != null)
+ {
+ // Get the name of the compensation method
+ String compensationMethod = methodInfo.getCompensationMethod();
+ temporaryObjects.put(compensationMethod+identifier,object);
+ }
+ }
+
+ // Return a compensation object for a given transaction
+ public Object getTemporaryObject(String methodName,String identifier)
+ {
+ log.info("getTemporaryObject()");
+
+ return temporaryObjects.get(methodName+identifier);
+
+ }
+
+ // Return a compensation object for a given transaction
+ public Object getReturnObject(String methodName)
+ {
+ log.info("getReturnObject()");
+ MethodInformation methodInfo = methodList.get(methodName);
+ if (methodInfo != null)
+ {
+ return returnObjects.get(methodInfo);
+ }
+ return null;
+ }
+
+ public void addCompensationObject(String methodName, Object object)
+ {
+ log.info("addCompensationObject()");
+ MethodInformation methodInfo = methodList.get(methodName);
+ if ( methodInfo == null )
+ {
+ return;
+ }
+ Object[] objects = compensationObjects.get(methodInfo);
+ Integer paramListSize = 1;
+ if (objects != null)
+ {
+ paramListSize = objects.length;
+ Object[] tempObjects = new Object[paramListSize+1];
+ System.arraycopy(objects,0,tempObjects,0,objects.length);
+ tempObjects[paramListSize] = object;
+ compensationObjects.put(methodInfo,tempObjects);
+ }
+ else
+ {
+ objects = new Object[1];
+ objects[0] = object;
+ compensationObjects.put(methodInfo,objects);
+ }
+ }
+
+ public Object[] getCompensationObject(String methodName)
+ {
+ log.info("getCompensationObject()");
+ MethodInformation methodInfo = methodList.get(methodName);
+ if (methodInfo == null)
+ {
+ return null;
+ }
+ return compensationObjects.get(methodInfo);
+ }
+
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/JaxWSBASpecifierHandler.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/JaxWSBASpecifierHandler.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/JaxWSBASpecifierHandler.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,122 @@
+package org.jboss.txbridge.ba;
+
+import org.apache.log4j.Logger;
+
+import javax.xml.ws.handler.Handler;
+import javax.xml.ws.handler.MessageContext;
+
+
+import org.jboss.txbridge.data.ClassInformation;
+import org.jboss.txbridge.helper.*;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class JaxWSBASpecifierHandler implements Handler
+{
+ // Logger
+ private static Logger log = Logger.getLogger(JaxWSBASpecifierHandler.class);
+
+ // Service factory
+ private static ServiceAccessFactory serviceAccess = new JBossServiceAccessFactory();
+
+ public boolean handleMessage(MessageContext msgContext)
+ {
+ log.debug("handleMessage()");
+
+ Boolean outbound = (Boolean)msgContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+ if (outbound == null)
+ {
+ throw new IllegalStateException("Cannot obtain required property: " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+ }
+ return outbound ? handleOutbound(msgContext) : handleInbound(msgContext);
+ }
+
+ private boolean handleInbound(MessageContext msgContext)
+ {
+
+ log.debug("handleInbound()");
+
+ // Get reference to the service which is invoked
+ Class clazz = serviceAccess.getService();
+ String className = clazz.getName();
+ log.info("Class name: " + className);
+
+ // Get reference to the class manager
+ ClassInformationManager classInfoManager = ClassInformationManager.getSingletonInstance();
+
+ // Obtain information about the class
+ // - first check if the classInfoManager knows about this class
+ ClassInformation classInfo = classInfoManager.getClassInformation(className);
+ // - if not than process this class
+ if (classInfo == null)
+ {
+ // Process class and obtain info
+ classInfo = ClassBAVisitor.processClass(clazz);
+
+ // Remember info about the class
+ classInfoManager.storeClassInformation(classInfo);
+
+ }
+
+ // Inject task identifier
+
+
+ // Check the web method's name
+ String methodName = SOAPProcessor.getMethodName(msgContext);
+
+ // Get the real name of the method
+ methodName = classInfo.getOriginalMethodName(methodName);
+
+ // Display for logging purposes
+ String transactionType = classInfo.getTransactionAttribute(methodName);
+ log.info("Mapping: (" + methodName + "," + transactionType + ")");
+ String serviceType = classInfo.getServiceType(methodName);
+ log.info("Mapping: (" + methodName + "," + serviceType + ")");
+ String compensationMethod = classInfo.getCompensationMethod(methodName);
+ log.info("Link: (" + methodName + "," + compensationMethod + ")");
+ Class returnType = classInfo.getReturnType(methodName);
+ log.info("Return type: (" + methodName + "," + returnType.getName() + ")");
+
+ // Set properties
+ msgContext.put(BAProperties.BAClass.toString(),className);
+ msgContext.put(BAProperties.BAMethod.toString(),methodName);
+
+ return true;
+ }
+
+ private boolean handleOutbound(MessageContext msgContext)
+ {
+ log.info("handleOutbound()");
+ // Remove properties
+ if (msgContext.containsKey(BAProperties.BAClass.toString()))
+ {
+ msgContext.remove(BAProperties.BAClass.toString());
+ }
+ if (msgContext.containsKey(BAProperties.BAMethod.toString()))
+ {
+ msgContext.remove(BAProperties.BAMethod.toString());
+ }
+ return true;
+ }
+
+ public boolean handleFault(MessageContext msgContext)
+ {
+ log.info("handleFault()");
+ // Remove properties
+ if (msgContext.containsKey(BAProperties.BAClass.toString()))
+ {
+ msgContext.remove(BAProperties.BAClass.toString());
+ }
+ if (msgContext.containsKey(BAProperties.BAMethod.toString()))
+ {
+ msgContext.remove(BAProperties.BAMethod.toString());
+ }
+ return true;
+ }
+
+ public void close(MessageContext messageContext)
+ {
+ log.info("close()");
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/JaxWSBusinessActivityHandler.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/JaxWSBusinessActivityHandler.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/JaxWSBusinessActivityHandler.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,180 @@
+package org.jboss.txbridge.ba;
+
+import org.apache.log4j.Logger;
+import org.jboss.txbridge.helper.*;
+import org.jboss.txbridge.data.ClassInformation;
+import org.jboss.txbridge.data.MethodInformation;
+
+import javax.xml.ws.handler.Handler;
+import javax.xml.ws.handler.MessageContext;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class JaxWSBusinessActivityHandler implements Handler
+{
+ // Logger
+ private static Logger log = Logger.getLogger(JaxWSBusinessActivityHandler.class);
+
+ // Service access factory
+ private static ServiceAccessFactory serviceAccess = new JBossServiceAccessFactory();
+
+ // Get access to the class information manager
+ private static ClassInformationManager classInfoManager = ClassInformationManager.getSingletonInstance();
+
+ public boolean handleMessage(MessageContext msgContext)
+ {
+ log.debug("handleMessage()");
+
+ Boolean outbound = (Boolean)msgContext.get(MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+
+ if (outbound == null)
+ {
+ throw new IllegalStateException("Cannot obtain required property: " + MessageContext.MESSAGE_OUTBOUND_PROPERTY);
+ }
+
+ return outbound ? handleOutbound(msgContext) : handleInbound(msgContext);
+ }
+
+ public boolean handleFault(MessageContext messageContext)
+ {
+ log.info("handleFault()");
+ return true;
+ }
+
+ public void close(MessageContext messageContext)
+ {
+ log.info("close()");
+ }
+
+ protected boolean handleInbound(MessageContext msgContext)
+ {
+ log.debug("handleInbound()");
+
+ // Get access to the class
+ Class clazz = serviceAccess.getService();
+
+ // Obtain class info
+ ClassInformation classInfo = classInfoManager.getClassInformation(clazz.getName());
+
+ // Get properties
+ String className = (String) msgContext.get(BAProperties.BAClass.toString());
+ log.info("className: " + className);
+ String webMethodName = (String) msgContext.get(BAProperties.BAMethod.toString());
+ log.info("webMethodName: " + webMethodName);
+
+ // Check if those are correct
+ // - check class
+ if (!className.equals(clazz.getName()))
+ {
+ return false;
+ }
+ // - check method
+ // TODO: IMPLEMENT
+
+ // Get original method name
+ String methodName = classInfo.getOriginalMethodName(webMethodName);
+ // Get method information
+ MethodInformation methodInfo = classInfo.getMethodInformation(methodName);
+
+ // Display for logging purposes
+ log.info("Business Activity...");
+ log.info("BAService: " + methodInfo.getServiceType());
+ log.info("BATransactionAttribute: " + methodInfo.getTransactionAttribute());
+ log.info("BACompensatedBy: " + methodInfo.getCompensationMethod());
+ log.info("Return Type: " + methodInfo.getReturnType().getName());
+
+ // Check the type of transaction
+ if (methodInfo.getTransactionAttribute() == null)
+ {
+
+ }
+ else if (methodInfo.getTransactionAttribute().equals("COORDINATOR_COMPLETION"))
+ {
+
+ }
+ else if (methodInfo.getTransactionAttribute().equals("PARTICIPANT_COMPLETION"))
+ {
+ // Get reference to the BABridgeManager
+ log.info("Getting reference to the BA Bridge Manager");
+ BABridgeManager babridgeManager = BABridgeManager.getSingletonInstance();
+
+ // Starting transaction management
+ log.info("Starting transaction managemenet");
+ babridgeManager.manageTransaction(methodInfo);
+
+ }
+
+ return true;
+ }
+
+ /**
+ * Tidy up the Transaction/Thread association before returning a message to the client.
+ *
+ * @param msgContext
+ * @return
+ */
+ protected boolean handleOutbound(MessageContext msgContext)
+ {
+
+ log.info("handleOutbound()");
+ try
+ {
+ // Get the soap method name
+ String className = (String) msgContext.get(BAProperties.BAClass.toString());
+ log.info("className: " + className);
+ String webMethodName = (String) msgContext.get(BAProperties.BAMethod.toString());
+ log.info("webMethodName: " + webMethodName);
+
+ // Get the methods information
+ ClassInformation classInfo = classInfoManager.getClassInformation(className);
+ String methodName = classInfo.getOriginalMethodName(webMethodName);
+ log.info("originalName: " + methodName);
+ MethodInformation methodInfo = classInfo.getMethodInformation(methodName);
+
+ // Check the type of transaction
+ if (methodInfo.getTransactionAttribute() == null)
+ {
+
+ }
+ else if (methodInfo.getTransactionAttribute().equals("COORDINATOR_COMPLETION"))
+ {
+
+ }
+ else if (methodInfo.getTransactionAttribute().equals("PARTICIPANT_COMPLETION"))
+ {
+ log.info("Getting reference to the bridge manager");
+ BABridgeManager babridgeManager = BABridgeManager.getSingletonInstance();
+
+ // Get the return object if necessary
+ log.info("checking return type...");
+ Class returnType = methodInfo.getReturnType();
+ log.info("return type: " + returnType.getName());
+ if (!methodInfo.getReturnType().getName().equals("void"))
+ {
+ log.info("Getting return object");
+ Object returnObject = SOAPProcessor.getReturnObject(msgContext);
+ log.info("Return object: " + returnObject.toString());
+ // Set compensation object
+
+ log.info("Remembering return object");
+ babridgeManager.manageReturnObject(methodInfo,returnObject);
+ }
+
+ babridgeManager.completeTransaction();
+ }
+
+
+
+ }
+ catch (Exception soape)
+ {
+ soape.printStackTrace();
+ }
+
+ return true;
+ }
+
+
+
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/ParticipantCompletionParticipantBA.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/ParticipantCompletionParticipantBA.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/ba/ParticipantCompletionParticipantBA.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,168 @@
+package org.jboss.txbridge.ba;
+
+import com.arjuna.wst.*;
+import com.arjuna.ats.internal.jta.transaction.arjunacore.jca.XATerminatorImple;
+import org.apache.log4j.Logger;
+import org.jboss.txbridge.data.MethodInformation;
+import org.jboss.txbridge.helper.CompensationService;
+import org.jboss.txbridge.annotations.CompensationIdentifier;
+
+import javax.transaction.xa.Xid;
+import java.lang.reflect.Method;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.util.List;
+import java.util.ArrayList;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class ParticipantCompletionParticipantBA implements BusinessAgreementWithCoordinatorCompletionParticipant
+{
+ // Logger
+ private static Logger log = Logger.getLogger(ParticipantCompletionParticipantBA.class);
+
+ // Transaction identifier
+ String txId;
+
+ // Reference to the inbound bridge
+ InboundBABridge myBridge;
+
+ // Complete information about the original and compensation methods
+ private MethodInformation method;
+
+ // AT Transaction support
+ private XATerminatorImple xaTerminator;
+ private Xid xid;
+
+
+ public ParticipantCompletionParticipantBA(String txId,MethodInformation methodInformation)
+ {
+ log.info("constructor()");
+ method = methodInformation;
+ this.txId = txId;
+ }
+
+
+
+
+ public void complete() throws WrongStateException, SystemException
+ {
+ log.info("complete()");
+ }
+
+ public void close() throws WrongStateException, SystemException
+ {
+ log.info("close()");
+ }
+
+ public void cancel() throws WrongStateException, SystemException
+ {
+ log.info("cancel()");
+ }
+
+ public void compensate() throws FaultedException, WrongStateException, SystemException
+ {
+ log.info("compensate()");
+ try
+ {
+ // Obtain the return object
+ log.info("Getting the return object");
+ CompensationService compensationService = CompensationService.getSingletonInstance();
+ Object returnObject = compensationService.getReturnObject(txId,method.getOriginalMethod());
+ log.info("Return object that will be used: " + returnObject.toString());
+ Object[] parameterObjects = new Object[1];
+ Class[] parameterTypes = new Class[1];
+
+ parameterObjects[0] = returnObject;
+ parameterTypes[0] = returnObject.getClass();
+
+ // Obtain the compensation objects
+ log.info("Getting the compensation object");
+ Object[] compensationObjects = compensationService.getCompensationObject(txId,method.getOriginalMethod());
+ if ( compensationObjects == null )
+ {
+ log.info("No compensation objects will be used.");
+ }
+ else
+ {
+ log.info("Compensation objects found.");
+ for (Object singleObject : compensationObjects)
+ {
+ log.info("Compensation object: " + singleObject);
+ }
+ log.info("Adding compensation objects as parameters.");
+ Object[] tempParameters = new Object[compensationObjects.length+1];
+ System.arraycopy(compensationObjects,0,tempParameters,0,compensationObjects.length);
+ tempParameters[compensationObjects.length] = returnObject;
+ parameterObjects = new Object[tempParameters.length];
+ parameterTypes = new Class[tempParameters.length];
+ System.arraycopy(tempParameters,0,parameterObjects,0,tempParameters.length);
+ int i = 0;
+ log.info("Adding parameter types.");
+ for (Object singleObject : parameterObjects)
+ {
+ log.info("Link (" + singleObject + "," + singleObject.getClass()+")");
+ parameterTypes[i++] = singleObject.getClass();
+ }
+
+ }
+
+ log.info("Parameter objects:");
+ for (Object parameter : parameterObjects)
+ {
+ log.info(parameter);
+ }
+ log.info("Parameter types:");
+ for (Class clazz : parameterTypes)
+ {
+ log.info(clazz);
+ }
+ log.info(parameterTypes);
+
+ // Get reference to the method
+ Class clazz = method.getCompensationClass();
+ log.info("Class: " + clazz.getName());
+ Method theMethod = clazz.getMethod(method.getCompensationMethod(),parameterTypes);
+ log.info("Method: " + theMethod.getName());
+ Constructor classConstructor = clazz.getConstructor();
+ log.info("Constructor: " + classConstructor.toString());
+ Object classObject = classConstructor.newInstance();
+
+ // Inject the transaction identifier
+ Field[] fields = clazz.getDeclaredFields();
+ for (Field singleField : fields)
+ {
+ CompensationIdentifier cid = singleField.getAnnotation(CompensationIdentifier.class);
+ if (cid != null)
+ {
+ singleField.setAccessible(true);
+ singleField.set(classObject,txId);
+ }
+ }
+
+ // Invoke the compensation method
+ theMethod.invoke(classObject,parameterObjects);
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public String status() throws SystemException
+ {
+ log.info("status()");
+ return null;
+ }
+
+ public void unknown() throws SystemException
+ {
+ log.info("unknown()");
+ }
+
+ public void error() throws SystemException
+ {
+ log.info("error()");
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/ClassInformation.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/ClassInformation.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/ClassInformation.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,84 @@
+package org.jboss.txbridge.data;
+
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class ClassInformation
+{
+ // Class
+ private Class clazz;
+
+ // Mappings
+ // (web_method_name,real_method_name)
+ private ConcurrentMap<String,String> webMethodMappings;
+ // (real_method_name,method_information)
+ private ConcurrentMap<String,MethodInformation> methodMappings;
+
+ // Constructor
+ public ClassInformation(Class clazz, ConcurrentMap<String,String> webMethodMappings, ConcurrentMap<String, MethodInformation> methodMappings)
+ {
+ this.clazz = clazz;
+ this.webMethodMappings = webMethodMappings;
+ this.methodMappings = methodMappings;
+ }
+
+ // Get the class that is being described
+ public Class getTheClass()
+ {
+ return clazz;
+ }
+
+ // Get the name of a compensation method for a given method
+ public String getCompensationMethod(String originalMethod)
+ {
+ if (methodMappings.containsKey(originalMethod))
+ {
+ return methodMappings.get(originalMethod).getCompensationMethod();
+ }
+ return null;
+ }
+
+ // Get return type for a given method
+ public Class getReturnType(String originalMethod)
+ {
+ if (methodMappings.containsKey(originalMethod))
+ {
+ return methodMappings.get(originalMethod).getReturnType();
+ }
+ return null;
+ }
+
+ // Get transaction attribute for a given method
+ public String getTransactionAttribute(String originalMethod)
+ {
+ if (methodMappings.containsKey(originalMethod))
+ {
+ return methodMappings.get(originalMethod).getTransactionAttribute();
+ }
+ return null;
+ }
+
+ // Get the service type for the given method
+ public String getServiceType(String originalMethod)
+ {
+ if (methodMappings.containsKey(originalMethod))
+ {
+ return methodMappings.get(originalMethod).getServiceType();
+ }
+ return null;
+ }
+
+ // Get full method information
+ public MethodInformation getMethodInformation(String methodName)
+ {
+ return methodMappings.get(methodName);
+ }
+
+ // Get the original method's name
+ public String getOriginalMethodName(String webMethodName)
+ {
+ return webMethodMappings.get(webMethodName);
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/CompensationObject.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/CompensationObject.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/CompensationObject.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,8 @@
+package org.jboss.txbridge.data;
+
+/**
+ * Author: Maciej Machulak
+ */
+public interface CompensationObject
+{
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/MethodInformation.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/MethodInformation.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/MethodInformation.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,93 @@
+package org.jboss.txbridge.data;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class MethodInformation
+{
+ // Web method name
+ private String webMethodName;
+
+ // Original method
+ private Class originalClass;
+ private String originalMethod;
+ private Class returnType;
+
+ // Transaction attribute
+ private String transactionAttribute;
+
+ // Service type
+ private String serviceType;
+
+ // Compensation method
+ private Class compensationClass;
+ private String compensationMethod;
+ private Class[] parameterType;
+
+
+ public MethodInformation(String webMethodName, Class originalClass, String originalMethod, Class returnType, String transactionAttribute, String serviceType, Class compensationClass, String compensationMethod, Class[] parameterType)
+ {
+ this.webMethodName = webMethodName;
+ this.originalClass = originalClass;
+ this.originalMethod = originalMethod;
+ this.returnType = returnType;
+ this.transactionAttribute = transactionAttribute;
+ this.serviceType = serviceType;
+ this.compensationClass = compensationClass;
+ this.compensationMethod = compensationMethod;
+ this.parameterType = parameterType;
+ }
+
+ public Class getOriginalClass()
+ {
+ return originalClass;
+ }
+
+ public String getOriginalMethod()
+ {
+ return originalMethod;
+ }
+
+ public Class getReturnType()
+ {
+ return returnType;
+ }
+
+ public Class getCompensationClass()
+ {
+ return compensationClass;
+ }
+
+ public String getCompensationMethod()
+ {
+ return compensationMethod;
+ }
+
+ public Class[] getParameterType()
+ {
+ return parameterType;
+ }
+
+
+ public void setReturnType(Class returnType)
+ {
+ this.returnType = returnType;
+ }
+
+ public String getTransactionAttribute()
+ {
+ return transactionAttribute;
+ }
+
+
+ public String getServiceType()
+ {
+ return serviceType;
+ }
+
+
+ public String getWebMethodName()
+ {
+ return webMethodName;
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/ServiceDescription.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/ServiceDescription.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/data/ServiceDescription.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,45 @@
+package org.jboss.txbridge.data;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class ServiceDescription
+{
+ private String className;
+ private ConcurrentMap<String,String> compensationMappings = new ConcurrentHashMap<String,String>();
+ private ConcurrentMap<String,String> protocolMappings = new ConcurrentHashMap<String,String>();
+ private ConcurrentMap<String,String> serviceTypeMappings = new ConcurrentHashMap<String,String>();
+ private ConcurrentMap<String,Object> compensationObjects = new ConcurrentHashMap<String,Object>();
+
+
+ ServiceDescription(String className)
+ {
+ this.className = className;
+ }
+
+ String newCompensationMapping(String key, String value)
+ {
+ return compensationMappings.putIfAbsent(key, value);
+ }
+
+
+ String newProtocolMapping(String key, String value)
+ {
+ return protocolMappings.putIfAbsent(key, value);
+ }
+
+
+ String newServiceTypeMapping(String key, String value)
+ {
+ return serviceTypeMappings.putIfAbsent(key, value);
+ }
+
+
+ public Object newCompensationObject(String key, Object value)
+ {
+ return compensationObjects.putIfAbsent(key, value);
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/BAProperties.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/BAProperties.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/BAProperties.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,10 @@
+package org.jboss.txbridge.helper;
+
+/**
+ * Author: Maciej Machulak
+ */
+public enum BAProperties
+{
+ BAClass,
+ BAMethod
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/BATaskIdentifierFactory.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/BATaskIdentifierFactory.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/BATaskIdentifierFactory.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,15 @@
+package org.jboss.txbridge.helper;
+
+/**
+ * Author: Maciej Machulak
+ */
+public abstract class BATaskIdentifierFactory
+{
+ protected BATaskIdentifierFactory()
+ {
+ String BATaskIdentifier = getIdentifier();
+ }
+
+ public abstract String getIdentifier();
+
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ClassBAVisitor.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ClassBAVisitor.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ClassBAVisitor.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,134 @@
+package org.jboss.txbridge.helper;
+
+import org.jboss.txbridge.annotations.*;
+import org.jboss.txbridge.data.ClassInformation;
+import org.jboss.txbridge.data.MethodInformation;
+import org.apache.log4j.Logger;
+
+import javax.jws.WebMethod;
+import javax.ejb.TransactionAttributeType;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.lang.reflect.Method;
+
+
+/**
+ * Author: Maciej Machulak
+ */
+public class ClassBAVisitor
+{
+ // Logger
+ private static Logger log = Logger.getLogger(ClassBAVisitor.class);
+
+ // Other
+ private static TransactionAttributeType defaultTxAttributeType = TransactionAttributeType.REQUIRED;
+ private static BAServiceType defaultBAServiceType = BAServiceType.MODIFY;
+
+ // Create information about a class
+ public static synchronized ClassInformation processClass(Class clazz)
+ {
+ log.info("processClass()");
+
+ // Create new mappings
+ ConcurrentMap<String, MethodInformation> methodMappings = new ConcurrentHashMap<String,MethodInformation>();
+ ConcurrentMap<String,String> methodNameMappings = new ConcurrentHashMap<String,String>();
+
+ // Get all the methods from the class
+ Method[] methodList = clazz.getDeclaredMethods();
+ log.info("Number of methods: " + methodList.length);
+
+ // Loop through all methods
+ for (Method singleMethod : methodList)
+ {
+ // Return class
+ Class<?> returnType = null;
+ Class<?>[] parameterTypes = null;
+
+ // Check what is the name of the method
+ log.info("Single method: " + singleMethod.getName());
+ String methodName = singleMethod.getName();
+ String webMethodName = methodName;
+
+ // Check if there is a WebMethod annotation
+ WebMethod webMethodAnnotation = singleMethod.getAnnotation(WebMethod.class);
+ if (webMethodAnnotation != null)
+ {
+ log.info("WebMethod annotation present!");
+
+ // Check if the operation name has been specified
+ String name = webMethodAnnotation.operationName();
+ if (name != null && !name.equals(""))
+ {
+ log.info("WebMethod operationName: " + name);
+ // If yes... change the name of the web method
+ webMethodName = name;
+ }
+ }
+ // Remember (method,webMethod) association
+ methodNameMappings.put(methodName,webMethodName);
+
+ // Check if this method is a BA service
+ String serviceType = defaultBAServiceType.toString();
+ BAService baService = singleMethod.getAnnotation(BAService.class);
+ if (baService != null)
+ {
+ log.info("Method " + webMethodName + " is a BA service.");
+
+ // Get the type of the service
+ BAServiceType baServiceType = baService.value();
+ if (baServiceType != null)
+ {
+ log.info("BAServiceType: " + baServiceType);
+ serviceType = baServiceType.toString();
+ }
+
+ }
+
+ // Check the transaction attribute
+ String transactionType = defaultTxAttributeType.toString();
+ BATransactionAttribute txAttr = singleMethod.getAnnotation(BATransactionAttribute.class);
+ if (txAttr != null)
+ {
+
+ log.info("BATransactionAttribute annotation present!");
+ // If there was a transaction attribute check the type of the transaction attribute
+ BATransactionAttributeType txType = txAttr.value();
+
+ if (txType != null)
+ {
+ log.info("BATransactionAttributeType: " + txType);
+ transactionType = txType.toString();
+ }
+ }
+
+ // Check the compensation method
+ String compensationMethod = "";
+ BACompensatedBy baComp = singleMethod.getAnnotation(BACompensatedBy.class);
+ if (baComp != null)
+ {
+ log.info("BACompensatedBy annotation present!");
+ compensationMethod = baComp.value();
+ }
+
+ // Check the types of the parameters
+ for (Method theMethod : methodList)
+ {
+ if (theMethod.getName().equals(compensationMethod))
+ {
+ parameterTypes = theMethod.getParameterTypes();
+ break;
+ }
+ }
+
+ // Get the return type
+ returnType = singleMethod.getReturnType();
+
+ MethodInformation singleMethodInfo = new MethodInformation(webMethodName,clazz,methodName,returnType,transactionType,serviceType,clazz,compensationMethod,parameterTypes);
+ methodMappings.putIfAbsent(webMethodName,singleMethodInfo);
+ }
+
+ // Cache all obtained values
+ return new ClassInformation(clazz,methodNameMappings,methodMappings);
+ }
+
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ClassInformationManager.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ClassInformationManager.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ClassInformationManager.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,83 @@
+package org.jboss.txbridge.helper;
+
+import org.jboss.txbridge.data.ClassInformation;
+import org.apache.log4j.Logger;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class ClassInformationManager
+{
+ // Logger
+ private static Logger log = Logger.getLogger(ClassInformationManager.class);
+
+ // Mapping (class name , class information)
+ private ConcurrentMap<String, ClassInformation> classDescriptions;
+
+ // Class information manager instance
+ private volatile static ClassInformationManager cim = null;
+
+ // Constructor
+ private ClassInformationManager()
+ {
+ log.info("constructor()");
+ classDescriptions = new ConcurrentHashMap<String,ClassInformation>();
+ }
+
+ // Get instance of the class information manager
+ public static ClassInformationManager getSingletonInstance()
+ {
+ log.info("getSingletonInstance()");
+ if (cim == null)
+ {
+ synchronized(ClassInformationManager.class)
+ {
+ if (cim == null)
+ {
+ log.info("Creating new instance");
+ cim = new ClassInformationManager();
+ }
+ }
+ }
+ return cim;
+ }
+
+ // Store information about a class
+ public void storeClassInformation(ClassInformation classInformation)
+ {
+ log.info("storeClassInformation(ClassInformation)");
+ storeClassInformation(classInformation.getTheClass().getName(),classInformation);
+ }
+
+ // Store information about a class
+ public void storeClassInformation(String className,ClassInformation classInformation)
+ {
+ log.info("storeClassInformation(String,ClassInformation)");
+ classDescriptions.putIfAbsent(className,classInformation);
+ }
+
+ // Get information about a class of a given name
+ public ClassInformation getClassInformation(String className)
+ {
+ log.info("getClassInformation()");
+ log.info("No. of classes: " + classDescriptions.size());
+ ClassInformation classInfo = classDescriptions.get(className);
+ if (classInfo == null)
+ {
+ log.info("Returning null...");
+ }
+ return classInfo;
+ }
+
+ // Check if a class of a given name has its information object stored
+ public boolean knowsAbout(String className)
+ {
+ log.info("knowsAbout()");
+ return classDescriptions.containsKey(className);
+ }
+
+
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/CompensationManager.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/CompensationManager.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/CompensationManager.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,90 @@
+package org.jboss.txbridge.helper;
+
+import com.arjuna.mw.wst.BusinessActivityManager;
+import com.arjuna.mw.wst.TxContext;
+import com.arjuna.wst.SystemException;
+import org.apache.log4j.Logger;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class CompensationManager
+{
+ // Logger
+ Logger log = Logger.getLogger(CompensationManager.class);
+
+
+ BusinessActivityManager businessActivityManager;
+ CompensationService cs;
+
+ public CompensationManager()
+ {
+ // Get business activity manager
+ businessActivityManager = BusinessActivityManager.getBusinessActivityManager();
+
+ // Get compensation service
+ cs = CompensationService.getSingletonInstance();
+
+
+ }
+
+ public void store(String methodName, Object returnObject)
+ {
+ log.info("store()");
+ // Get transaction identifier
+ try
+ {
+ String txId = businessActivityManager.currentTransaction().toString();
+ cs.addCompensationObject(txId,methodName,returnObject);
+ }
+ catch (SystemException e)
+ {
+ e.printStackTrace();
+ }
+
+ }
+
+ public void storeTemporary(String methodName, String identifier, Object object)
+ {
+ log.info("storeTemporary()");
+ // Get transaction identifier
+ try
+ {
+ String txId = businessActivityManager.currentTransaction().toString();
+ cs.addTemporaryCompensationObject(txId,methodName,identifier,object);
+ }
+ catch (SystemException e)
+ {
+ e.printStackTrace();
+ }
+ }
+
+ public Object getTemporaryObject(String txId,String methodName,String identifier)
+ {
+ if (txId == null)
+ {
+ return null;
+ }
+ // Get transaction identifier
+ log.info("getTemporaryObject()");
+ return cs.getTemporaryCompensationObject(txId,methodName,identifier);
+
+ }
+
+ public Object retrieve(String methodName)
+ {
+ log.info("retrieve()");
+ // Get transaction identifier
+ try
+ {
+ businessActivityManager = BusinessActivityManager.getBusinessActivityManager();
+ String txId = businessActivityManager.currentTransaction().toString();
+ return cs.getCompensationObject(txId,methodName);
+ }
+ catch (SystemException e)
+ {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/CompensationService.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/CompensationService.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/CompensationService.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,136 @@
+package org.jboss.txbridge.helper;
+
+import org.apache.log4j.Logger;
+import org.jboss.txbridge.ba.InboundBABridge;
+import org.jboss.txbridge.data.MethodInformation;
+
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class CompensationService
+{
+ // Logger
+ private static Logger log = Logger.getLogger(CompensationService.class);
+
+ // Compensation manager instance
+ private volatile static CompensationService compensationService = null;
+
+ // Mappings
+ // - transaction IDs and Inbound Bridges
+ private static ConcurrentMap<String,InboundBABridge> bridges;
+ // - transaction IDs and method information
+ private static ConcurrentMap<String, MethodInformation> txMethods;
+ // - unique ID and temporary objects
+ private static ConcurrentMap<String,Object> returnObjects;
+ // - transaction IDs and additional compensation objects
+ private static ConcurrentMap<String,Object[]> compensationObjects;
+
+ // Constructor
+ private CompensationService()
+ {
+ log.info("constructor()");
+ bridges = new ConcurrentHashMap<String,InboundBABridge>();
+ txMethods = new ConcurrentHashMap<String,MethodInformation>();
+ returnObjects = new ConcurrentHashMap<String,Object>();
+ compensationObjects = new ConcurrentHashMap<String,Object[]>();
+ }
+
+ public void registerBridge(String txId,InboundBABridge bridge)
+ {
+ bridges.put(txId,bridge);
+ }
+
+ // Return instance of the compensation manager
+ public static CompensationService getSingletonInstance()
+ {
+ log.info("getSingletonInstance()");
+ if (compensationService == null)
+ {
+ synchronized(CompensationService.class)
+ {
+ if (compensationService == null)
+ {
+ log.info("Creating new instance");
+ compensationService = new CompensationService();
+ }
+ }
+ }
+ return compensationService;
+ }
+
+ // Add new compensation object
+ public void addReturnObject(String txId, String methodName,Object object)
+ {
+ log.info("addReturnObject()");
+ InboundBABridge bridge = bridges.get(txId);
+ if (bridge != null)
+ {
+ log.info("Bridge found...");
+ bridge.addReturnObject(methodName,object);
+ }
+ }
+
+ // Add new compensation object
+ public void addTemporaryCompensationObject(String txId, String methodName,String identifier,Object object)
+ {
+ log.info("addTemporaryCompensationObject()");
+ InboundBABridge bridge = bridges.get(txId);
+ if (bridge != null)
+ {
+ log.info("Bridge found...");
+ bridge.addTemporaryObject(methodName,identifier,object);
+ }
+ }
+
+ // Return a compensation object for a given transaction
+ public Object getTemporaryCompensationObject(String txId,String methodName,String identifier)
+ {
+ log.info("getTemporaryCompensationObject()");
+ InboundBABridge bridge = bridges.get(txId);
+ if (bridge != null)
+ {
+ log.info("Bridge found...");
+ return bridge.getTemporaryObject(methodName,identifier);
+ }
+ return null;
+ }
+
+ // Return a compensation object for a given transaction
+ public Object getReturnObject(String txId,String methodName)
+ {
+ log.info("getReturnObject()");
+ InboundBABridge bridge = bridges.get(txId);
+ if (bridge != null)
+ {
+ log.info("Bridge found...");
+ return bridge.getReturnObject(methodName);
+ }
+ return null;
+ }
+
+ public void addCompensationObject(String txId, String methodName, Object object)
+ {
+ log.info("addCompensationObject()");
+ InboundBABridge bridge = bridges.get(txId);
+ if (bridge != null)
+ {
+ log.info("Bridge found...");
+ bridge.addCompensationObject(methodName,object);
+ }
+ }
+
+ public Object[] getCompensationObject(String txId, String methodName)
+ {
+ log.info("getCompensationObject()");
+ InboundBABridge bridge = bridges.get(txId);
+ if (bridge != null)
+ {
+ log.info("Bridge found...");
+ return bridge.getCompensationObject(methodName);
+ }
+ return null;
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/JBossServiceAccessFactory.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/JBossServiceAccessFactory.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/JBossServiceAccessFactory.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,26 @@
+package org.jboss.txbridge.helper;
+
+import org.jboss.ws.core.CommonMessageContext;
+import org.jboss.ws.core.soap.MessageContextAssociation;
+import org.jboss.ws.metadata.umdm.EndpointMetaData;
+import org.jboss.txbridge.helper.ServiceAccessFactory;
+import org.apache.log4j.Logger;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class JBossServiceAccessFactory extends ServiceAccessFactory
+{
+ // Logger
+ private static Logger log = Logger.getLogger(JBossServiceAccessFactory.class);
+
+ // Return a class that's method is being invoked in this context
+ public Class getService()
+ {
+ log.info("getService()");
+ CommonMessageContext commonMessageContext = MessageContextAssociation.peekMessageContext();
+ EndpointMetaData emd = commonMessageContext.getEndpointMetaData();
+ return emd.getServiceEndpointInterface();
+ }
+
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/SOAPProcessor.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/SOAPProcessor.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/SOAPProcessor.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,57 @@
+package org.jboss.txbridge.helper;
+
+import org.jboss.ws.core.soap.SOAPContentElement;
+import org.apache.log4j.Logger;
+
+import javax.xml.ws.handler.MessageContext;
+import javax.xml.ws.handler.soap.SOAPMessageContext;
+import javax.xml.soap.SOAPMessage;
+import javax.xml.soap.SOAPBody;
+import javax.xml.soap.SOAPBodyElement;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class SOAPProcessor
+{
+ // Logger
+ private static Logger log = Logger.getLogger(SOAPProcessor.class);
+
+ // Pull out a method's name from the SOAP message
+ public static synchronized String getMethodName(MessageContext msgContext)
+ {
+ log.info("getMethodName()");
+ try
+ {
+ SOAPMessage soapMessage = ((SOAPMessageContext)msgContext).getMessage();
+ SOAPBody soapBody = soapMessage.getSOAPBody();
+ SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next();
+ return soapBodyElement.getElementName().getLocalName();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ // Pull out the return object from a message
+ public static synchronized Object getReturnObject(MessageContext msgContext)
+ {
+ log.info("getReturnObject()");
+ try
+ {
+ SOAPMessage soapMessage = ((SOAPMessageContext)msgContext).getMessage();
+ SOAPBody soapBody = soapMessage.getSOAPBody();
+ SOAPBodyElement soapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next();
+ SOAPContentElement parameterElement = (SOAPContentElement) soapBodyElement.getChildElements().next();
+ parameterElement.getObjectValue();
+ return parameterElement.getObjectValue();
+ }
+ catch (Exception e)
+ {
+ e.printStackTrace();
+ }
+ return null;
+ }
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ServiceAccessFactory.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ServiceAccessFactory.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/ServiceAccessFactory.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,15 @@
+package org.jboss.txbridge.helper;
+
+/**
+ * Author: Maciej Machulak
+ */
+public abstract class ServiceAccessFactory
+{
+
+ protected ServiceAccessFactory()
+ {
+ Class clazz = getService();
+ }
+
+ public abstract Class getService();
+}
Added: labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/SimpleBATaskIdentifierFactory.java
===================================================================
--- labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/SimpleBATaskIdentifierFactory.java (rev 0)
+++ labs/jbosstm/workspace/maciej.machulak/code/demo/app/bridge/org/jboss/txbridge/helper/SimpleBATaskIdentifierFactory.java 2007-06-19 01:34:12 UTC (rev 12666)
@@ -0,0 +1,34 @@
+package org.jboss.txbridge.helper;
+
+import org.apache.log4j.Logger;
+import org.jboss.ws.core.CommonMessageContext;
+import org.jboss.ws.core.soap.MessageContextAssociation;
+import org.jboss.ws.metadata.umdm.EndpointMetaData;
+
+import java.util.Random;
+
+/**
+ * Author: Maciej Machulak
+ */
+public class SimpleBATaskIdentifierFactory
+{
+ // Identifier uniqueness
+ private static int IDENTIFIER_PRECISION = 24;
+
+ // Logger
+ private static Logger log = Logger.getLogger(SimpleBATaskIdentifierFactory.class);
+
+ // Random generator
+ private static Random rg = new Random();
+
+ // Randomly generated bytes
+ byte[] taskIdentifier = new byte[IDENTIFIER_PRECISION];
+
+ // Return a class that's method is being invoked in this context
+ public String getIdentifier()
+ {
+ log.info("getIdentifier()");
+ rg.nextBytes(taskIdentifier);
+ return new String(taskIdentifier);
+ }
+}
More information about the jboss-svn-commits
mailing list