Overview
Exchange is a construct (TODO: add link to API docs) for storing a message payload plus contextual information relating to an invocation on an Operation exposed by a Service. It also contains methods for sending the Exchange instance from the Service Consumer/Client to the target ServiceOperation ("IN") and for sending a response/fault from the target Service back to the waiting Consumer/Client ("OUT").
The following is a simple illustration of an IN_OUT message Exchange (IN_ONLY is also supported).
- A: Consumer puts an IN message payload into the Exchange and calls send().
- B: Service Operation extracts the IN message payload and processes it.
- C: Service Operation produces an OUT message payload and puts it into the Exchange and calls send().
- D: Consumer extracts OUT message payload and processes it.
During the lifecycle of the Exchange, the message payloads (IN and OUT) may need to exist in different formats:
- The IN message payload will start life (at A) as the payload type produced by the consumer, but may need to be presented to the target Service Operation (at B) as a different type (one that the Service Operation understands).
- Likewise with the OUT message payload, it may start life as one format (at C), but may need to be presented to the Consumer as a different format (at D).
Message payload type is also something that applies to Fault messages. If the Service Operation needs to route a Fault back to the Consumer (OUT), the possible Fault message type produced by the Service Operation (at C) may be different to the Fault message type accepted by the Consumer (at D).
To formalize all of the above, SwitchYard has the concept of an ExchangeContract. This construct allows us to decorate an Excahnge instance with the message type information as outlined above. ExchangeContract is defined in code as follows.
public interface ExchangeContract { InvocationContract getInvokerInvocationMetaData(); ServiceOperation getServiceOperation(); } public interface InvocationContract { QName getInputType(); QName getOutputType(); QName getFaultType(); } public interface ServiceOperation extends InvocationContract { // Non-relevant methods omitted !! }
The main point to note is that ExchangeContract is a 2-way InvocationContract, specifiying the input, output and fault types of both the Consumer/Invoker and the ServiceOperation:
- Invoker: The IN message payload type put into the message by the Consumer/Invoker (at A).
- Invoker: The OUT message payload type expected/accepted by the Consumer/Invoker (at D).
- Invoker: The Fault message payload type expected/accepted by the Consumer/Invoker (at D).
- ServiceOperation: The IN message payload type expected/accepted by the ServiceOperation (at B).
- ServiceOperation: The OUT message payload type put into the message by the ServiceOperation (at C).
- ServiceOperation: The Fault message payload type put into the message by the ServiceOperation (at C).
Who Specifies The ExchangeContract Type Information?
As outlined above, two sets of type information needs to be specified:
- The Invoker/Consumer type information. This is specified on the ExchangeContract invokerInvocationMetaData.
- The target ServiceOperation type information. This is specified on the ExchangeContract serviceOperation.
Service registration should include ServiceInterface information, which should include a list of ServiceOperations for the operations exposed by the Service. In the case of Bean components Service implementations, this will be performed automatically by the deployer. The Invoker's type information must be attached to the ExchangeContract by the Invoker/Consumer.
In the case of the SOAP Gateway (as an example), it creates Exchange instances and uses them for invoking a target ServiceOperation. It sets the Invoker type information based on SOAP port input and output types. It sets the fault type as the standard SOAP Fault type. The type information for the target ServiceOperation comes from the registration of that Service.
Comments