Pass message payload by reference: Usage scenarios and example code for forwarding applications
A JMS forwarder application receives a message (through a connection factory, or if it is a message-driven bean through an activation specification), then sends the message object on to another destination. Explore the different usage scenarios, then code your JMS forwarding applications so that you can safely pass message payloads by reference when forwarding messages from one queue to another within a single server.
When large object messages or bytes messages are sent, the cost in memory and processor use of serializing, deserializing, and copying the message payload can be significant. If you enable the pass message payload by reference properties on a connection factory or activation specification, you tell the default messaging provider to override the JMS 1.1 specification and potentially reduce or bypass this data copying.
In the following figure, messages pass from queue1 on a messaging engine, through a consumer activation specification or connection factory, to a JMS forwarding application. They are then forwarded through a producer connection factory to queue2 on the same messaging engine.
- A forwarding application does not replace the message object. This is useful if your application
is just logging or otherwise recording (for example, printing out) the message before forwarding it,
and also means that the forwarded message retains some useful message properties such as the
JMSCorrelationID
,JMSReplyTo
andJMSType
properties. - A forwarding application can modify or replace the message payload. If it replaces the payload, it sets the new payload in the message object and changes the payload reference to point to the new message payload.
- For a forwarding application, the forwarded message is created and configured by the consumer connection factory or activation specification. The producer connection factory is used solely to route the forwarded message and has no effect upon the contents of the forwarded message.
The following table describes the four forwarding application usage scenarios that affect how you set the pass message payload by reference properties. Note that, because the producer connection factory has no effect upon the contents of the forwarded message, you set both the consumer properties and the producer/forwarder properties on the consumer connection factory or activation specification.
Forwarding application usage scenario | consumerDoesNotModify
property settingPayloadAfterGet |
producerDoesNotModify
(for connection factories)
or PayloadAfterSet forwarderDoesNotModify
(for activation specifications) property
settingPayloadAfterSet |
---|---|---|
Scenario 1: The application receives a message, looks at the payload but does not modify it, and forwards the message on without modifying or replacing the payload. | Enabled | Not required, but can be enabled |
Scenario 2: The application receives a message, looks at the payload but does not modify it, replaces the payload in the message with a new payload and forwards the message on without modifying the payload after the call to set it into the message. | Enabled | Enabled |
Scenario 3: The application receives a message, looks at and modifies the payload, then sets the modified payload or some other data back into the message and forwards the message on without further modifying the payload after the call to set it into the message. | NOT enabled | Enabled |
Scenario 4: The application receives a message, looks at and modifies the payload, then sets the modified payload or some other data back into the message, then further modifies the payload after the call to set it into the message. | NOT enabled | NOT enabled |
For scenarios 1, 2 and 3 you can enable one or more of the pass message payload by reference properties, provided that your forwarding application can guarantee to behave as described in the scenario. To help you achieve this, here is some example code that you can adapt for use in your applications.
Forwarding application: scenario 1
The application receives a message, looks at the payload but does not modify it, and forwards the message on without modifying or replacing the payload.
public void onMessage (Message message)
{
ObjectMessage oMessage = (ObjectMessage) message;
DataObject data = oMessage.getObject();
System.out.print(data.getXXX());
System.out.print(data.getYYY());
// get a session to forward on the received message
producer.send(message);
session.close();
}
Forwarding application: scenario 2
The application receives a message, looks at the payload but does not modify it, replaces the payload in the message with a new payload and forwards the message on without modifying the payload after the call to set it into the message.
public void onMessage (Message message)
{
ObjectMessage oMessage = (ObjectMessage) message;
DataObject data = oMessage.getObject();
System.out.print(data.getXXX());
System.out.print(data.getYYY());
// get a session to forward on the received message
message.setObject(newData);
producer.send(message);
session.close();
}
For bytes messages, your application must also guarantee to write only a single full byte array into the message.byte [] data = myByteData;
BytesMessage message = session.createBytesMessage();
message.writeBytes(data);
data = null;
producer.send(message);
Forwarding application: scenario 3
The application receives a message, looks at and modifies the payload, then sets the modified payload or some other data back into the message and forwards the message on without further modifying the payload after the call to set it into the message.
public void onMessage (Message message)
{
ObjectMessage oMessage = (ObjectMessage) message;
DataObject data = oMessage.getObject();
System.out.print(data.getXXX());
System.out.print(data.getYYY());
// get a session to forward on the received message
data.setXXX(xxx);
data.setYYY(yyy);
message.setObject(data);
producer.send(message);
session.close();
}
For bytes messages, your application must also guarantee to write only a single full byte array into the message.byte [] data = myByteData;
BytesMessage message = session.createBytesMessage();
message.writeBytes(data);
data = null;
producer.send(message);