/* * 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; }
/** * 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; }