Package org.apache.sandesha2.workers

Source Code of org.apache.sandesha2.workers.SenderWorker

package org.apache.sandesha2.workers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;

import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axis2.AxisFault;
import org.apache.axis2.Constants;
import org.apache.axis2.client.async.Callback;
import org.apache.axis2.client.async.AxisCallback;
import org.apache.axis2.util.CallbackReceiver;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.addressing.EndpointReference;
import org.apache.axis2.context.ConfigurationContext;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.context.OperationContext;
import org.apache.axis2.context.OperationContextFactory;
import org.apache.axis2.context.ServiceContext;
import org.apache.axis2.description.AxisOperation;
import org.apache.axis2.description.OutOnlyAxisOperation;
import org.apache.axis2.engine.AxisEngine;
import org.apache.axis2.engine.MessageReceiver;
import org.apache.axis2.engine.Handler.InvocationResponse;
import org.apache.axis2.transport.RequestResponseTransport;
import org.apache.axis2.transport.TransportUtils;
import org.apache.axis2.transport.RequestResponseTransport.RequestResponseTransportStatus;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.axis2.wsdl.WSDLConstants;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.sandesha2.RMMsgContext;
import org.apache.sandesha2.Sandesha2Constants;
import org.apache.sandesha2.SandeshaException;
import org.apache.sandesha2.i18n.SandeshaMessageHelper;
import org.apache.sandesha2.i18n.SandeshaMessageKeys;
import org.apache.sandesha2.policy.SandeshaPolicyBean;
import org.apache.sandesha2.storage.SandeshaStorageException;
import org.apache.sandesha2.storage.StorageManager;
import org.apache.sandesha2.storage.Transaction;
import org.apache.sandesha2.storage.beanmanagers.SenderBeanMgr;
import org.apache.sandesha2.storage.beans.RMDBean;
import org.apache.sandesha2.storage.beans.RMSBean;
import org.apache.sandesha2.storage.beans.SenderBean;
import org.apache.sandesha2.util.AcknowledgementManager;
import org.apache.sandesha2.util.MessageRetransmissionAdjuster;
import org.apache.sandesha2.util.MsgInitializer;
import org.apache.sandesha2.util.RMMsgCreator;
import org.apache.sandesha2.util.SandeshaUtil;
import org.apache.sandesha2.util.SpecSpecificConstants;
import org.apache.sandesha2.util.TerminateManager;
import org.apache.sandesha2.wsrm.*;

public class SenderWorker extends SandeshaWorker implements Runnable {

  private static final Log log = LogFactory.getLog(SenderWorker.class);

  private ConfigurationContext configurationContext = null;
  private SenderBean senderBean = null;
  private RMMsgContext messageToSend = null;
  private String rmVersion = null;

  public SenderWorker (ConfigurationContext configurationContext, SenderBean senderBean, String rmVersion) {
    this.configurationContext = configurationContext;
    this.senderBean = senderBean;
    this.rmVersion = rmVersion;
  }
 
  public void setMessage(RMMsgContext msg) {
    this.messageToSend = msg;
  }
 
