/*
  * Merges the statistics logs of the ESB artifacts that are not already
  * collected by the request flow.
  */
 private void mergeStatisticsRecords(
     final StatisticsRecord source, final StatisticsRecord destination) {
   StatisticsRecord clonedSourceStatRecord = MessageHelper.getClonedStatisticRecord(source);
   for (StatisticsLog clonedSourceStatLog : clonedSourceStatRecord.getAllStatisticsLogs()) {
     if (!clonedSourceStatLog.isCollectedByRequestFlow()) {
       destination.collect(clonedSourceStatLog);
     }
   }
 }
  private static MessageContext cloneForSend(MessageContext ori, String preserveAddressing)
      throws AxisFault {

    MessageContext newMC = MessageHelper.clonePartially(ori);

    newMC.setEnvelope(ori.getEnvelope());
    if (preserveAddressing != null && Boolean.parseBoolean(preserveAddressing)) {
      newMC.setMessageID(ori.getMessageID());
    } else {
      MessageHelper.removeAddressingHeaders(newMC);
    }

    newMC.setProperty(
        org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS,
        ori.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS));

    return newMC;
  }
Exemple #3
0
  /**
   * clone the provided message context as a new message, and mark as the messageSequence'th message
   * context of a total of messageCount messages
   *
   * @param synCtx - MessageContext which is subjected to the cloning
   * @param messageSequence - the position of this message of the cloned set
   * @param messageCount - total of cloned copies
   * @return MessageContext the cloned message context
   */
  private MessageContext getClonedMessageContext(
      MessageContext synCtx, int messageSequence, int messageCount) {

    MessageContext newCtx = null;
    try {

      newCtx = MessageHelper.cloneMessageContext(synCtx);

      StatisticsRecord statRecord =
          (StatisticsRecord) newCtx.getProperty(SynapseConstants.STATISTICS_STACK);
      if (statRecord != null) {
        for (StatisticsLog statLog : statRecord.getAllStatisticsLogs()) {
          /*
           * Marks that this statistics log is collected by the
           * request flow.
           */
          statLog.setCollectedByRequestFlow(true);
        }
      }
      // Set isServerSide property in the cloned message context
      ((Axis2MessageContext) newCtx)
          .getAxis2MessageContext()
          .setServerSide(((Axis2MessageContext) synCtx).getAxis2MessageContext().isServerSide());

      if (id != null) {
        // set the parent correlation details to the cloned MC -
        //                              for the use of aggregation like tasks
        newCtx.setProperty(EIPConstants.AGGREGATE_CORRELATION + "." + id, synCtx.getMessageID());
        // set the property MESSAGE_SEQUENCE to the MC for aggregation purposes
        newCtx.setProperty(
            EIPConstants.MESSAGE_SEQUENCE + "." + id,
            String.valueOf(messageSequence)
                + EIPConstants.MESSAGE_SEQUENCE_DELEMITER
                + messageCount);
      } else {
        newCtx.setProperty(
            EIPConstants.MESSAGE_SEQUENCE,
            String.valueOf(messageSequence)
                + EIPConstants.MESSAGE_SEQUENCE_DELEMITER
                + messageCount);
      }
    } catch (AxisFault axisFault) {
      handleException("Error cloning the message context", axisFault, synCtx);
    }

    return newCtx;
  }
  /**
   * This will call the send method on the messages with implicit message parameters or else if
   * there is an endpoint, with that endpoint parameters
   *
   * @param synInCtx the current message to be sent
   * @return false for in-out invocations as flow should put on to hold after the Call mediator,
   *     true for out only invocations
   */
  public boolean mediate(MessageContext synInCtx) {

    if (synInCtx.getEnvironment().isDebuggerEnabled()) {
      MessageHelper.setWireLogHolderProperties(
          synInCtx,
          isBreakPoint(),
          getRegisteredMediationFlowPoint()); // this needs to be set only in mediators where
                                              // outgoing messages are present
      if (super.divertMediationRoute(synInCtx)) {
        return true;
      }
    }

    if (blocking) {
      return handleBlockingCall(synInCtx);
    } else {
      return handleNonBlockingCall(synInCtx);
    }
  }
  public boolean dispatch(MessageContext messageContext) {

    if (log.isDebugEnabled()) {
      log.debug(
          "Sending the message to client with message processor ["
              + messageProcessor.getName()
              + "]");
    }

    // The below code is just for keeping the backward compatibility with the old code.
    if (targetEndpoint == null) {
      targetEndpoint =
          (String) messageContext.getProperty(ForwardingProcessorConstants.TARGET_ENDPOINT);
    }

    MessageContext outCtx = null;
    SOAPEnvelope originalEnvelop = messageContext.getEnvelope();

    if (targetEndpoint != null) {
      Endpoint ep = messageContext.getEndpoint(targetEndpoint);

      try {

        // Send message to the client
        while (!isSuccessful && !isTerminated) {
          try {
            // For each retry we need to have a fresh copy of the actual message. otherwise retry
            // may not
            // work as expected.
            messageContext.setEnvelope(MessageHelper.cloneSOAPEnvelope(originalEnvelop));
            OMElement firstChild = null; //
            org.apache.axis2.context.MessageContext origAxis2Ctx =
                ((Axis2MessageContext) messageContext).getAxis2MessageContext();
            if (JsonUtil.hasAJsonPayload(origAxis2Ctx)) {
              firstChild = origAxis2Ctx.getEnvelope().getBody().getFirstElement();
            } // Had to do this because MessageHelper#cloneSOAPEnvelope does not clone
            // OMSourcedElemImpl correctly.
            if (JsonUtil.hasAJsonPayload(firstChild)) { //
              OMElement clonedFirstElement =
                  messageContext.getEnvelope().getBody().getFirstElement();
              if (clonedFirstElement != null) {
                clonedFirstElement.detach();
                messageContext.getEnvelope().getBody().addChild(firstChild);
              }
            } // Had to do this because MessageHelper#cloneSOAPEnvelope does not clone
            // OMSourcedElemImpl correctly.
            origAxis2Ctx.setProperty(
                HTTPConstants.NON_ERROR_HTTP_STATUS_CODES, getNonRetryStatusCodes());
            outCtx = sender.send(ep, messageContext);
            isSuccessful = true;

          } catch (Exception e) {

            // this means send has failed due to some reason so we have to retry it
            if (e instanceof SynapseException) {
              isSuccessful = isNonRetryErrorCode(e.getCause().getMessage());
            }
            if (!isSuccessful) {
              log.error(
                  "BlockingMessageSender of message processor ["
                      + this.messageProcessor.getName()
                      + "] failed to send message to the endpoint");
            }
          }

          if (isSuccessful) {
            if (outCtx != null) {
              if ("true"
                  .equals(outCtx.getProperty(ForwardingProcessorConstants.BLOCKING_SENDER_ERROR))) {

                // this means send has failed due to some reason so we have to retry it
                isSuccessful =
                    isNonRetryErrorCode(
                        (String) outCtx.getProperty(SynapseConstants.ERROR_MESSAGE));

                if (isSuccessful) {
                  sendThroughReplySeq(outCtx);
                } else {
                  // This means some error has occurred so must try to send down the fault sequence.
                  log.error(
                      "BlockingMessageSender of message processor ["
                          + this.messageProcessor.getName()
                          + "] failed to send message to the endpoint");
                  sendThroughFaultSeq(outCtx);
                }
              } else {
                // Send the message down the reply sequence if there is one
                sendThroughReplySeq(outCtx);
                messageConsumer.ack();
                attemptCount = 0;
                isSuccessful = true;

                if (log.isDebugEnabled()) {
                  log.debug(
                      "Successfully sent the message to endpoint ["
                          + ep.getName()
                          + "]"
                          + " with message processor ["
                          + messageProcessor.getName()
                          + "]");
                }
              }
            } else {
              // This Means we have invoked an out only operation
              // remove the message and reset the count
              messageConsumer.ack();
              attemptCount = 0;
              isSuccessful = true;

              if (log.isDebugEnabled()) {
                log.debug(
                    "Successfully sent the message to endpoint ["
                        + ep.getName()
                        + "]"
                        + " with message processor ["
                        + messageProcessor.getName()
                        + "]");
              }
            }
          }

          if (!isSuccessful) {
            // Then we have to retry sending the message to the client.
            prepareToRetry();
          } else {
            if (messageProcessor.isPaused()) {
              this.messageProcessor.resumeService();
              log.info(
                  "Resuming the service of message processor [" + messageProcessor.getName() + "]");
            }
          }
        }
      } catch (Exception e) {
        log.error(
            "Message processor ["
                + messageProcessor.getName()
                + "] failed to send the message to"
                + " client",
            e);
      }
    } else {
      // No Target Endpoint defined for the Message
      // So we do not have a place to deliver.
      // Here we log a warning and remove the message
      // todo: we can improve this by implementing a target inferring mechanism

      log.warn(
          "Property "
              + ForwardingProcessorConstants.TARGET_ENDPOINT
              + " not found in the message context , Hence removing the message ");

      messageConsumer.ack();
    }

    return true;
  }
  /**
   * Get the aggregated message from the specified Aggregate instance
   *
   * @param aggregate the Aggregate object that holds collected messages and properties of the
   *     aggregation
   * @return the aggregated message context
   */
  private MessageContext getAggregatedMessage(Aggregate aggregate) {

    MessageContext newCtx = null;
    StatisticsRecord destinationStatRecord = null;

    for (MessageContext synCtx : aggregate.getMessages()) {

      if (newCtx == null) {
        try {
          newCtx = MessageHelper.cloneMessageContextForAggregateMediator(synCtx);
          destinationStatRecord =
              (StatisticsRecord) newCtx.getProperty(SynapseConstants.STATISTICS_STACK);
        } catch (AxisFault axisFault) {
          handleException("Error creating a copy of the message", axisFault, synCtx);
        }

        if (log.isDebugEnabled()) {
          log.debug("Generating Aggregated message from : " + newCtx.getEnvelope());
        }

      } else {
        try {
          if (log.isDebugEnabled()) {
            log.debug(
                "Merging message : "
                    + synCtx.getEnvelope()
                    + " using XPath : "
                    + aggregationExpression);
          }

          EIPUtils.enrichEnvelope(
              newCtx.getEnvelope(), synCtx.getEnvelope(), synCtx, aggregationExpression);
          if (destinationStatRecord != null
              && synCtx.getProperty(SynapseConstants.STATISTICS_STACK) != null) {
            // Merge the statistics logs to one single message
            // context.
            mergeStatisticsRecords(
                (StatisticsRecord) synCtx.getProperty(SynapseConstants.STATISTICS_STACK),
                destinationStatRecord);
          }

          if (log.isDebugEnabled()) {
            log.debug("Merged result : " + newCtx.getEnvelope());
          }

        } catch (JaxenException e) {
          handleException(
              "Error merging aggregation results using XPath : " + aggregationExpression.toString(),
              e,
              synCtx);
        } catch (SynapseException e) {
          handleException(
              "Error evaluating expression: " + aggregationExpression.toString(), e, synCtx);
        }
      }
    }

    // Enclose with a parent element if EnclosingElement is defined
    if (enclosingElementPropertyName != null) {

      if (log.isDebugEnabled()) {
        log.debug(
            "Enclosing the aggregated message with enclosing element: "
                + enclosingElementPropertyName);
      }

      Object enclosingElementProperty = newCtx.getProperty(enclosingElementPropertyName);

      if (enclosingElementProperty != null) {
        if (enclosingElementProperty instanceof OMElement) {
          OMElement enclosingElement = ((OMElement) enclosingElementProperty).cloneOMElement();
          EIPUtils.encloseWithElement(newCtx.getEnvelope(), enclosingElement);

          return newCtx;

        } else {
          handleException(
              "Enclosing Element defined in the property: "
                  + enclosingElementPropertyName
                  + " is not an OMElement ",
              newCtx);
        }
      } else {
        handleException(
            "Enclosing Element property: " + enclosingElementPropertyName + " not found ", newCtx);
      }
    }

    if (MessageFlowTracingDataCollector.isMessageFlowTracingEnabled()) {
      List<String> newMessageFlowTrace = new ArrayList<String>();
      for (MessageContext synCtx : aggregate.getMessages()) {
        List<String> messageFlowTrace =
            (List<String>) synCtx.getProperty(MessageFlowTracerConstants.MESSAGE_FLOW);
        if (null != messageFlowTrace) {
          newMessageFlowTrace.addAll(messageFlowTrace);
        }
      }
      newCtx.setProperty(MessageFlowTracerConstants.MESSAGE_FLOW, newMessageFlowTrace);
    }

    return newCtx;
  }
  /**
   * Invoked by the Aggregate objects that are timed out, to signal timeout/completion of itself
   *
   * @param aggregate the timed out Aggregate that holds collected messages and properties
   */
  public boolean completeAggregate(Aggregate aggregate) {

    boolean markedCompletedNow = false;
    boolean wasComplete = aggregate.isCompleted();
    if (wasComplete) {
      return false;
    }

    if (log.isDebugEnabled()) {
      log.debug("Aggregation completed or timed out");
    }

    // cancel the timer
    synchronized (this) {
      if (!aggregate.isCompleted()) {
        aggregate.cancel();
        aggregate.setCompleted(true);
        markedCompletedNow = true;
      }
    }

    if (!markedCompletedNow) {
      return false;
    }

    MessageContext newSynCtx = getAggregatedMessage(aggregate);

    if (newSynCtx == null) {
      log.warn("An aggregation of messages timed out with no aggregated messages", null);
      return false;
    } else {
      // Get the aggregated message to the next mediator placed after the aggregate mediator
      // in the sequence
      if (newSynCtx.isContinuationEnabled()) {
        try {
          aggregate
              .getLastMessage()
              .setEnvelope(MessageHelper.cloneSOAPEnvelope(newSynCtx.getEnvelope()));
        } catch (AxisFault axisFault) {
          log.warn(
              "Error occurred while assigning aggregated message"
                  + " back to the last received message context");
        }
      }
    }

    aggregate.clear();
    activeAggregates.remove(aggregate.getCorrelation());

    if ((correlateExpression != null
            && !correlateExpression.toString().equals(aggregate.getCorrelation()))
        || correlateExpression == null) {

      if (onCompleteSequence != null) {

        ContinuationStackManager.addReliantContinuationState(newSynCtx, 0, getMediatorPosition());
        boolean result = onCompleteSequence.mediate(newSynCtx);
        if (result) {
          ContinuationStackManager.removeReliantContinuationState(newSynCtx);
        }
        return result;

      } else if (onCompleteSequenceRef != null
          && newSynCtx.getSequence(onCompleteSequenceRef) != null) {

        ContinuationStackManager.updateSeqContinuationState(newSynCtx, getMediatorPosition());
        return newSynCtx.getSequence(onCompleteSequenceRef).mediate(newSynCtx);

      } else {
        handleException(
            "Unable to find the sequence for the mediation " + "of the aggregated message",
            newSynCtx);
      }
    }
    return false;
  }
  /**
   * Based on the Axis2 client code. Sends the Axis2 Message context out and returns the Axis2
   * message context for the response.
   *
   * <p>Here Synapse works as a Client to the service. It would expect 200 ok, 202 ok and 500
   * internal server error as possible responses.
   *
   * @param endpoint the endpoint being sent to, maybe null
   * @param synapseOutMessageContext the outgoing synapse message
   * @throws AxisFault on errors
   */
  public static void send(
      EndpointDefinition endpoint, org.apache.synapse.MessageContext synapseOutMessageContext)
      throws AxisFault {

    boolean separateListener = false;
    boolean wsSecurityEnabled = false;
    String wsSecPolicyKey = null;
    String inboundWsSecPolicyKey = null;
    String outboundWsSecPolicyKey = null;
    boolean wsRMEnabled = false;
    String wsRMPolicyKey = null;
    boolean wsAddressingEnabled = false;
    String wsAddressingVersion = null;

    if (endpoint != null) {
      separateListener = endpoint.isUseSeparateListener();
      wsSecurityEnabled = endpoint.isSecurityOn();
      wsSecPolicyKey = endpoint.getWsSecPolicyKey();
      inboundWsSecPolicyKey = endpoint.getInboundWsSecPolicyKey();
      outboundWsSecPolicyKey = endpoint.getOutboundWsSecPolicyKey();
      wsRMEnabled = endpoint.isReliableMessagingOn();
      wsRMPolicyKey = endpoint.getWsRMPolicyKey();
      wsAddressingEnabled = endpoint.isAddressingOn() || wsRMEnabled;
      wsAddressingVersion = endpoint.getAddressingVersion();
    }

    if (log.isDebugEnabled()) {
      String to;
      if (endpoint != null && endpoint.getAddress() != null) {
        to = endpoint.getAddress(synapseOutMessageContext);
      } else {
        to = synapseOutMessageContext.getTo().toString();
      }

      log.debug(
          "Sending [add = "
              + wsAddressingEnabled
              + "] [sec = "
              + wsSecurityEnabled
              + "] [rm = "
              + wsRMEnabled
              + (endpoint != null
                  ? "] [mtom = "
                      + endpoint.isUseMTOM()
                      + "] [swa = "
                      + endpoint.isUseSwa()
                      + "] [format = "
                      + endpoint.getFormat()
                      + "] [force soap11="
                      + endpoint.isForceSOAP11()
                      + "] [force soap12="
                      + endpoint.isForceSOAP12()
                      + "] [pox="
                      + endpoint.isForcePOX()
                      + "] [get="
                      + endpoint.isForceGET()
                      + "] [encoding="
                      + endpoint.getCharSetEncoding()
                  : "")
              + "] [to="
              + to
              + "]");
    }

    // save the original message context without altering it, so we can tie the response
    MessageContext originalInMsgCtx =
        ((Axis2MessageContext) synapseOutMessageContext).getAxis2MessageContext();

    // TODO Temp hack: ESB removes the session id from request in a random manner.
    Map headers = (Map) originalInMsgCtx.getProperty(MessageContext.TRANSPORT_HEADERS);
    String session = (String) synapseOutMessageContext.getProperty("LB_COOKIE_HEADER");
    if (session != null) {
      headers.put("Cookie", session);
    }

    // create a new MessageContext to be sent out as this should not corrupt the original
    // we need to create the response to the original message later on
    String preserveAddressingProperty =
        (String) synapseOutMessageContext.getProperty(SynapseConstants.PRESERVE_WS_ADDRESSING);
    MessageContext axisOutMsgCtx = cloneForSend(originalInMsgCtx, preserveAddressingProperty);

    if (log.isDebugEnabled()) {
      log.debug(
          "Message [Original Request Message ID : "
              + synapseOutMessageContext.getMessageID()
              + "]"
              + " [New Cloned Request Message ID : "
              + axisOutMsgCtx.getMessageID()
              + "]");
    }
    // set all the details of the endpoint only to the cloned message context
    // so that we can use the original message context for resending through different endpoints
    if (endpoint != null) {

      if (SynapseConstants.FORMAT_POX.equals(endpoint.getFormat())) {
        axisOutMsgCtx.setDoingREST(true);
        axisOutMsgCtx.setProperty(
            org.apache.axis2.Constants.Configuration.MESSAGE_TYPE,
            org.apache.axis2.transport.http.HTTPConstants.MEDIA_TYPE_APPLICATION_XML);
        axisOutMsgCtx.setProperty(
            Constants.Configuration.CONTENT_TYPE,
            org.apache.axis2.transport.http.HTTPConstants.MEDIA_TYPE_APPLICATION_XML);

        Object o =
            axisOutMsgCtx.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
        Map _headers = (Map) o;
        if (_headers != null) {
          _headers.remove(HTTP.CONTENT_TYPE);
          _headers.put(
              HTTP.CONTENT_TYPE,
              org.apache.axis2.transport.http.HTTPConstants.MEDIA_TYPE_APPLICATION_XML);
        }

      } else if (SynapseConstants.FORMAT_GET.equals(endpoint.getFormat())) {
        axisOutMsgCtx.setDoingREST(true);
        axisOutMsgCtx.setProperty(
            Constants.Configuration.HTTP_METHOD, Constants.Configuration.HTTP_METHOD_GET);
        axisOutMsgCtx.setProperty(
            org.apache.axis2.Constants.Configuration.MESSAGE_TYPE,
            org.apache.axis2.transport.http.HTTPConstants.MEDIA_TYPE_X_WWW_FORM);

      } else if (SynapseConstants.FORMAT_SOAP11.equals(endpoint.getFormat())) {
        axisOutMsgCtx.setDoingREST(false);
        axisOutMsgCtx.removeProperty(org.apache.axis2.Constants.Configuration.MESSAGE_TYPE);
        // We need to set this explicitly here in case the request was not a POST
        axisOutMsgCtx.setProperty(
            Constants.Configuration.HTTP_METHOD, Constants.Configuration.HTTP_METHOD_POST);
        if (axisOutMsgCtx.getSoapAction() == null && axisOutMsgCtx.getWSAAction() != null) {
          axisOutMsgCtx.setSoapAction(axisOutMsgCtx.getWSAAction());
        }
        if (!axisOutMsgCtx.isSOAP11()) {
          SOAPUtils.convertSOAP12toSOAP11(axisOutMsgCtx);
        }
        Object o =
            axisOutMsgCtx.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
        Map _headers = (Map) o;
        if (_headers != null) {
          _headers.remove(HTTP.CONTENT_TYPE);
          _headers.put(
              HTTP.CONTENT_TYPE, org.apache.axis2.transport.http.HTTPConstants.MEDIA_TYPE_TEXT_XML);
        }

      } else if (SynapseConstants.FORMAT_SOAP12.equals(endpoint.getFormat())) {
        axisOutMsgCtx.setDoingREST(false);
        axisOutMsgCtx.removeProperty(org.apache.axis2.Constants.Configuration.MESSAGE_TYPE);
        // We need to set this explicitly here in case the request was not a POST
        axisOutMsgCtx.setProperty(
            Constants.Configuration.HTTP_METHOD, Constants.Configuration.HTTP_METHOD_POST);
        if (axisOutMsgCtx.getSoapAction() == null && axisOutMsgCtx.getWSAAction() != null) {
          axisOutMsgCtx.setSoapAction(axisOutMsgCtx.getWSAAction());
        }
        if (axisOutMsgCtx.isSOAP11()) {
          SOAPUtils.convertSOAP11toSOAP12(axisOutMsgCtx);
        }
        Object o =
            axisOutMsgCtx.getProperty(org.apache.axis2.context.MessageContext.TRANSPORT_HEADERS);
        Map _headers = (Map) o;
        if (_headers != null) {
          _headers.remove(HTTP.CONTENT_TYPE);
          _headers.put(
              HTTP.CONTENT_TYPE,
              org.apache.axis2.transport.http.HTTPConstants.MEDIA_TYPE_APPLICATION_SOAP_XML);
        }

      } else if (SynapseConstants.FORMAT_REST.equals(endpoint.getFormat())) {
        /*format=rest is kept only backword compatibility. We no longer needed that.*/
        /* Remove Message Type  for GET and DELETE Request */
        if (originalInMsgCtx.getProperty(Constants.Configuration.HTTP_METHOD) != null) {
          if (originalInMsgCtx
                  .getProperty(Constants.Configuration.HTTP_METHOD)
                  .toString()
                  .equals(Constants.Configuration.HTTP_METHOD_GET)
              || originalInMsgCtx
                  .getProperty(Constants.Configuration.HTTP_METHOD)
                  .toString()
                  .equals(Constants.Configuration.HTTP_METHOD_DELETE)) {
            axisOutMsgCtx.removeProperty(org.apache.axis2.Constants.Configuration.MESSAGE_TYPE);
          }
        }
        axisOutMsgCtx.setDoingREST(true);
      } else {
        processWSDL2RESTRequestMessageType(originalInMsgCtx, axisOutMsgCtx);
      }

      if (endpoint.isUseMTOM()) {
        axisOutMsgCtx.setDoingMTOM(true);
        // fix / workaround for AXIS2-1798
        axisOutMsgCtx.setProperty(
            org.apache.axis2.Constants.Configuration.ENABLE_MTOM,
            org.apache.axis2.Constants.VALUE_TRUE);
        axisOutMsgCtx.setDoingMTOM(true);

      } else if (endpoint.isUseSwa()) {
        axisOutMsgCtx.setDoingSwA(true);
        // fix / workaround for AXIS2-1798
        axisOutMsgCtx.setProperty(
            org.apache.axis2.Constants.Configuration.ENABLE_SWA,
            org.apache.axis2.Constants.VALUE_TRUE);
        axisOutMsgCtx.setDoingSwA(true);
      }

      if (endpoint.getCharSetEncoding() != null) {
        axisOutMsgCtx.setProperty(
            Constants.Configuration.CHARACTER_SET_ENCODING, endpoint.getCharSetEncoding());
        // Need to Clean this up. TargetRequest line 176 contains a code block which over writes the
        // Content-Type returned by the message formatter with the Content-Type in
        // TRANSPORT_HEADERS. Because of that, even when
        // the Character set encoding is set by the message formatter, it will be replaced by the
        // Content-Type header in TRANSPORT_HEADERS.
        // So Im setting a property to check in TargetRequest before over writing the header.
        axisOutMsgCtx.setProperty("EndpointCharEncodingSet", "true");
      }

      // HTTP Endpoint : use the specified HTTP method and remove REST_URL_POSTFIX, it's not
      // supported in HTTP Endpoint
      if (endpoint.isHTTPEndpoint()) {
        axisOutMsgCtx.setProperty(
            Constants.Configuration.HTTP_METHOD,
            synapseOutMessageContext.getProperty(Constants.Configuration.HTTP_METHOD));
        axisOutMsgCtx.removeProperty(NhttpConstants.REST_URL_POSTFIX);
      }

      // add rest request' suffix URI
      String restSuffix = (String) axisOutMsgCtx.getProperty(NhttpConstants.REST_URL_POSTFIX);
      boolean isRest = SynapseConstants.FORMAT_REST.equals(endpoint.getFormat());

      if (!isRest && !endpoint.isForceSOAP11() && !endpoint.isForceSOAP12()) {
        isRest = isRequestRest(originalInMsgCtx);
      }

      if (endpoint.getAddress() != null) {
        String address = endpoint.getAddress(synapseOutMessageContext);
        if (isRest && restSuffix != null && !"".equals(restSuffix)) {

          String url;
          if (!address.endsWith("/")
              && !restSuffix.startsWith("/")
              && !restSuffix.startsWith("?")) {
            url = address + "/" + restSuffix;
          } else if (address.endsWith("/") && restSuffix.startsWith("/")) {
            url = address + restSuffix.substring(1);
          } else if (address.endsWith("/") && restSuffix.startsWith("?")) {
            url = address.substring(0, address.length() - 1) + restSuffix;
          } else {
            url = address + restSuffix;
          }
          axisOutMsgCtx.setTo(new EndpointReference(url));

        } else {
          axisOutMsgCtx.setTo(new EndpointReference(address));
        }
        axisOutMsgCtx.setProperty(NhttpConstants.ENDPOINT_PREFIX, address);
        synapseOutMessageContext.setProperty(SynapseConstants.ENDPOINT_PREFIX, address);
      } else {
        // Supporting RESTful invocation
        if (isRest && restSuffix != null && !"".equals(restSuffix)) {
          EndpointReference epr = axisOutMsgCtx.getTo();
          if (epr != null) {
            String address = epr.getAddress();
            String url;
            if (!address.endsWith("/")
                && !restSuffix.startsWith("/")
                && !restSuffix.startsWith("?")) {
              url = address + "/" + restSuffix;
            } else {
              url = address + restSuffix;
            }
            axisOutMsgCtx.setTo(new EndpointReference(url));
          }
        }
      }

      if (endpoint.isUseSeparateListener()) {
        axisOutMsgCtx.getOptions().setUseSeparateListener(true);
      }
    } else {
      processWSDL2RESTRequestMessageType(originalInMsgCtx, axisOutMsgCtx);
    }

    // only put whttp:location for the REST (GET) requests, otherwise causes issues for POX messages
    if (axisOutMsgCtx.isDoingREST()
        && HTTPConstants.MEDIA_TYPE_X_WWW_FORM.equals(
            axisOutMsgCtx.getProperty(Constants.Configuration.MESSAGE_TYPE))) {
      if (axisOutMsgCtx.getProperty(WSDL2Constants.ATTR_WHTTP_LOCATION) == null
          && axisOutMsgCtx.getEnvelope().getBody().getFirstElement() != null) {
        axisOutMsgCtx.setProperty(
            WSDL2Constants.ATTR_WHTTP_LOCATION,
            axisOutMsgCtx.getEnvelope().getBody().getFirstElement().getQName().getLocalPart());
      }
    }

    if (wsAddressingEnabled) {

      if (wsAddressingVersion != null
          && SynapseConstants.ADDRESSING_VERSION_SUBMISSION.equals(wsAddressingVersion)) {

        axisOutMsgCtx.setProperty(
            AddressingConstants.WS_ADDRESSING_VERSION,
            AddressingConstants.Submission.WSA_NAMESPACE);

      } else if (wsAddressingVersion != null
          && SynapseConstants.ADDRESSING_VERSION_FINAL.equals(wsAddressingVersion)) {

        axisOutMsgCtx.setProperty(
            AddressingConstants.WS_ADDRESSING_VERSION, AddressingConstants.Final.WSA_NAMESPACE);
      }

      axisOutMsgCtx.setProperty(
          AddressingConstants.DISABLE_ADDRESSING_FOR_OUT_MESSAGES, Boolean.FALSE);
    } else {
      axisOutMsgCtx.setProperty(
          AddressingConstants.DISABLE_ADDRESSING_FOR_OUT_MESSAGES, Boolean.TRUE);
    }

    // remove the headers if we don't need to preserve them.
    // determine weather we need to preserve the processed headers
    String preserveHeaderProperty =
        (String) synapseOutMessageContext.getProperty(SynapseConstants.PRESERVE_PROCESSED_HEADERS);
    if (preserveHeaderProperty == null || !Boolean.parseBoolean(preserveHeaderProperty)) {
      // default behaviour is to remove the headers
      MessageHelper.removeProcessedHeaders(
          axisOutMsgCtx,
          (preserveAddressingProperty != null && Boolean.parseBoolean(preserveAddressingProperty)));
    }

    ConfigurationContext axisCfgCtx = axisOutMsgCtx.getConfigurationContext();
    AxisConfiguration axisCfg = axisCfgCtx.getAxisConfiguration();

    AxisService anoymousService =
        AnonymousServiceFactory.getAnonymousService(
            synapseOutMessageContext.getConfiguration(),
            axisCfg,
            wsAddressingEnabled,
            wsRMEnabled,
            wsSecurityEnabled);
    // mark the anon services created to be used in the client side of synapse as hidden
    // from the server side of synapse point of view
    anoymousService.getParent().addParameter(SynapseConstants.HIDDEN_SERVICE_PARAM, "true");
    ServiceGroupContext sgc =
        new ServiceGroupContext(axisCfgCtx, (AxisServiceGroup) anoymousService.getParent());
    ServiceContext serviceCtx = sgc.getServiceContext(anoymousService);

    boolean outOnlyMessage =
        "true".equals(synapseOutMessageContext.getProperty(SynapseConstants.OUT_ONLY));

    // get a reference to the DYNAMIC operation of the Anonymous Axis2 service
    AxisOperation axisAnonymousOperation =
        anoymousService.getOperation(
            outOnlyMessage
                ? new QName(AnonymousServiceFactory.OUT_ONLY_OPERATION)
                : new QName(AnonymousServiceFactory.OUT_IN_OPERATION));

    Options clientOptions = MessageHelper.cloneOptions(originalInMsgCtx.getOptions());
    clientOptions.setUseSeparateListener(separateListener);
    // if RM is requested,
    if (wsRMEnabled) {
      // if a WS-RM policy is specified, use it
      if (wsRMPolicyKey != null) {
        Object property = synapseOutMessageContext.getEntry(wsRMPolicyKey);
        if (property instanceof OMElement) {
          OMElement policyOMElement = (OMElement) property;
          RMAssertionBuilder builder = new RMAssertionBuilder();
          SandeshaPolicyBean sandeshaPolicyBean =
              (SandeshaPolicyBean) builder.build(policyOMElement, null);
          Parameter policyParam =
              new Parameter(Sandesha2Constants.SANDESHA_PROPERTY_BEAN, sandeshaPolicyBean);
          anoymousService.addParameter(policyParam);
        }
      }
    }

    // if security is enabled,
    if (wsSecurityEnabled) {
      // if a WS-Sec policy is specified, use it
      if (wsSecPolicyKey != null) {
        clientOptions.setProperty(
            SynapseConstants.RAMPART_POLICY,
            MessageHelper.getPolicy(synapseOutMessageContext, wsSecPolicyKey));
      } else {
        if (inboundWsSecPolicyKey != null) {
          clientOptions.setProperty(
              SynapseConstants.RAMPART_IN_POLICY,
              MessageHelper.getPolicy(synapseOutMessageContext, inboundWsSecPolicyKey));
        }
        if (outboundWsSecPolicyKey != null) {
          clientOptions.setProperty(
              SynapseConstants.RAMPART_OUT_POLICY,
              MessageHelper.getPolicy(synapseOutMessageContext, outboundWsSecPolicyKey));
        }
      }
      // temporary workaround for https://issues.apache.org/jira/browse/WSCOMMONS-197
      if (axisOutMsgCtx.getEnvelope().getHeader() == null) {
        SOAPFactory fac =
            axisOutMsgCtx.isSOAP11()
                ? OMAbstractFactory.getSOAP11Factory()
                : OMAbstractFactory.getSOAP12Factory();
        fac.createSOAPHeader(axisOutMsgCtx.getEnvelope());
      }
    }

    OperationClient mepClient = axisAnonymousOperation.createClient(serviceCtx, clientOptions);
    mepClient.addMessageContext(axisOutMsgCtx);
    axisOutMsgCtx.setAxisMessage(
        axisAnonymousOperation.getMessage(WSDLConstants.MESSAGE_LABEL_OUT_VALUE));

    // set the SEND_TIMEOUT for transport sender
    if (endpoint != null && endpoint.getTimeoutDuration() > 0) {
      axisOutMsgCtx.setProperty(SynapseConstants.SEND_TIMEOUT, endpoint.getTimeoutDuration());
    }

    // always set a callback as we decide if the send it blocking or non blocking within
    // the MEP client. This does not cause an overhead, as we simply create a 'holder'
    // object with a reference to the outgoing synapse message context
    // synapseOutMessageContext
    AsyncCallback callback = new AsyncCallback(axisOutMsgCtx, synapseOutMessageContext);
    if (!outOnlyMessage) {
      if (endpoint != null) {
        // set the timeout time and the timeout action to the callback, so that the
        // TimeoutHandler can detect timed out callbacks and take approprite action.
        callback.setTimeOutOn(System.currentTimeMillis() + endpoint.getTimeoutDuration());
        callback.setTimeOutAction(endpoint.getTimeoutAction());
      } else {
        callback.setTimeOutOn(System.currentTimeMillis());
      }
    }
    mepClient.setCallback(callback);
    //
    //        if (Utils.isClientThreadNonBlockingPropertySet(axisOutMsgCtx)) {
    //            SynapseCallbackReceiver synapseCallbackReceiver = (SynapseCallbackReceiver)
    // axisOutMsgCtx.getAxisOperation().getMessageReceiver();
    //            synapseCallbackReceiver.addCallback(axisOutMsgCtx.getMessageID(), new
    // FaultCallback(axisOutMsgCtx, synapseOutMessageContext));
    //        }

    // this is a temporary fix for converting messages from HTTP 1.1 chunking to HTTP 1.0.
    // Without this HTTP transport can block & become unresponsive because we are streaming
    // HTTP 1.1 messages and HTTP 1.0 require the whole message to caculate the content length
    if (originalInMsgCtx.isPropertyTrue(NhttpConstants.FORCE_HTTP_1_0)) {
      synapseOutMessageContext.getEnvelope().toString();
    }

    // with the nio transport, this causes the listener not to write a 202
    // Accepted response, as this implies that Synapse does not yet know if
    // a 202 or 200 response would be written back.
    originalInMsgCtx
        .getOperationContext()
        .setProperty(org.apache.axis2.Constants.RESPONSE_WRITTEN, "SKIP");

    // if the transport out is explicitly set use it
    Object o = originalInMsgCtx.getProperty("TRANSPORT_OUT_DESCRIPTION");
    if (o != null && o instanceof TransportOutDescription) {
      axisOutMsgCtx.setTransportOut((TransportOutDescription) o);
      clientOptions.setTransportOut((TransportOutDescription) o);
      clientOptions.setProperty("TRANSPORT_OUT_DESCRIPTION", o);
    }

    mepClient.execute(true);
    if (wsRMEnabled) {
      Object rm11 = clientOptions.getProperty(SandeshaClientConstants.RM_SPEC_VERSION);
      if ((rm11 != null) && rm11.equals(Sandesha2Constants.SPEC_VERSIONS.v1_1)) {
        ServiceClient serviceClient =
            new ServiceClient(
                axisOutMsgCtx.getConfigurationContext(), axisOutMsgCtx.getAxisService());
        serviceClient.setTargetEPR(
            new EndpointReference(endpoint.getAddress(synapseOutMessageContext)));
        serviceClient.setOptions(clientOptions);
        serviceClient
            .getOptions()
            .setTo(new EndpointReference(endpoint.getAddress(synapseOutMessageContext)));
        SandeshaClient.terminateSequence(serviceClient);
      }
    }
  }
  /**
   * Send request in non-blocking manner
   *
   * @param synInCtx message context
   * @return continue the mediation flow or not
   */
  private boolean handleNonBlockingCall(MessageContext synInCtx) {
    SynapseLog synLog = getLog(synInCtx);

    if (synLog.isTraceOrDebugEnabled()) {
      synLog.traceOrDebug("Start : Call mediator - Non Blocking Call");
      if (synLog.isTraceTraceEnabled()) {
        synLog.traceTrace("Message : " + synInCtx.getEnvelope());
      }
    }

    // clear the message context properties related to endpoint in last service invocation
    Set keySet = synInCtx.getPropertyKeySet();
    if (keySet != null) {
      keySet.remove(SynapseConstants.RECEIVING_SEQUENCE);
      keySet.remove(EndpointDefinition.DYNAMIC_URL_VALUE);
    }

    boolean outOnlyMessage = "true".equals(synInCtx.getProperty(SynapseConstants.OUT_ONLY));

    // Prepare the outgoing message context
    MessageContext synOutCtx = null;
    if (outOnlyMessage) {
      try {
        synOutCtx = MessageHelper.cloneMessageContext(synInCtx);
      } catch (AxisFault axisFault) {
        handleException("Error occurred while cloning msg context", axisFault, synInCtx);
      }
    } else {
      synOutCtx = synInCtx;
    }

    synOutCtx.setProperty(SynapseConstants.CONTINUATION_CALL, true);
    ContinuationStackManager.updateSeqContinuationState(synOutCtx, getMediatorPosition());

    // If no endpoints are defined, send where implicitly stated
    if (endpoint == null) {

      if (synLog.isTraceOrDebugEnabled()) {
        StringBuffer sb = new StringBuffer();
        sb.append("Calling ")
            .append(synOutCtx.isResponse() ? "response" : "request")
            .append(" message using implicit message properties..");
        sb.append("\nCalling To: ")
            .append(synOutCtx.getTo() != null ? synOutCtx.getTo().getAddress() : "null");
        sb.append("\nSOAPAction: ")
            .append(synOutCtx.getWSAAction() != null ? synOutCtx.getWSAAction() : "null");
        synLog.traceOrDebug(sb.toString());
      }

      if (synLog.isTraceTraceEnabled()) {
        synLog.traceTrace("Envelope : " + synOutCtx.getEnvelope());
      }
      synOutCtx.getEnvironment().send(null, synOutCtx);

    } else {
      endpoint.send(synOutCtx);
    }

    if (synLog.isTraceOrDebugEnabled()) {
      synLog.traceOrDebug("End : Call mediator - Non Blocking Call");
    }

    if (outOnlyMessage) {
      // For out only invocations request flow should continue
      // otherwise flow should stop from here
      return true;
    }
    return false;
  }