I have this code, i want to trigger another node to run specific flow inside on a flow. When Requester Node run the IssuanceFlow, I want some code in that flow when it will trigger the Approver Node to run ApproverIssuanceFlow. And I want to use the output of ApproverIssuanceFlow as an input in the next step in IssuanceFlow.
public class IssuanceFlow {
@InitiatingFlow
@StartableByRPC
public static class IssuanceInitiator extends FlowLogic<SignedTransaction> {
private Amount<Currency> amount;
public IssuanceInitiator(Amount<Currency> amount) {
this.amount = amount;
}
//STEP GENERATOR
private final ProgressTracker.Step GENERATE_TRX = new ProgressTracker.Step("Generating trx.");
private final ProgressTracker.Step VERIFY_TRX = new ProgressTracker.Step("Verify trx.");
private final ProgressTracker.Step SIGN_TRX = new ProgressTracker.Step("Sign trx.");
private final ProgressTracker.Step GATHER_SIGN = new ProgressTracker.Step("Collecting other sign.") {
@Override
public ProgressTracker childProgressTracker() {
return CollectSignaturesFlow.Companion.tracker();
}
};
private final ProgressTracker.Step FINALIZE_TRX = new ProgressTracker.Step("Notarize and record.") {
@Override
public ProgressTracker childProgressTracker() {
return FinalityFlow.Companion.tracker();
}
};
public ProgressTracker progressTracker = new ProgressTracker(
GENERATE_TRX,
VERIFY_TRX,
SIGN_TRX,
GATHER_SIGN,
FINALIZE_TRX
);
@Override
public ProgressTracker getProgressTracker() {
return progressTracker;
}
@Suspendable
@Override
public SignedTransaction call() throws FlowException {
//obtain notary
final Party notary =getServiceHub().getNetworkMapCache().getNotaryIdentities().get(0);
progressTracker.setCurrentStep(GENERATE_TRX);
UniqueIdentifier linearID = new UniqueIdentifier();
Date issuanceDate = new Date();
Party approver = getServiceHub().getNetworkMapCache().getPeerByLegalName(CordaX500Name.parse("O=Approver,L=Jakarta,C=ID")); //always choose Central Bank as approver
**// I want to trigger another node to run another flow, and use the output in this flow**
//build output
IssuanceState newIssuance = new IssuanceState(linearID, this.amount, this.getOurIdentity(), approver, issuanceDate);
//build transaction
TransactionBuilder transactionBuilder = new TransactionBuilder(notary)
.addOutputState(newIssuance)
.addCommand(new IssuanceContract.Commands.Issue(), Arrays.asList(getOurIdentity().getOwningKey(), approver.getOwningKey()));
progressTracker.setCurrentStep(VERIFY_TRX);
//verify transaction
transactionBuilder.verify(getServiceHub());
progressTracker.setCurrentStep(SIGN_TRX);
//sign transaction
final SignedTransaction partiallySign = getServiceHub().signInitialTransaction(transactionBuilder);
progressTracker.setCurrentStep(GATHER_SIGN);
//send to counterparty, back with signature
FlowSession otherPartySession = initiateFlow(approver);
final SignedTransaction fullySign = subFlow(new CollectSignaturesFlow(partiallySign,Arrays.asList(otherPartySession)));
progressTracker.setCurrentStep(FINALIZE_TRX);
//notarize, record transaction
final SignedTransaction finalityFlow = subFlow(new FinalityFlow(fullySign, Arrays.asList(otherPartySession)));
return finalityFlow;
}
}
@InitiatedBy(IssuanceInitiator.class)
public static class IssuanceResponder extends FlowLogic<Void> {
private FlowSession otherPartySession;
public IssuanceResponder(FlowSession otherPartySession) {
this.otherPartySession = otherPartySession;
}
@Override
@Suspendable
public Void call() throws FlowException {
SignedTransaction signedTransaction = subFlow(new SignTransactionFlow(otherPartySession) {
@Override
@Suspendable
protected void checkTransaction(@NotNull SignedTransaction stx) throws FlowException {
}
});
//stored to db
subFlow(new ReceiveFinalityFlow(otherPartySession,signedTransaction.getId()));
return null;
}
}
You cannot trigger anything in other nodes, it would be a big breach of security if a party could trigger unexpected behaviors in other parties' nodes. Remember that other nodes are expected to be other companies, competitors, legal entities in general.
What you want to do could be achieved with a simple p2p communication between parties using send
or sendAndReceive
(documentation is here). They allow the initiator flow to send a message to the receiver and the receiver could send back another message. That response could be the input for whatever you need to do next.
Still all this needs to be done anyway inside a session in a Flow, so in a transaction between PartyA - the initiator - and PartyB - the receiver.