  public void run () {
   
    if (log.isDebugEnabled())
      log.debug("Enter: SenderWorker::run");

    Transaction transaction = null;
   
    try {
      StorageManager storageManager = SandeshaUtil.getSandeshaStorageManager(configurationContext, configurationContext.getAxisConfiguration());
      SenderBeanMgr senderBeanMgr = storageManager.getSenderBeanMgr();

      transaction = storageManager.getTransaction();

      String key = senderBean.getMessageContextRefKey();
      MessageContext msgCtx = null;
      RMMsgContext   rmMsgCtx = null;
      if(messageToSend != null) {
        msgCtx = messageToSend.getMessageContext();
        rmMsgCtx = messageToSend;
      } else {
        msgCtx = storageManager.retrieveMessageContext(key, configurationContext);
     
        if (msgCtx == null) {
          // This sender bean has already been processed
         
          if(transaction != null && transaction.isActive()) transaction.commit();
          transaction = null;

          return;
        }
     
        rmMsgCtx = MsgInitializer.initializeMessage(msgCtx);
      }

      // sender will not send the message if following property is
      // set and not true.
      // But it will set if it is not set (null)

      // This is used to make sure that the mesage get passed the
      // Sandesha2TransportSender.

      String qualifiedForSending = (String) msgCtx.getProperty(Sandesha2Constants.QUALIFIED_FOR_SENDING);
      if (qualifiedForSending != null && !qualifiedForSending.equals(Sandesha2Constants.VALUE_TRUE)) {
        if (log.isDebugEnabled())
          log.debug("Exit: SenderWorker::run, !qualified for sending");
       
        if(transaction != null && transaction.isActive()) {
          transaction.commit();
          transaction = null;
        }
       
        return;
      }

      if (msgCtx == null) {
        if (log.isDebugEnabled())
          log.debug(SandeshaMessageHelper.getMessage(SandeshaMessageKeys.sendHasUnavailableMsgEntry));
       
        if(transaction != null && transaction.isActive()) {
          transaction.commit();
          transaction = null;
        }
       
        return;     
      }

      // operation is the lowest level Sandesha2 should be attached
      ArrayList msgsNotToSend = SandeshaUtil.getPropertyBean(msgCtx.getAxisOperation()).getMsgTypesToDrop();

      if (msgsNotToSend != null && msgsNotToSend.contains(new Integer(rmMsgCtx.getMessageType()))) {
        if (log.isDebugEnabled())
          log.debug("Exit: SenderWorker::run, message type to be dropped " + rmMsgCtx.getMessageType());
       
        if(transaction != null && transaction.isActive()) {
          transaction.commit();
          transaction = null;
        }
       
        return
      }

      // If we are sending to the anonymous URI then we _must_ have a transport waiting,
      // or the message can't go anywhere. If there is nothing here then we leave the
      // message in the sender queue, and a MakeConnection (or a retransmitted request)
      // will hopefully pick it up soon.
      Boolean makeConnection = (Boolean) msgCtx.getProperty(Sandesha2Constants.MAKE_CONNECTION_RESPONSE);
      EndpointReference toEPR = msgCtx.getTo();

      MessageContext inMsg = null;
      OperationContext op = msgCtx.getOperationContext();
     
      RequestResponseTransport t = (RequestResponseTransport) msgCtx.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
     
      if (t==null) {
        if (op != null)
          inMsg = op.getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
        if (inMsg != null)
          t = (RequestResponseTransport) inMsg.getProperty(RequestResponseTransport.TRANSPORT_CONTROL);
      }

      // If we are anonymous, and this is not a makeConnection, then we must have a transport waiting
      if((toEPR==null || toEPR.hasAnonymousAddress()) &&
         (makeConnection == null || !makeConnection.booleanValue()) &&
         (t != null && !t.getStatus().equals(RequestResponseTransportStatus.WAITING))) {
       
        // Mark this sender bean so that we know that the transport is unavailable, if the
        // bean is still stored.
        SenderBean bean = senderBeanMgr.retrieve(senderBean.getMessageID());
        if(bean != null && bean.isTransportAvailable()) {
          bean.setTransportAvailable(false);
          senderBeanMgr.update(bean);
        }
       
        // Commit the update
        if(transaction != null && transaction.isActive()) transaction.commit();
        transaction = null;
       
        if (log.isDebugEnabled())
          log.debug("Exit: SenderWorker::run, no response transport for anonymous message");
        return;
      }
     
      //if the message belong to the Replay Model, it will be send out only if


      boolean continueSending = updateMessage(rmMsgCtx,senderBean,storageManager);
      //save changes done @ updateMessage -> MessageRetransmissionAdjuster.adjustRetransmittion
      storageManager.getSenderBeanMgr().update(senderBean);
     

      if (!continueSending) {
        if (log.isDebugEnabled())
          log.debug("Exit: SenderWorker::run, !continueSending");
       
        if(transaction != null && transaction.isActive()) {
          transaction.commit();
          transaction = null;
        }
        invokeCallBackObject(storageManager,msgCtx ,"Exit: SenderWorker::run, !continueSending");
        return;
      }

      int messageType = senderBean.getMessageType();
     
      if (isAckPiggybackableMsgType(messageType)) {
        // Commit the update
        if(transaction != null && transaction.isActive()) transaction.commit();
        transaction = storageManager.getTransaction();

        // Piggyback ack messages based on the 'To' address of the message
        transaction = AcknowledgementManager.piggybackAcksIfPresent(rmMsgCtx, storageManager, transaction);
      }

      // sending the message
      boolean successfullySent = false;

      // Although not actually sent yet, update the send count to indicate an attempt
      if (senderBean.isReSend()) {
        SenderBean bean2 = senderBeanMgr.retrieve(senderBean.getMessageID());
        if (bean2 != null) {
          bean2.setSentCount(senderBean.getSentCount());
          senderBeanMgr.update(bean2);
        }
      }

      // have to commit the transaction before sending. This may
      // get changed when WS-AT is available.
      if(transaction != null) {
        transaction.commit();
        transaction = null;
      }

      msgCtx.getOptions().setTimeOutInMilliSeconds(1000000);
     
      boolean processResponseForFaults = false ;
      try {
        InvocationResponse response = InvocationResponse.CONTINUE;
       
        SandeshaPolicyBean policy = SandeshaUtil.getPropertyBean(msgCtx.getAxisOperation());
        if(policy.isUseMessageSerialization()) {
          if(msgCtx.isPaused()) {
            if (log.isDebugEnabled())
              log.debug("Resuming a send for message : " + msgCtx.getEnvelope().getHeader());
            msgCtx.setPaused(false);
            msgCtx.setProperty(MessageContext.TRANSPORT_NON_BLOCKING, Boolean.FALSE);
            response = AxisEngine.resumeSend(msgCtx);
          } else {
            if (log.isDebugEnabled())
              log.debug("Sending a message : " + msgCtx.getEnvelope().getHeader());
            msgCtx.setProperty(MessageContext.TRANSPORT_NON_BLOCKING, Boolean.FALSE);
            AxisEngine.send(msgCtx)// TODO check if this should return an invocation response
          }
        } else {
          // had to fully build the SOAP envelope to support
          // retransmissions.
          // Otherwise a 'parserAlreadyAccessed' exception could
          // get thrown in retransmissions.
          // But this has a performance reduction.
          msgCtx.getEnvelope().build();
 
          ArrayList retransmittablePhases = (ArrayList) msgCtx.getProperty(Sandesha2Constants.RETRANSMITTABLE_PHASES);
          if (retransmittablePhases!=null) {
            msgCtx.setExecutionChain(retransmittablePhases);
          } else {
            ArrayList emptyExecutionChain = new ArrayList ();
            msgCtx.setExecutionChain(emptyExecutionChain);
          }
         
          msgCtx.setCurrentHandlerIndex(0);
          msgCtx.setCurrentPhaseIndex(0);
          msgCtx.setPaused(false);
       
          if (log.isDebugEnabled())
            log.debug("Resuming a send for message : " + msgCtx.getEnvelope().getHeader());
          response = AxisEngine.resumeSend(msgCtx);
        }
        if(log.isDebugEnabled()) log.debug("Engine resume returned " + response);
        if(response != InvocationResponse.SUSPEND) {
          if(t != null) {
            if(log.isDebugEnabled()) log.debug("Signalling transport in " + t);
            t.signalResponseReady();
          }
        }
       
        successfullySent = true;
       
      } catch (AxisFault e) {
        //this is a possible SOAP 1.2 Fault. So letting it proceed.
       
        processResponseForFaults = true;
       
        recordError(e, rmMsgCtx, storageManager);
       
      } catch (Exception e) {
        String message = SandeshaMessageHelper.getMessage(
            SandeshaMessageKeys.sendMsgError, e.toString());
       
        if (log.isErrorEnabled())
          log.error(message, e);
       
        recordError(e, rmMsgCtx, storageManager);
       
      }
      // Establish the transaction for post-send processing
      transaction = storageManager.getTransaction();

      // update or delete only if the object is still present.
      SenderBean bean1 = senderBeanMgr
          .retrieve(senderBean.getMessageID());
      if (bean1 != null) {
        if (senderBean.isReSend()) {
          bean1.setTimeToSend(senderBean.getTimeToSend());
          senderBeanMgr.update(bean1);
        }
      }

      // Commit the transaction to release the SenderBean

      if (transaction!=null)
        transaction.commit();
     
      transaction = null;

            if ((processResponseForFaults || successfullySent) && !msgCtx.isServerSide()) {
                boolean  validCs = checkForSyncResponses(msgCtx );
                if (!validCs) {
                    invokeCallBackObject(storageManager,msgCtx ,
                            "Sandesha2 sender thread has not received a valid CreateSequnceResponse");
                }
            }

            if ((rmMsgCtx.getMessageType() == Sandesha2Constants.MessageTypes.TERMINATE_SEQ)
          &&
           (Sandesha2Constants.SPEC_2005_02.NS_URI.equals(rmMsgCtx.getRMNamespaceValue()))) {
        try {
          transaction = storageManager.getTransaction();
          //terminate message sent using the SandeshaClient. Since the terminate message will simply get the
          //InFlow of the reference message get called which could be zero sized (OutOnly operations).
         
          // terminate sending side if this is the WSRM 1.0 spec.
          // If the WSRM versoion is 1.1 termination will happen in the terminate sequence response message.
         
          TerminateSequence terminateSequence = (TerminateSequence) rmMsgCtx
              .getMessagePart(Sandesha2Constants.MessageParts.TERMINATE_SEQ);
          String sequenceID = terminateSequence.getIdentifier().getIdentifier();
 
          RMSBean rmsBean = SandeshaUtil.getRMSBeanFromSequenceId(storageManager, sequenceID);
          TerminateManager.terminateSendingSide(rmsBean, storageManager);
         
          if(transaction != null && transaction.isActive()) transaction.commit();
          transaction = null;
        } finally {
          if(transaction != null && transaction.isActive()) {
            transaction.rollback();
            transaction = null;
          }
        }
      }

    } catch (Exception e) {
      if (log.isDebugEnabled()) log.debug("Caught exception", e);
    } finally {
      if (lock!=null && workId!=null) {
        lock.removeWork(workId);
      }

      if (transaction!=null && transaction.isActive()) {
        try {
          transaction.rollback();
        } catch (SandeshaStorageException e) {
          if (log.isWarnEnabled())
            log.warn("Caught exception rolling back transaction", e);
        }
      }
    }
   
    if (log.isDebugEnabled())
      log.debug("Exit: SenderWorker::run");
  }
 
