/** * 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; }
/** * 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; }
/** * Aggregate messages flowing through this mediator according to the correlation criteria and the * aggregation algorithm specified to it * * @param synCtx - MessageContext to be mediated and aggregated * @return boolean true if the complete condition for the particular aggregate is validated */ public boolean mediate(MessageContext synCtx) { if (synCtx.getEnvironment().isDebugEnabled()) { if (super.divertMediationRoute(synCtx)) { return true; } } SynapseLog synLog = getLog(synCtx); if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug("Start : Aggregate mediator"); if (synLog.isTraceTraceEnabled()) { synLog.traceTrace("Message : " + synCtx.getEnvelope()); } } try { Aggregate aggregate = null; String correlationIdName = (id != null ? EIPConstants.AGGREGATE_CORRELATION + "." + id : EIPConstants.AGGREGATE_CORRELATION); // if a correlateExpression is provided and there is a coresponding // element in the current message prepare to correlate the messages on that Object result = null; if (correlateExpression != null) { result = correlateExpression.evaluate(synCtx); if (result instanceof List) { if (((List) result).isEmpty()) { handleException( "Failed to evaluate correlate expression: " + correlateExpression.toString(), synCtx); } } } if (result != null) { while (aggregate == null) { synchronized (lock) { if (activeAggregates.containsKey(correlateExpression.toString())) { aggregate = activeAggregates.get(correlateExpression.toString()); if (aggregate != null) { if (!aggregate.getLock()) { aggregate = null; } } } else { if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug( "Creating new Aggregator - " + (completionTimeoutMillis > 0 ? "expires in : " + (completionTimeoutMillis / 1000) + "secs" : "without expiry time")); } Double minMsg = Double.parseDouble(minMessagesToComplete.evaluateValue(synCtx)); Double maxMsg = Double.parseDouble(maxMessagesToComplete.evaluateValue(synCtx)); aggregate = new Aggregate( synCtx.getEnvironment(), correlateExpression.toString(), completionTimeoutMillis, minMsg.intValue(), maxMsg.intValue(), this); if (completionTimeoutMillis > 0) { synCtx .getConfiguration() .getSynapseTimer() .schedule(aggregate, completionTimeoutMillis); } aggregate.getLock(); activeAggregates.put(correlateExpression.toString(), aggregate); } } } } else if (synCtx.getProperty(correlationIdName) != null) { // if the correlattion cannot be found using the correlateExpression then // try the default which is through the AGGREGATE_CORRELATION message property // which is the unique original message id of a split or iterate operation and // which thus can be used to uniquely group messages into aggregates Object o = synCtx.getProperty(correlationIdName); String correlation; if (o != null && o instanceof String) { correlation = (String) o; while (aggregate == null) { synchronized (lock) { if (activeAggregates.containsKey(correlation)) { aggregate = activeAggregates.get(correlation); if (aggregate != null) { if (!aggregate.getLock()) { aggregate = null; } } else { break; } } else { if (synLog.isTraceOrDebugEnabled()) { synLog.traceOrDebug( "Creating new Aggregator - " + (completionTimeoutMillis > 0 ? "expires in : " + (completionTimeoutMillis / 1000) + "secs" : "without expiry time")); } Double minMsg = -1.0; if (minMessagesToComplete != null) { minMsg = Double.parseDouble(minMessagesToComplete.evaluateValue(synCtx)); } Double maxMsg = -1.0; if (maxMessagesToComplete != null) { maxMsg = Double.parseDouble(maxMessagesToComplete.evaluateValue(synCtx)); } aggregate = new Aggregate( synCtx.getEnvironment(), correlation, completionTimeoutMillis, minMsg.intValue(), maxMsg.intValue(), this); if (completionTimeoutMillis > 0) { synchronized (aggregate) { if (!aggregate.isCompleted()) { synCtx .getConfiguration() .getSynapseTimer() .schedule(aggregate, completionTimeoutMillis); } } } aggregate.getLock(); activeAggregates.put(correlation, aggregate); } } } } else { synLog.traceOrDebug("Unable to find aggrgation correlation property"); return true; } } else { synLog.traceOrDebug("Unable to find aggrgation correlation XPath or property"); return true; } // if there is an aggregate continue on aggregation if (aggregate != null) { // this is a temporary fix synCtx.getEnvelope().build(); boolean collected = aggregate.addMessage(synCtx); if (synLog.isTraceOrDebugEnabled()) { if (collected) { synLog.traceOrDebug("Collected a message during aggregation"); if (synLog.isTraceTraceEnabled()) { synLog.traceTrace("Collected message : " + synCtx); } } } // check the completeness of the aggregate and if completed aggregate the messages // if not completed return false and block the message sequence till it completes if (aggregate.isComplete(synLog)) { synLog.traceOrDebug("Aggregation completed - invoking onComplete"); boolean onCompleteSeqResult = completeAggregate(aggregate); synLog.traceOrDebug("End : Aggregate mediator"); isAggregateComplete = onCompleteSeqResult; return onCompleteSeqResult; } else { aggregate.releaseLock(); } } else { // if the aggregation correlation cannot be found then continue the message on the // normal path by returning true synLog.traceOrDebug("Unable to find an aggregate for this message - skip"); return true; } } catch (JaxenException e) { handleException("Unable to execute the XPATH over the message", e, synCtx); } synLog.traceOrDebug("End : Aggregate mediator"); // When Aggregation is not completed return false to hold the flow return false; }