I want to implement a use case where two responder flows (different classes) are initiated by the same parent flow.
I get the following exception:
java.lang.IllegalArgumentException: com.flow.initialFlows.InitialFlow has been specified as the initiating flow by both com.flow.responder.Responder1 and com.flow.responder2.Responder2
in How can I test two different responder flows in the same CorDapp? the suggestion was to use setCordappPackages(). this method is used in test scenarios and is part of the corda test package. what can you use outside test scenarios?
A single node cannot have two responder flows registered for the same initiating flow.
This is by design. Otherwise, the responding node know which of the two flows to invoke.
Related
If I have 3 participants and I need to make sure that the contract can only be initiated by, say PartyA. Should I be including this participant as a variable in the respective flow? Because anyhow we'll be initiating the flow from that participant's node right!?
You can hardcode the value inside the Initiator flow:
if (getOurIdentity().equals(CordaX500Name.parse("O=Initiator,L=London,C=GB"))) {
}
But the above step is not enough, the resopnders to your flow don't know (and don't trust) whether you made sure that the initiator is a certain entity or not. So, inside the Responder you must also check the initiator:
if (otherPartySession.getCounterparty()
.equals(CordaX500Name.parse("O=Initiator,L=London,C=GB"))) {
}
Btw, a better option than hardcoding the value, would be to use CorDapp configuration files; read about it in my article here.
On a side note, remember that it's the responsibility of the responding node to implement (i.e. write) a responder flow; just because you gave some node your CorDapp (so they can run the responder), doesn't mean they'll use it; they can create their own version of the responder flow (read here). That's why the check must happen in both Initiator and Responder flows.
I would like to have more than one version of certain flow pairs (both the InitiatingFlow and InitiatedBy) in a node's cordapps directory.
The reason for maintaining several copies of certain flow pairs is that some of the nodes may be using a previous version of the flow because they have yet to migrate the version of the flow.
As the flow's version is only in the annotation, I suspect there would be more than one class with the same fully-qualified name. This would result in a runtime error.
Can you provide an example of flow pairs with different versions that can remain in the same cordapps folder?
The correct approach here is not to define several flows pairs, but to use the flow version number in the InitiatingFlow to control how the corresponding InitiatedBy flow behaves.
For example, suppose we have an InitiatingFlow that:
Sends an Int in version 1
Sends a String in subsequent versions
The corresponding InitiatedBy flow may look like this:
#Suspendable
override fun call() {
val otherFlowVersion = otherSession.getCounterpartyFlowInfo().flowVersion
val receivedString = if (otherFlowVersion == 1) {
otherSession.receive<Int>().unwrap { it.toString() }
} else {
otherSession.receive<String>().unwrap { it }
}
}
By using the InitiatingFlow's version number, the InitiatedBy flow is able to communicate with parties running any version of the InitiatingFlow.
Note that there is no equivalent version number for the InitiatedBy flow, which means that the InitiatingFlow cannot condition its behaviour on the version of the InitiatedBy flow. The InitiatedBy flow is the side that must adapt to handle changes in the InitiatingFlow, and not vice-versa.
Additional information on flow versioning can be found here.
Corda has fairly limited versioning model for flows. For example, there is no way for the initiating flow to adapt its behaviour to work with an older version of the responding flow.
The way this could be worked around is through Protocol Handshake pattern. It works like the following. Implement a pair of subflows, say, InitiatorProtocolHandshakeFlow and RespondToProtocolHandshakeFlow. Make every initiating flow in the CorDapp that establishes a new flow session with another note to invoke InitiatorProtocolHandshakeFlow with the counterparty session, and make every responding flow to invoke RespondToProtocolHandshakeFlow with the counterparty session before sending or receiving anything else. Make the flows to negotiate relevant 'protocol features'. This could be implemented in a number of way, of which the simplest one to make the responder to send (and initiator to receive) a simple version number. Unlike flow version number in the annotation, the initiating flow can actually alter its behaviour based on the number provided by the responding flow.
I saw a tutorial video explain the chain of responsibility design pattern, and I think I understand how it works but I'm not sure when I would really use it. What are some common usages of the chain of responsibility?
From the GoF:
Known Uses
Several class libraries use the Chain of Responsibility
pattern to handle user events. They use different names for the
Handler class, but the idea is the same: When the user clicks the
mouse or presses a key, an event gets generated and passed along the
chain. MacApp [App89] and ET++ [WGM88] call it "EventHandler,"
Symantec's TCL library [Sym93b] calls it "Bureaucrat," and NeXT's
AppKit [Add94] uses the name "Responder."
The Unidraw framework for graphical editors defines Command objects
that encapsulate requests to Component and ComponentView objects
[VL90]. Commands are requests in the sense that a component or
component view may interpret a command to perform an operation. This
corresponds to the "requests as objects" approach described in
Implementation. Components and component views may be structured
hierarchically. A component or a component view may forward command
interpretation to its parent, which may in turn forward it to its
parent, and so on, thereby forming a chain of responsibility.
ET++ uses Chain of Responsibility to handle graphical update. A
graphical object calls the InvalidateRect operation whenever it must
update a part of its appearance. A graphical object can't handle
InvalidateRect by itself, because it doesn't know enough about its
context. For example, a graphical object can be enclosed in objects
like Scrollers or Zoomers that transform its coordinate system. That
means the object might be scrolled or zoomed so that it's partially
out of view. Therefore the default implementation of InvalidateRect
forwards the request to the enclosing container object. The last
object in the forwarding chain is a Window instance. By the time
Window receives the request, the invalidation rectangle is guaranteed
to be transformed properly. The Window handles InvalidateRect by
notifying the window system interface and requesting an update.
I have an orchestration called MyUsefulOrch, hosted in an application MySharedApp.
MyUsefulOrch has an inbound messagebox-direct-bound port to receive requests, and after doing some useful work, an outbound messagebox-direct-bound port to send a message to the caller.
Now, I have another orchestration called MyCallerOrch which wants to benefit from the useful processing provided by MyUsefulOrch. However, MyCallerOrch is hosted in a different application, MyCallingApp.
I do not want to have any references to the assembly which contains MyUsefulOrch from MyCallerOrch.
My problem now is making sure I can send a message to MyUsefulOrch from MyCallerOrch and receive a response from it.
Ahah! Correlation should do the trick! But how do I go about getting correlation to work in this scenario?
For example:
Would I put a correlation id in a property schema and stuff a guid into the message context under this property from MyCallerOrch just before sending it to the messagebox?
How do I ensure that MyCallerOrch receives only the responses it needs to receive from MyUsefulOrch?
Do I need to put the correlation id value into the message body of the messages which are sent between the two orchestrations?
I would greatly appreciate any help, ideally as descriptive as possible, about how to acheive this.
Many thanks in advance.
If you use a two-way, request/response send port in the caller orchestration to send messages to the useful orchestration, then you can use correlation to route the relevant messages back to the userful orch from the caller.
The trick is that you will need to modify the useful orch (to make it more useful, of course).
If you do not/cannot control whether or not callers to the userful orch are expecting a response back, then you would need to make the inbound (request) port a one-way port. The orchestration would then complete by sending to a one-way outbound (response) port.
To ensure that messages received from two-way/request-response callers are routed back properly, the construct shape of the outbound message inside your useful orch will need to set the following message properties to true using a message assignment shape:
BTS.RouteDirectToTP
BTS.IsRequestResponse
Before setting those two properties, though, also make sure to do something like msgOut(*) f= msgIn(*); in the same message assignment shape to ensure that other properties get copied over. If the inbound and outbound messages are not the same, then you have to manually set each of the required properties, one at a time.
Those properties, of course, in addition to the two above, are what help ensure that the result of the useful orch is properly routed to the caller. They should be inside your correlation set and are:
BTS.CorrelationToken
BTS.EpmRRCorrelationToken
BTS.IsRequestResponse
BTS.ReqRespTransmitPipelineID
BTS.RouteDirectToTP
I'm getting a bit ahead of myself, however, as you assign the correlation set to the outbound send shape only if BTS.EpmRRCorrelationToken exists msgIn. This is critical. I have used a decision shape in an orchcestration, with the decision based upon that exact phrase. If the result is true, then send the previously constructed message out and assign the correlation set from above as the Initializing correlation set. This will cause BizTalk to route the message back to the caller as its expected response.
If the result of the decision was false then the caller of the useful orchestration was one-way. You will still likely want to send out a result (and just have someone else subscribe to it). You can even use the same send port as for two-way responses, just do not assign the correlation set.
You will want to thoroughly test this, of course. It does work for me in the one scenario in which I have used it, but that doesn't absolve others from doing their due diligence.
I think you are pretty much on the right track
Since the 2 applications are going to send messages to eachother, if you use strongly typed schemas, both apps will need to know about the schemas.
In this case recommend that you separate the common schemas off into a separate assembly, and reference this from both your orchestration apps.
(Schemas registered on the Server must have unique XMLNS#ROOTs, even across multiple applications)
However, if you really can't stand even a shared schema assembly reference, you might need to resort to untyped messages.
Richard Seroter has an example here
His article also explains a technique for auto stamping a correlation GUID on the context properties.
Edit : Good point. It is possible to promote custom context properties on the message without a Pipeline - see the tricks here and here - this would suffice to send the context property to MyUsefulOrch and similarly, the Custom context could be promoted on the return message from within MyUsefulOrch (since MyUsefulOrch doesn't need any correlation). However I can't think how, on the return to MyCallingOrch that the custom context property can be used to continue the "following correlation", unless you add a new correlating property into the return message.
We have a parent orchestration where we call a child orchestration.
However, once the child orchestration has completed, we would like to return a message to the parent orchestration.
What is the best / most standard way to do this?
A) Just publish the message from the child orchestration to the messagebox and correlate this in the parent with a receive
B) Can we use a message as a C# style ref / out parameter when passing it from the Parent to Child orchestration?
Other?
Thanks
Stuart
You can go either way...
B is the Easiest solution. You use a return parameter with the "Call Shape." Two major cons of this way is that you will be processing Synchronously. So if these two orchestrations aren't related, or are in separate business processes's you will have a lot of orchestrations waiting. Second is that you are coupling the parent and child. So you are creating a dependency between parent and child. Anytime you need to stop the parent, you will have to stop the child.
If your situation doesn't meet the above you might want to be decoupled and perform Asynchronously go for the Start shape or messagebox directbound ports. MessageBox direct bound ports is the only true decoupled scenario and is the most scalable.