  /**
   * Update the message before sending it. We adjust the retransmission intervals and send counts
   * for the message. If the message is an application message then we ensure that we have added
   * the Sequence header.
   */
  private boolean updateMessage(RMMsgContext rmMsgContext, SenderBean senderBean, StorageManager storageManager) throws AxisFault {
   
    // Lock the message to enable retransmission update
    // No need to do the following. This is being done inside run(), which is the callee of
    // updateMessage()
    //senderBean = storageManager.getSenderBeanMgr().retrieve(senderBean.getMessageID());
   
    // Only continue if we find a SenderBean
    if (senderBean == null)
      return false;

    int messageType = senderBean.getMessageType();

    boolean continueSending = MessageRetransmissionAdjuster.adjustRetransmittion(
        rmMsgContext, senderBean, rmMsgContext.getConfigurationContext(), storageManager);
    if(!continueSending) return false;
   
    Identifier id = null;

    if(messageType == Sandesha2Constants.MessageTypes.APPLICATION ||
       messageType == Sandesha2Constants.MessageTypes.LAST_MESSAGE) {
     
      String namespace = SpecSpecificConstants.getRMNamespaceValue(rmVersion);
      Sequence sequence = (Sequence) rmMsgContext.getMessagePart(Sandesha2Constants.MessageParts.SEQUENCE);
      if(sequence == null) {
        sequence = new Sequence(namespace);
       
        MessageNumber msgNumber = new MessageNumber(namespace);
        msgNumber.setMessageNumber(senderBean.getMessageNumber());
        sequence.setMessageNumber(msgNumber);

        if(senderBean.isLastMessage() &&
            SpecSpecificConstants.isLastMessageIndicatorRequired(rmVersion)) {
          sequence.setLastMessage(new LastMessage(namespace));
        }
       
        // We just create the id here, we will add the value in later
        id = new Identifier(namespace);
        sequence.setIdentifier(id);
       
        rmMsgContext.setMessagePart(Sandesha2Constants.MessageParts.SEQUENCE, sequence);
       
      }
     
    } else if(messageType == Sandesha2Constants.MessageTypes.TERMINATE_SEQ) {
      TerminateSequence terminate = (TerminateSequence) rmMsgContext.getMessagePart(Sandesha2Constants.MessageParts.TERMINATE_SEQ);
      id = terminate.getIdentifier();

    } else if(messageType == Sandesha2Constants.MessageTypes.CLOSE_SEQUENCE) {
      CloseSequence close = (CloseSequence) rmMsgContext.getMessagePart(Sandesha2Constants.MessageParts.CLOSE_SEQUENCE);
      id = close.getIdentifier();
   
    } else if(messageType == Sandesha2Constants.MessageTypes.ACK_REQUEST) {
      // The only time that we can have a message of this type is when we are sending a
      // stand-alone ack request, and in that case we only expect to find a single ack
      // request header in the message.
      Iterator ackRequests = rmMsgContext.getMessageParts(Sandesha2Constants.MessageParts.ACK_REQUEST);
      AckRequested ackRequest = (AckRequested) ackRequests.next();
      if (ackRequests.hasNext()) {
        throw new SandeshaException (SandeshaMessageHelper.getMessage(SandeshaMessageKeys.ackRequestMultipleParts));
      }
      id = ackRequest.getIdentifier();
    }
   
    // TODO consider adding an extra ack request, as we are about to send the message and we
    // know which sequence it is associated with.

    if(id != null && !senderBean.getSequenceID().equals(id.getIdentifier())) {
      id.setIndentifer(senderBean.getSequenceID());

      // Write the changes back into the message context
      rmMsgContext.addSOAPEnvelope();
    }
   
    //if this is an sync WSRM 1.0 case we always have to add an ack
    boolean ackPresent = false;
    Iterator it = rmMsgContext.getMessageParts (Sandesha2Constants.MessageParts.SEQ_ACKNOWLEDGEMENT);
    if (it.hasNext())
      ackPresent = true;
   
    if (!ackPresent && rmMsgContext.getMessageContext().isServerSide()
        &&
      (messageType==Sandesha2Constants.MessageTypes.APPLICATION ||
         messageType==Sandesha2Constants.MessageTypes.APPLICATION ||
         messageType==Sandesha2Constants.MessageTypes.UNKNOWN ||
         messageType==Sandesha2Constants.MessageTypes.LAST_MESSAGE)) {
     
      String inboundSequenceId = senderBean.getInboundSequenceId();
      if (inboundSequenceId==null)
        throw new SandeshaException ("InboundSequenceID is not set for the sequence:" + id);
     
      RMDBean incomingSequenceBean = SandeshaUtil.getRMDBeanFromSequenceId(storageManager, inboundSequenceId);
     
      if (incomingSequenceBean!=null)
        RMMsgCreator.addAckMessage(rmMsgContext, inboundSequenceId, incomingSequenceBean);
     
    }
   
    return true;
  }
 
