@DoNotImplement public class FlowSession
A class FlowSession
is a handle on a communication sequence between two paired flows, possibly running on separate nodes.
It is used to send and receive messages between the flows as well as to query information about the counter-flow.
There are two ways of obtaining such a session:
Calling FlowLogic.initiateFlow
. This will create a class FlowSession
object on which the first send/receive
operation will attempt to kick off a corresponding annotationclass InitiatedBy
flow on the counterparty's node.
As constructor parameter to annotationclass InitiatedBy
flows. This session is the one corresponding to the initiating flow and
may be used for replies.
To port flows using the old Party-based API:
Look for Deprecated usages of send/receive/sendAndReceive/getFlowInfo.
If it's an InitiatingFlow:
Look for the send/receive that kicks off the counter flow. Insert a
val session = initiateFlow(party)
and use this session afterwards for send/receives. For example: send(party, something) will become session.send(something)
If it's an InitiatedBy flow:
Change the constructor to take an otherSideSession: FlowSession instead of a counterparty: Party Then look for usages of the deprecated functions and change them to use the FlowSession For example: send(counterparty, something) will become otherSideSession.send(something)
public FlowSession()
A class FlowSession
is a handle on a communication sequence between two paired flows, possibly running on separate nodes.
It is used to send and receive messages between the flows as well as to query information about the counter-flow.
There are two ways of obtaining such a session:
Calling FlowLogic.initiateFlow
. This will create a class FlowSession
object on which the first send/receive
operation will attempt to kick off a corresponding annotationclass InitiatedBy
flow on the counterparty's node.
As constructor parameter to annotationclass InitiatedBy
flows. This session is the one corresponding to the initiating flow and
may be used for replies.
To port flows using the old Party-based API:
Look for Deprecated usages of send/receive/sendAndReceive/getFlowInfo.
If it's an InitiatingFlow:
Look for the send/receive that kicks off the counter flow. Insert a
val session = initiateFlow(party)
and use this session afterwards for send/receives. For example: send(party, something) will become session.send(something)
If it's an InitiatedBy flow:
Change the constructor to take an otherSideSession: FlowSession instead of a counterparty: Party Then look for usages of the deprecated functions and change them to use the FlowSession For example: send(counterparty, something) will become otherSideSession.send(something)
@NotNull public Destination getDestination()
The interface Destination
on the other side of this session. In the case of a session created by FlowLogic.initiateFlow
this is the same
destination as the one passed to that function.
interface Destination
,
FlowLogic.initiateFlow
@NotNull public Party getCounterparty()
If the destination on the other side of this session is a class Party
then returns that, otherwise throws IllegalStateException.
Only use this method if it's known the other side is a class Party
, otherwise use destination
.
IllegalStateException
- if the other side is not a class Party
.class Party
,
IllegalStateException,
class Party
,
destination
,
destination
@Suspendable @NotNull public FlowInfo getCounterpartyFlowInfo(boolean maySkipCheckpoint)
Returns a class FlowInfo
object describing the flow counterparty
is using. With FlowInfo.flowVersion it
provides the necessary information needed for the evolution of flows and enabling backwards compatibility.
This method can be called before any send or receive has been done with counterparty
. In such a case this will
force them to start their flow.
maySkipCheckpoint
- setting it to true indicates to the platform that it may optimise away the checkpoint.class FlowInfo
,
counterparty
,
counterparty
@Suspendable @NotNull public FlowInfo getCounterpartyFlowInfo()
Returns a class FlowInfo
object describing the flow counterparty
is using. With FlowInfo.flowVersion it
provides the necessary information needed for the evolution of flows and enabling backwards compatibility.
This method can be called before any send or receive has been done with counterparty
. In such a case this will
force them to start their flow.
class FlowInfo
,
counterparty
,
counterparty
@Suspendable @NotNull public <R> UntrustworthyData<R> sendAndReceive(@NotNull java.lang.Class<R> receiveType, @NotNull java.lang.Object payload, boolean maySkipCheckpoint)
Serializes and queues the given payload
object for sending to the counterparty
. Suspends until a response
is received, which must be of the given receiveType
. Remember that when receiving data from other parties the
data should not be trusted until it's been thoroughly verified for consistency and that all expectations are
satisfied, as a malicious peer may send you subtly corrupted data in order to exploit your code.
Note that this function is not just a simple send+receive pair: it is more efficient and more correct to
use this when you expect to do a message swap than do use send
and then receive in turn.
maySkipCheckpoint
- setting it to true indicates to the platform that it may optimise away the checkpoint.class UntrustworthyData
wrapper around the received object.payload
,
counterparty
,
receiveType
,
send
@Suspendable @NotNull public <R> UntrustworthyData<R> sendAndReceive(@NotNull java.lang.Class<R> receiveType, @NotNull java.lang.Object payload)
Serializes and queues the given payload
object for sending to the counterparty
. Suspends until a response
is received, which must be of the given receiveType
. Remember that when receiving data from other parties the
data should not be trusted until it's been thoroughly verified for consistency and that all expectations are
satisfied, as a malicious peer may send you subtly corrupted data in order to exploit your code.
Note that this function is not just a simple send+receive pair: it is more efficient and more correct to
use this when you expect to do a message swap than do use send
and then receive in turn.
class UntrustworthyData
wrapper around the received object.payload
,
counterparty
,
receiveType
,
send
@Suspendable @NotNull public <R> UntrustworthyData<R> receive(@NotNull java.lang.Class<R> receiveType, boolean maySkipCheckpoint)
Suspends until counterparty
sends us a message of type receiveType
.
Remember that when receiving data from other parties the data should not be trusted until it's been thoroughly verified for consistency and that all expectations are satisfied, as a malicious peer may send you subtly corrupted data in order to exploit your code.
maySkipCheckpoint
- setting it to true indicates to the platform that it may optimise away the checkpoint.class UntrustworthyData
wrapper around the received object.counterparty
,
receiveType
@Suspendable @NotNull public <R> UntrustworthyData<R> receive(@NotNull java.lang.Class<R> receiveType)
Suspends until counterparty
sends us a message of type receiveType
.
Remember that when receiving data from other parties the data should not be trusted until it's been thoroughly verified for consistency and that all expectations are satisfied, as a malicious peer may send you subtly corrupted data in order to exploit your code.
class UntrustworthyData
wrapper around the received object.counterparty
,
receiveType
@Suspendable public void send(@NotNull java.lang.Object payload, boolean maySkipCheckpoint)
Queues the given payload
for sending to the counterparty
and continues without suspending.
Note that the other party may receive the message at some arbitrary later point or not at all: if counterparty
is offline then message delivery will be retried until it comes back or until the message is older than the
network's event horizon time.
maySkipCheckpoint
- setting it to true indicates to the platform that it may optimise away the checkpoint.payload
,
counterparty
,
counterparty
@Suspendable public void send(@NotNull java.lang.Object payload)
Queues the given payload
for sending to the counterparty
and continues without suspending.
Note that the other party may receive the message at some arbitrary later point or not at all: if counterparty
is offline then message delivery will be retried until it comes back or until the message is older than the
network's event horizon time.
payload
,
counterparty
,
counterparty
@Suspendable public void close()
Closes this session and performs cleanup of any resources tied to this session.
Note that sessions are closed automatically when the corresponding top-level flow terminates.
So, it's beneficial to eagerly close them in long-lived flows that might have many open sessions that are not needed anymore and consume resources (e.g. memory, disk etc.).
A closed session cannot be used anymore, e.g. to send or receive messages. So, you have to ensure you are calling this method only when the session is not going to be used anymore.
As a result, any operations on a closed session will fail with an exception UnexpectedFlowEndException
.
When a session is closed, the other side is informed and the session is closed there too eventually.
To prevent misuse of the API, if there is an attempt to close an uninitialised session the invocation will fail with an IllegalStateException.