Sending a message to another JBI component

This section describes the mechanisms which provide MessageExchanges transport between JBI components.

The messaging architecture in a Petals node is composed of 3 main layers to convey components messages.

The DeliveryChannel, introduced in the JBI specifications, is the access point for JBI components to send messages. Each JBI component interacts with its DeliveryChannel. The Router, which is the core of the NormalizedMessageRouter, assures the routing of MessageExchanges toward their destinations. It is the ''Router-impl'' Fractal component

The Transporter, at the bottom level, provides the transport device to send and receive MessageExchanges inside the PEtALS domain. It is the ''Joram-Transporter'' Fractal component

exchangecollabo.png

A service consumer asks for a service by sending a MessageExchange object using the ''send()'' or ''sendSync()'' methods of its DeliveryChannel.

A service provider treats requests from consumers by polling MessageExchanges, using the ''accept()'' method of its DeliveryChannel.

The consumer has to create and form a MessageExchange object before using the ''send()'' method (via the MessageExchangeFactory provided by the DeliveryChannel).

MessageExchange implementation

This MessageExchange, implemented by org.objectweb.petals.jbi.messaging.MessageExchangeImpl is mainly composed of :

  • the address of the service to invoke (an ''Interface'', ''Service'', or ''Endpoint''),
  • the message to exchange (NormalizedMessage),
  • its message exchange pattern (request, request-response),
  • the DeliveryChannelImpl of the initiator of the exchange (the Consumer).
msgExchangeClass.JPG

Sending a message asynchronously

  • Delivery Channel layer
When the DeliveryChannel ''send()'' method is called, it begins by updating the status of the MessageExchangeImpl, setting it to the terminate state if necessary.

If the MessageExchangeImpl becomes terminated, and the ACK property is not set on the message, the MessageExchangeImpl is not send. Otherwise, the DeliveryChannelImpl calls the send() method of the RouterImpl.

  • Router layer
The RouterImpl checks the current role of the MessageExchangeImpl.

If the role is Consumer, it means that the message is addressed to the provider of the service, so the RouterImpl asks to the AdressResolver instance to resolve the targeted endPoint by calling ''resolveAdress()''. The AdressResolver can deals with the register component to resolve the endPoint.

If the role is Provider, the consumer endPoint is already referenced in the MessageExchangeImpl.

Once the endPoint retrieved, the RouterImpl changes the current role of the MessageExchangeImpl to match the role of the destination component.

Finally, it calls the ''send()'' method of the Transporter implementation.

  • Transporter layer
We propose for the moment only one implementation of the Transporter, relying on JORAM, the JoramTransporter. It takes care of the transport of the issued MessageExchange to the destination address.

To optimize the transport, the JoramTransporter cleans the payload of the MessageExchangeImpl. This lightening permits to gain performance during serialization/unserialization processing and message transport duration.

A MessageExchangeImpl is composed of a HashMap of NormalizedMessageImpls, which constitute the payload of the message.

When an acknowledgement is sent, the attached NormalizedMessageImpls are removed.

When a response NormalizedMessageImpl is sent, the previous request NormalizedMessageImpl, still attached to the MessageExchangeimpl, is removed.

Receiving a message

receivesequence.png

Once the ''accept()'' method is called on the DeliveryChannelImpl, this latter checks if he is opened, if so it calls the ''receive()'' method of the RouterImpl.

The RouterImpl extracts the name of the component from the ComponentContextImpl, and calls the poll() method of the JoramTransporter.

Any message issued in an asynchronous way is fetch from the JORAM server and returns by the JoramTransporter.

Sending a message synchronously

  • Message correlation
When the issuer of the MessageExchange want to send synchronously its message, a mechanism is supplied to correlate the MessageExchangeImpl issued and the response received back.

In fact, the instance of MessageExchange that the JBI component manipulates is a MessageExchangeDecorator. This decorator contains a reference to a MessageExchangeImpl.

  • The sending
sendsyncsequence2.png

When the ''sendSync()'' method of the DeliveryChannelImpl is called, it extracts the MessageExchangeImpl from the received MessageExchangeDecorator, set SYNC properties to it and store it into an HashMap called ''waitingExchanges''.

After that, the normal processing of a send is called.

Once the send is done, a ''wait()'' is done on the MessageExchangeDecorator, which makes the current thread to wait.

  • The reception
responsesync.png

The JoramTransporter is listening for the response by filtering incoming messages marked with the SYNC properties.

Once the response is received into the JoramTransporter, it relays the MessageExchangeImpl to the implementation of the MessageExchangeListener, which is the DeliveryChannelImpl by calling the method ''onMessageExchange()''.

Then the DeliveryChannelImpl removes the SYNC properties from the MessageExchangeImpl, retrieves the bounded MessageExchangeDecorator from ''waitingExchanges'', attaches the MessageExchangeImpl to it, notifies it to awaken the pending thread.

Finally, the awaken thread finishes the ''sendSync()'' method and returns true. The JBI component manipulates its MessageExchangeDecorator to retrieve the response message.

  • Timeout
timeoutsync.png

In synchronous mode, it is possible to specify a timeout, to limit the duration of waiting a response. If the timeout is set, the wait done on the MessageExchangeDecorator during the ''sendSync()'' processing is waiting until the response has been received OR until the timeout is reached.

If so, the owner of the MessageExchangeDecorator is switched back, its status is set to the ERROR state and it is set to terminated.

Finally the ''sendSync()'' method returns false.