  private boolean isAckPiggybackableMsgType(int messageType) {
    if (log.isDebugEnabled())
      log.debug("Enter: SenderWorker::isAckPiggybackableMsgType, " + messageType);
    boolean piggybackable = true;

    if (messageType == Sandesha2Constants.MessageTypes.ACK)
      piggybackable = false;

    if (log.isDebugEnabled())
      log.debug("Exit: SenderWorker::isAckPiggybackableMsgType, " + piggybackable);
    return piggybackable;
  }

    /**
     * return value will be false if the create sequence fails else it will be true
     * @param msgCtx
     * @return
     */
    private boolean checkForSyncResponses(MessageContext msgCtx ) {
    if (log.isDebugEnabled())
      log.debug("Enter: SenderWorker::checkForSyncResponses, " + msgCtx.getEnvelope().getHeader());

    try {

      // create the responseMessageContext

      MessageContext responseMessageContext = msgCtx.getOperationContext().getMessageContext(WSDLConstants.MESSAGE_LABEL_IN_VALUE);
      SOAPEnvelope resenvelope = null;
      if (responseMessageContext!=null)
        resenvelope = responseMessageContext.getEnvelope();
     
      boolean transportInPresent = (msgCtx.getProperty(MessageContext.TRANSPORT_IN) != null);
      if (!transportInPresent && (responseMessageContext==null || responseMessageContext.getEnvelope()==null)) {
        if(log.isDebugEnabled()) log.debug("Exit: SenderWorker::checkForSyncResponses, no response present");
        return true;
      }
     
      //to find out weather the response was built by me.
      boolean syncResponseBuilt = false;
     
      if (responseMessageContext==null || responseMessageContext.getEnvelope()==null) {
        if (responseMessageContext==null)
          responseMessageContext = new MessageContext();

        OperationContext requestMsgOpCtx = msgCtx.getOperationContext();
                responseMessageContext.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING, requestMsgOpCtx
                .getProperty(Constants.Configuration.CHARACTER_SET_ENCODING));
        responseMessageContext.setProperty(Constants.Configuration.CONTENT_TYPE, requestMsgOpCtx
                .getProperty(Constants.Configuration.CONTENT_TYPE));
        responseMessageContext.setProperty(HTTPConstants.MTOM_RECEIVED_CONTENT_TYPE, requestMsgOpCtx
                .getProperty(HTTPConstants.MTOM_RECEIVED_CONTENT_TYPE));
//                responseMessageContext.setOperationContext(requestMsgOpCtx);
//                if ( !requestMsgOpCtx.isComplete()) {
//                    requestMsgOpCtx.addMessageContext(responseMessageContext);
//                }
                responseMessageContext.setAxisOperation(msgCtx.getAxisOperation());

                //If the response MsgCtx was not available Axis2 would hv put the transport info into a
        //HashMap, getting the data from it.
        HashMap transportInfoMap = (HashMap) msgCtx.getProperty(Constants.Configuration.TRANSPORT_INFO_MAP);
        if (transportInfoMap != null) {
          responseMessageContext.setProperty(Constants.Configuration.CONTENT_TYPE,
                  transportInfoMap.get(Constants.Configuration.CONTENT_TYPE));
          responseMessageContext.setProperty(Constants.Configuration.CHARACTER_SET_ENCODING,
                  transportInfoMap.get(Constants.Configuration.CHARACTER_SET_ENCODING));
        }
     
        responseMessageContext.setConfigurationContext(msgCtx.getConfigurationContext());
        responseMessageContext.setTransportIn(msgCtx.getTransportIn());
        responseMessageContext.setTransportOut(msgCtx.getTransportOut());
        responseMessageContext.setProperty(MessageContext.TRANSPORT_IN, msgCtx
            .getProperty(MessageContext.TRANSPORT_IN));
       
        //we will not be setting the operation context here since this msgs may not be an application reply.
        //we let other dispatchers find it.
        responseMessageContext.setServiceContext(msgCtx.getServiceContext());
        responseMessageContext.setServiceGroupContext(msgCtx.getServiceGroupContext());

        responseMessageContext.setProperty(Sandesha2Constants.MessageContextProperties.MAKECONNECTION_ENTRY,
        msgCtx.getProperty(Sandesha2Constants.MessageContextProperties.MAKECONNECTION_ENTRY));

        // If request is REST we assume the responseMessageContext is REST,
        // so set the variable

        responseMessageContext.setDoingREST(msgCtx.isDoingREST());

        resenvelope = responseMessageContext.getEnvelope();
        try {
          // MessageContext is modified in TransportUtils.createSOAPMessage(). It might be used by axis.engine or handler.
          // To catch the modification and pass it to engine or handler, resenvelope is created by responseMessageContext.
          if (resenvelope==null) {
            //We try to build the response out of the transport stream.
            resenvelope = TransportUtils.createSOAPMessage(responseMessageContext);
            responseMessageContext.setEnvelope(resenvelope);
            syncResponseBuilt = true;
          }
        } catch (AxisFault e) {
          //Cannot find a valid SOAP envelope.
          if (log.isErrorEnabled() ) {
            log.error (SandeshaMessageHelper
                .getMessage(SandeshaMessageKeys.soapEnvNotSet));
          log.error ("Caught exception", e);
          }
       
          return true;
        }
       
        //If addressing is disabled we will be adding this message simply as the application response of the request message.
        Boolean addressingDisabled = (Boolean) msgCtx.getProperty(AddressingConstants.DISABLE_ADDRESSING_FOR_OUT_MESSAGES);
        if (addressingDisabled!=null && Boolean.TRUE.equals(addressingDisabled)) {
          // If the AxisOperation object doesn't have a message receiver, it means that this was
          // an out only op where we have added an ACK to the response.  Set the requestMsgOpCtx to
          // be the RMIn
          OperationContext responseMsgOpCtx = requestMsgOpCtx;
          if (requestMsgOpCtx.getAxisOperation().getMessageReceiver() == null) {
            // Generate a new RM In Only operation

            ServiceContext serviceCtx = responseMessageContext.getServiceContext();
            AxisOperation op = msgCtx.getAxisService().getOperation(Sandesha2Constants.RM_IN_ONLY_OPERATION);
            responseMsgOpCtx = OperationContextFactory.createOperationContext (op.getAxisSpecificMEPConstant(), op, serviceCtx);         

          }
         
          responseMessageContext.setOperationContext(responseMsgOpCtx);
        }
       
        AxisOperation operation = msgCtx.getAxisOperation();
        if (operation!=null && responseMessageContext.getAxisMessage()==null
            && !(operation instanceof OutOnlyAxisOperation))
          responseMessageContext.setAxisMessage(operation.getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE));

        RMMsgContext responseRMMessage = MsgInitializer.initializeMessage(responseMessageContext);
        if (responseRMMessage.getMessageType()==Sandesha2Constants.MessageTypes.ACK) {
          responseMessageContext.setAxisOperation(SpecSpecificConstants.getWSRMOperation
              (Sandesha2Constants.MessageTypes.ACK, responseRMMessage.getRMSpecVersion(), responseMessageContext.getAxisService()));
          responseMessageContext.setOperationContext(null);
        }
       
      }
     
