...
Its very easy to enable ActiveMQ for Stomp. Just add a connector to the broker using the stomp URL.
Code Block |
|
|
<transportConnectors>
<transportConnector name="stomp" uri="stomp://localhost:61613"/>
</transportConnectors>
|
To see a full example, try this XML. If you save that XML as foo.xml then you can run stomp via the command line as
Code Block |
|
|
activemq xbean:foo.xml
|
For more help see Run Broker.
...
For better scalability (and performance) you might want to run Stomp protocol over NIO transport. To do that just use stomp+nio transport prefix instead of stomp. For example, add the following transport configuration in your XML file
Code Block |
|
|
<transportConnector name="stomp+nio" uri="stomp+nio://localhost:61612"/>
|
...
It's easy to configure ActiveMQ to use Stomp over SSL connection. All you have to do is use stomp+ssl transport prefix instead of stomp. For example, add the following transport configuration in your XML file
Code Block |
|
|
<transportConnector name="stomp+ssl" uri="stomp+ssl://localhost:61612"/>
|
...
As of version 5.9.0 the timeout enforcement for read heart-beats is now configurable via a new transport option,
transport.hbGracePeriodMultiplier:
Code Block |
|
|
<transportConnectors>
<transportConnector name="stomp"
uri="stomp://localhost:61613?transport.hbGracePeriodMultiplier=1.5"/>
</transportConnectors>
|
...
Here's a quick example of how to use built-in transformer (taken from test cases)
Code Block |
|
|
private String xmlObject = "<pojo>\n"
+ " <name>Dejan</name>\n"
+ " <city>Belgrade</city>\n"
+ "</pojo>";
public void testTransformationReceiveXMLObject() throws Exception {
MessageProducer producer = session.createProducer(new ActiveMQQueue("USERS." + getQueueName()));
ObjectMessage message = session.createObjectMessage(new SamplePojo("Dejan", "Belgrade"));
producer.send(message);
String frame = "CONNECT\n" + "login: system\n" + "passcode: manager\n\n" + Stomp.NULL;
stompConnection.sendFrame(frame);
frame = stompConnection.receiveFrame();
assertTrue(frame.startsWith("CONNECTED"));
frame = "SUBSCRIBE\n" + "destination:/queue/USERS." + getQueueName() + "\n" + "ack:auto" + "\n" + "transformation:jms-object-xml\n\n" + Stomp.NULL;
stompConnection.sendFrame(frame);
frame = stompConnection.receiveFrame();
assertTrue(frame.trim().endsWith(xmlObject));
frame = "DISCONNECT\n" + "\n\n" + Stomp.NULL;
stompConnection.sendFrame(frame);
}
|
...
in the META-INF/services/org/apache/activemq/transport/frametranslator/jms-xml file.
Message Ordering
When delivering messages the broker uses the message-id to order them. This is based on the producer-id which, in the case of STOMP connections, is generated at the point that the producer connects to the broker.
Therefore out-of-order messages may occur from a stomp application perspective. To give an example:
- Producer p1 connects
- Producer p2 connects
- Producer p2 sends Message 1 to /queue/test
- Producer p1 sends Message 2 to /queue/test several seconds later
- Consumer c1 connects and subscribes to /queue/test and receives Message 2 followed by Message 1.
Debugging
In case you want to debug Stomp communication between broker and clients you should configure the Stomp connector with the trace parameter, like this:
Code Block |
<transportConnectors>
<transportConnector name="stomp" uri="stomp://localhost:61613?trace=true"/>
</transportConnectors>
|
...
Furthermore, you have to enable tracing for the appropriate log. You can achieve that by adding the following to your conf/log4j.properties
Code Block |
log4j.logger.org.apache.activemq.transport.stomp=TRACE
|
Finally, you will probably want to keep these messages in the separate file instead of polluting the standard broker's log. You can achieve that with the following log4j configuration:
Code Block |
log4j.appender.stomp=org.apache.log4j.RollingFileAppender
log4j.appender.stomp.file=${activemq.base}/data/stomp.log
log4j.appender.stomp.maxFileSize=1024KB
log4j.appender.stomp.maxBackupIndex=5
log4j.appender.stomp.append=true
log4j.appender.stomp.layout=org.apache.log4j.PatternLayout
log4j.appender.stomp.layout.ConversionPattern=%d [%-15.15t] %-5p %-30.30c{1} - %m%n
log4j.logger.org.apache.activemq.transport.stomp=TRACE, stomp
log4j.additivity.org.apache.activemq.transport.stomp=false
# Enable these two lines and disable the above two if you want the
frame IO ONLY (e.g., no heart beat messages, inactivity monitor etc).
#log4j.logger.org.apache.activemq.transport.stomp.StompIO=TRACE, stomp
#log4j.additivity.org.apache.activemq.transport.stomp.StompIO=false
|
...
Since version 5.2, there is a simple Java Stomp API distributed with ActiveMQ. Note that this API is provided purely for testing purposes and you should always consider using standard JMS API from Java instead of this one. The following code snippet provides a simple example of using this API:
Code Block |
StompConnection connection = new StompConnection();
connection.open("localhost", 61613);
connection.connect("system", "manager");
StompFrame connect = connection.receive();
if (!connect.getAction().equals(Stomp.Responses.CONNECTED)) {
throw new Exception ("Not connected");
}
connection.begin("tx1");
connection.send("/queue/test", "message1", "tx1", null);
connection.send("/queue/test", "message2", "tx1", null);
connection.commit("tx1");
connection.subscribe("/queue/test", Subscribe.AckModeValues.CLIENT);
connection.begin("tx2");
StompFrame message = connection.receive();
System.out.println(message.getBody());
connection.ack(message, "tx2");
message = connection.receive();
System.out.println(message.getBody());
connection.ack(message, "tx2");
connection.commit("tx2");
connection.disconnect();
|
This example is distributed with the ActiveMQ distribution. You can run it from the example folder with
Code Block |
ant stomp
|
Stomp extensions for JMS message semantics
...