Hello Guys! Sorry for not responding for such a long time, I had a lot on my hands lately. Among others I just completed the SEI certification, so I'm armed with new knowledge
I managed to solve the problem using the help you gave me and some additional learning. Here is my solution: I used a publish-subscribe channel and two aggregators. The PS channel sends the Dossier to both the businessRuleChannel and straight to the end of the processing where the second aggregator will store it until the subresults arrive. The chain handling the business rule engine invocation also contains an aggregator, to gather the Applicants into a list. So the second aggregator is only aggregating two object: the Dossier and the List of Applicants. You can see the code below. Please write if you have any suggestions how this implementation could be improved. The important requirement is that the administration around the BRE call should be self-contained so more such steps can be added to the flow easily.
PS. I think that the claim check in/out pattern is really suited for this situation, but I really can't figure out how to use it in practice. I either loose the real Dossier before I would split it into Applicants or I loose the id of the stored dossier. Strangely I also couldn't find a single example of this pattern in practice.
Code:
<beans ...>
<int:publish-subscribe-channel id="testProcessingOperationChannel" datatype="nl.vwpfs.pos.xmlcdm.dossier.Dossier"/>
<int:bridge input-channel="testProcessingOperationChannel" output-channel="businessRuleChannel"/>
<int:bridge input-channel="testProcessingOperationChannel" output-channel="dossierReassemblyChannel"/>
<int:channel id="businessRuleChannel" datatype="nl.vwpfs.pos.xmlcdm.dossier.Dossier"/>
<int:chain input-channel="businessRuleChannel" output-channel="dossierReassemblyChannel">
<int:header-enricher>
<int:header name="DossierID" expression="payload.getUid()"/>
</int:header-enricher>
<int:splitter apply-sequence="true" expression="payload.getApplication().getApplicants().getApplicantList()"/>
<int:service-activator method="checkAgeOfApplicant">
<bean class="nl.vwpfs.pos.esb.BusinessRuleEngine"/>
</int:service-activator>
<int:aggregator/>
</int:chain>
<int:channel id="dossierReassemblyChannel"/>
<int:aggregator
input-channel="dossierReassemblyChannel" output-channel="dossierServiceChannel"
ref="dossierReassembler"
method="processMessageGroup"
correlation-strategy="dossierReassembler"
release-strategy="dossierReassembler">
</int:aggregator>
<int:channel id="dossierServiceChannel" datatype="nl.vwpfs.pos.xmlcdm.dossier.Dossier"/>
<int:service-activator
id="dossierServiceServiceActivator"
input-channel="dossierServiceChannel"
ref="dossierService"
method="update"
output-channel="nullChannel"/>
<context:annotation-config/>
<import resource="beanDefinitionContext.xml"/>
</beans>
And the dossier reassebling aggregator:
Code:
class DossierReassembler extends AbstractAggregatingMessageGroupProcessor implements CorrelationStrategy, ReleaseStrategy {
@Override
Object getCorrelationKey(Message<?> message) {
if (message.getPayload() instanceof Dossier) {
return ((Dossier) message.getPayload()).getUid()
} else {
if (!message.headers["DossierID"]) throw new IllegalArgumentException("DossierID not present in header of message with payload type " + message.payload.class)
return message.headers["DossierID"]
}
}
@Override
boolean canRelease(MessageGroup group) {
//group should contain one list of applicants and one dossier
boolean applicantListArrived = group.marked.find { Message msg -> msg.payload instanceof List<Applicant> } != null
boolean dossierListArrived = group.marked.find { Message msg -> msg.payload instanceof Dossier } != null
return applicantListArrived && dossierListArrived
}
@Override
protected Object aggregatePayloads(MessageGroup group, Map<String, Object> defaultHeaders) {
List<Applicant> applicantList = group.marked.find { Message msg -> msg.payload instanceof List<Applicant> }.payload as List<Applicant>
Dossier dossier = group.marked.find { Message msg -> msg.payload instanceof Dossier }.payload as Dossier
dossier.application.applicants.applicantList.clear()
dossier.application.applicants.applicantList.addAll(applicantList)
return dossier
}
}