      //if the syncResponseWas not built here and the client was not expecting a sync response. We will not try to execute
      //here. Doing so will cause a double invocation for a async message.
      if (msgCtx.getOptions().isUseSeparateListener()==true &&  !syncResponseBuilt) {
        return true;
      }
     
     
      //setting the message as serverSide will let it go through the MessageReceiver (may be callback MR).
      responseMessageContext.setServerSide(true);
   
      if (responseMessageContext.getSoapAction()==null) {
        //if there is no SOAP action in the response message, Axis2 will wrongly identify it as a REST message
        //This happens because we set serverSide to True in a previous step.
        //So we have to add a empty SOAPAction here.
        responseMessageContext.setSoapAction("");
      }

      if (resenvelope!=null) {
        AxisEngine.receive(responseMessageContext);
      }

    } catch (Exception e) {

            String message = SandeshaMessageHelper.getMessage(SandeshaMessageKeys.noValidSyncResponse);
            if (msgCtx != null &&! msgCtx.isServerSide() &&
                    (Sandesha2Constants.SPEC_2005_02.Actions.ACTION_CREATE_SEQUENCE.equals(msgCtx.getSoapAction())
                            || Sandesha2Constants.SPEC_2007_02.Actions.ACTION_CREATE_SEQUENCE.equals(msgCtx.getSoapAction())) ){
                // We have not received a valid createSequnce reponse for the request we send so we need to terminate the seunce here
                return false;
            } else {
                if (log.isWarnEnabled())
                    log.warn(message, e);
            }
    }
    if (log.isDebugEnabled())
      log.debug("Exit: SenderWorker::checkForSyncResponses");
        return true;
    }
 
  private void recordError (Exception e, RMMsgContext outRMMsg, StorageManager storageManager) throws SandeshaStorageException {
    // Store the Exception as a sequence property to enable the client to lookup the last
    // exception time and timestamp.
   
    Transaction transaction = null;
   
    try
    {
      // Get the internal sequence id from the context
      String internalSequenceId = (String)outRMMsg.getProperty(Sandesha2Constants.MessageContextProperties.INTERNAL_SEQUENCE_ID);
      if(internalSequenceId == null) internalSequenceId = senderBean.getInternalSequenceID();
     
      if(internalSequenceId != null) {
        // Create a new Transaction
        transaction = storageManager.getTransaction();
       
        RMSBean bean = SandeshaUtil.getRMSBeanFromInternalSequenceId(storageManager, internalSequenceId);
     
        if (bean != null) {           
          bean.setLastSendError(e);
          bean.setLastSendErrorTimestamp(System.currentTimeMillis());

          // Update the RMSBean
          storageManager.getRMSBeanMgr().update(bean);
        }
       
        // Commit the properties
        if(transaction != null) {
          transaction.commit();
          transaction = null;
        }
      }
    }
    catch (Exception e1)
    {
      if (log.isErrorEnabled())
        log.error(e1);
    } finally {
      if (transaction != null) {
        transaction.rollback();
        transaction = null;
      }
    }
  }

    private void invokeCallBackObject(StorageManager storageManager,
                                      MessageContext msgCtx,
                                      String message) throws SandeshaStorageException {
        Transaction transaction = null;
        if (msgCtx.isServerSide()) {
            return;
        }
        try {
            transaction = storageManager.getTransaction();
            //terminate message sent using the SandeshaClient. Since the terminate message will simply get the
            //InFlow of the reference message get called which could be zero sized (OutOnly operations).

            // terminate sending side if this is the WSRM 1.0 spec.
            // If the WSRM versoion is 1.1 termination will happen in the terminate sequence response message.

            String internalSequenceId = (String) msgCtx.getProperty(Sandesha2Constants.MessageContextProperties.INTERNAL_SEQUENCE_ID);
            if (internalSequenceId == null) internalSequenceId = senderBean.getInternalSequenceID();
            if (internalSequenceId != null) {
                // Create a new Transaction
                transaction = storageManager.getTransaction();
                RMSBean bean = SandeshaUtil.getRMSBeanFromInternalSequenceId(storageManager, internalSequenceId);
                TerminateManager.terminateSendingSide(bean, storageManager);

                OperationContext opCtx =
                        configurationContext.getOperationContext(bean.getApplicationMessageMessageId());
                if (opCtx != null) {
                    AxisOperation applicationAxisOperation = opCtx.getAxisOperation();
                    if (applicationAxisOperation != null) {
                        MessageReceiver msgReceiver = applicationAxisOperation.getMessageReceiver();
                        if ((msgReceiver != null) && (msgReceiver instanceof CallbackReceiver)) {
                            Object callback = ((CallbackReceiver) msgReceiver)
                                    .lookupCallback(bean.getApplicationMessageMessageId());
                            if (callback != null) {
                                AxisCallback axisCallback = ((AxisCallback) callback);
                                axisCallback.onError(new Exception(message));
                                axisCallback.onComplete();
                            }
                        }
                    }
                }
                if (transaction != null && transaction.isActive()) transaction.commit();
                transaction = null;
            }

        } catch (Exception e) {
            if (log.isWarnEnabled())
                log.warn(e);
        } finally {
            if (transaction != null && transaction.isActive()) {
                transaction.rollback();
                transaction = null;
            }
        }
    }

}
TOP

Related Classes of org.apache.sandesha2.workers.SenderWorker

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.