In certain cases a communication from an object to a synchronous service is required.
Imagine a service using persistent state, that sends a GiveCreditSignal to a customer object and has to wait for approval or rejection before proceeding. An inelegant and very inefficient way to implement this is a loop that invokes or until the approval went through. A much better solution would allow the service to wait for a signal sent back by the object.
This construct of a conversation is implemented by two elements: a signal and a conversationID. The waiting service waits for a specific signal sent by the conversation partner. This signal is identified by the signal name and the conversationID, that can be passed as a parameter to each signal action.
The conversations are persisted in a persistent state database. If you stop a service or the service crashes between sending and accepting, the service will try to complete the conversation after service restart. Nevertheless, the accept event timeouts continue counting down and is considered after service restart.
If you use an external persistent state database, multiple services with same persistent state owner can send conversation signals between each other.
Initiating a Conversation and Waiting for a Conversation Response
Look at the activity diagram below. It is depicting the process of initiating a conversation and waiting for the response afterwards.
Figure: Sending Signal to an Object and Waiting for the Response
1. Initiating the Conversation
In the example above, a request for credit is sent to a persistent state object Customer. The object is identified by its customer number, which is the primary key of the Customer class.
Then, a conversation id is created and a GiveCredit signal is sent to the customer object. The conversationID is passed to the Customer object, so it can be used later on to send the reply (see Sending Conversation Signals).
Persistent state signals are implicitly committed on session end only and signals will be transferred to the recipient after commit (also see xUML Runtime Transaction Concepts). So in this case, the persistent state adapter has to be manually committed, because the accept event action was added to the same activity diagram. Manually committing is done by the use of the action commit.
2. Waiting for the Conversation Response
In part two of the activity diagram, the service is waiting for the response to arrive. Response means a signal sent by a send signal action with a given conversationID. In this case, this is the credit decision signal (the very same signal that was sent by the send signal action described below in Sending Conversation Signals). The service will wait for the signal until the timeout given in the tagged value timeout is reached.
The result of the credit check is transported in an attribute of the signal.
Figure: Attributes of the Returning Signal
This is done using the <<E2EAcceptEventAction>> stereotype. When a signal arrives, its attributes are passed as output. If no signal arrives within the given timeout, an exception will be thrown. Default timeout is 30 seconds.
Sending Conversation Signals
When a conversation partner is waiting for a response, you can send a signal to this conversation using the <<E2ESendSignalAction>>. The interface is very similar to sending . However only the provided conversationID is relevant to identify the target conversation of the signal.
Figure: Constructing a Handle and Sending a Conversation Signal
In the example above, the conversation ID received earlier has been stored in attribute creditRequestorConversationID of persistent state class customer. Now, it is re-used when sending the signal the conversation partner is waiting for. Additionally a Boolean is passed as a signal parameter.