/** * It is possible for us (Synapse) to cause the creation of a duplicate relatesTo as we try to * hold onto the outgoing message ID even for POX messages using the relates to Now once we get a * response, make sure we remove any trace of this before we proceed any further * * @param mc the message context from which a possibly duplicated relatesTo should be removed * @param relates the existing relatedTo array of the message */ private void removeDuplicateRelatesTo(MessageContext mc, RelatesTo[] relates) { int insertPos = 0; RelatesTo[] newRelates = new RelatesTo[relates.length]; for (RelatesTo current : relates) { boolean found = false; for (int j = 0; j < newRelates.length && j < insertPos; j++) { if (newRelates[j].equals(current) || newRelates[j].getValue().equals(current.getValue())) { found = true; break; } } if (!found) { newRelates[insertPos++] = current; } } RelatesTo[] trimmedRelates = new RelatesTo[insertPos]; System.arraycopy(newRelates, 0, trimmedRelates, 0, insertPos); mc.setRelationships(trimmedRelates); }
/** * Everytime a response message is received this method gets invoked. It will then select the * outgoing *Synapse* message context for the reply we received, and determine what action to take * at the Synapse level * * @param messageCtx the Axis2 message context of the reply received * @throws AxisFault */ public void receive(MessageContext messageCtx) throws AxisFault { String messageID = null; /** * In an Out-only scenario if the client receives a HTTP 202 accepted we need to remove the call * back/s registered for that request. This if will check weather this is a message sent in a * that scenario and remove the callback */ if (messageCtx.getProperty(NhttpConstants.HTTP_202_RECEIVED) != null && "true".equals(messageCtx.getProperty(NhttpConstants.HTTP_202_RECEIVED))) { if (callbackStore.containsKey(messageCtx.getMessageID())) { callbackStore.remove(messageCtx.getMessageID()); if (log.isDebugEnabled()) { log.debug( "CallBack registered with Message id : " + messageCtx.getMessageID() + " removed from the " + "callback store since we got an accepted Notification"); } } return; } if (messageCtx.getOptions() != null && messageCtx.getOptions().getRelatesTo() != null) { // never take a chance with a NPE at this stage.. so check at each level :-) Options options = messageCtx.getOptions(); if (options != null) { RelatesTo relatesTo = options.getRelatesTo(); if (relatesTo != null) { messageID = relatesTo.getValue(); } } } else if (messageCtx.getProperty(SandeshaClientConstants.SEQUENCE_KEY) == null) { messageID = (String) messageCtx.getProperty(SynapseConstants.RELATES_TO_FOR_POX); } if (messageID != null) { AsyncCallback callback = (AsyncCallback) callbackStore.remove(messageID); if (log.isDebugEnabled()) { log.debug( "Callback removed for request message id : " + messageID + ". Pending callbacks count : " + callbackStore.size()); } RelatesTo[] relates = messageCtx.getRelationships(); if (relates != null && relates.length > 1) { // we set a relates to to the response message so that if WSA is not used, we // could still link back to the original message. But if WSA was used, this // gets duplicated, and we should remove it removeDuplicateRelatesTo(messageCtx, relates); } if (callback != null) { handleMessage( messageID, messageCtx, ((AsyncCallback) callback).getSynapseOutMsgCtx(), (AsyncCallback) callback); } else { // TODO invoke a generic synapse error handler for this message log.warn( "Synapse received a response for the request with message Id : " + messageID + " But a callback is not registered (anymore) to process this response"); } } else if (!messageCtx.isPropertyTrue(NhttpConstants.SC_ACCEPTED)) { // TODO invoke a generic synapse error handler for this message log.warn("Synapse received a response message without a message Id"); } }
private void send(MessageContext msgctx) throws AxisFault { // create the responseMessageContext and set that its related to the current outgoing // message, so that it could be tied back to the original request even if the response // envelope does not contain addressing headers MessageContext responseMessageContext = new MessageContext(); responseMessageContext.setMessageID(msgctx.getMessageID()); responseMessageContext.setProperty( SynapseConstants.RELATES_TO_FOR_POX, msgctx.getMessageID()); responseMessageContext.setOptions(options); responseMessageContext.setServerSide(true); addMessageContext(responseMessageContext); responseMessageContext.setProperty("synapse.send", "true"); AxisEngine.send(msgctx); // did the engine receive a immediate synchronous response? // e.g. sometimes the transport sender may listen for a syncronous reply if (msgctx.getProperty(MessageContext.TRANSPORT_IN) != null) { responseMessageContext.setOperationContext(msgctx.getOperationContext()); responseMessageContext.setAxisMessage( msgctx .getOperationContext() .getAxisOperation() .getMessage(WSDLConstants.MESSAGE_LABEL_IN_VALUE)); responseMessageContext.setAxisService(msgctx.getAxisService()); responseMessageContext.setProperty( MessageContext.TRANSPORT_OUT, msgctx.getProperty(MessageContext.TRANSPORT_OUT)); responseMessageContext.setProperty( org.apache.axis2.Constants.OUT_TRANSPORT_INFO, msgctx.getProperty(org.apache.axis2.Constants.OUT_TRANSPORT_INFO)); responseMessageContext.setProperty( org.apache.synapse.SynapseConstants.ISRESPONSE_PROPERTY, Boolean.TRUE); responseMessageContext.setTransportIn(msgctx.getTransportIn()); responseMessageContext.setTransportOut(msgctx.getTransportOut()); // If request is REST assume that the responseMessageContext is REST too responseMessageContext.setDoingREST(msgctx.isDoingREST()); responseMessageContext.setProperty( MessageContext.TRANSPORT_IN, msgctx.getProperty(MessageContext.TRANSPORT_IN)); responseMessageContext.setTransportIn(msgctx.getTransportIn()); responseMessageContext.setTransportOut(msgctx.getTransportOut()); // Options object reused above so soapAction needs to be removed so // that soapAction+wsa:Action on response don't conflict responseMessageContext.setSoapAction(""); if (responseMessageContext.getEnvelope() == null) { // If request is REST we assume the responseMessageContext is // REST, so set the variable Options options = responseMessageContext.getOptions(); if (options != null) { RelatesTo relatesTo = options.getRelatesTo(); if (relatesTo != null) { relatesTo.setValue(msgctx.getMessageID()); } else { options.addRelatesTo(new RelatesTo(msgctx.getMessageID())); } } SOAPEnvelope resenvelope = TransportUtils.createSOAPMessage(responseMessageContext); if (resenvelope != null) { responseMessageContext.setEnvelope(resenvelope); AxisEngine.receive(responseMessageContext); if (responseMessageContext.getReplyTo() != null) { sc.setTargetEPR(responseMessageContext.getReplyTo()); } complete(msgctx); } else { throw new AxisFault(Messages.getMessage("blockingInvocationExpectsResponse")); } } } }