JMS message size

18,878

Solution 1

Because JMS messages are serialized in sending process, the best way how to obtain size of message is through ObjectOutputStream.

private int getMessageSizeInBytes(MessageWrapper message) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(message);
    oos.close();
    return baos.size();
}

Solution 2

I do not think that you have any seriously better alternative to determine the JMS message size than measuring of its serialized size.

But you can add some optimizations if you want. There are several types of messages (e.g. MapMessage, ObjectMessage, TextMessage).

The size of text message is the length of its text. The size of map message is the total size of all its fields. The fields are primitives or java.util.Date, so it is not a problem to measure them. Object message contains serializable object, so you can measure its size by writing to ByteOutputStream.

I think that implementation of leaky bucket using JMS may be simplified if you are using hidden feature of most JMS providers to send delayed messages. You can measure the message when enqueueing it and decide when do you want the subscriber to receive it. Please read here for details of how to send delayed messages: http://alexradzin.blogspot.com/2010/10/send-delayed-jms-messages.html

Solution 3

In addition to the earlier comment by @AlexR, BytesMessage has a getBodyLength() method

http://download.oracle.com/javaee/1.4/api/javax/jms/BytesMessage.html#getBodyLength

and you can probably estimate typical header size in transit by capturing a few objects created using Session.createMessage() - i.e. the JMS message type with no payload. I think i'd be tempted to work directly with a payload in a byte[], using a BytesMessage, and compress via a ZipOutputStream if bandwidth is critical. In addition, JMS allows hints to suppress message timestamp and message id, which may help reduce message size e.g.

http://download.oracle.com/javaee/1.4/api/javax/jms/MessageProducer.html#setDisableMessageTimestamp%28boolean%29

although providers are not required to support it,

If the JMS provider accepts this hint, these messages must have the message ID set to null; if the provider ignores the hint, the message ID must be set to its normal unique value

I once worked with very bandwidth-limited JMS on WebSphere MQ everyplace, and it was possible to get the message size pretty small in this way - although the native wireframe format was also optimised for size in that case

Share:
18,878
Sorceror
Author by

Sorceror

Programmer and computer enthusiastic. Love coding, computer graphics and demoscene.

Updated on August 07, 2022

Comments

  • Sorceror
    Sorceror almost 2 years

    I'm currently working on bandwidth limiting feature (don't ask me why, its not my decision) for application which use JMS (Spring framework JMS and Active MQ namely) to sending messages with payload between server and clients.

    I found lot of throttling methods to limit incoming JMS messages (but none of them based on actual bandwidth load), however I didn't find any possible way to limit outgoing message flow. So I decided to write Leaky bucket algorithm on my own.

    Is there some way how to obtain size of JMS message? Other than 'sizeof' implementation in Java (In Java, what is the best way to determine the size of an object?)

  • Sorceror
    Sorceror over 12 years
    Bandwidth is not critical, our customer just want to manage the throughput. +1 for getBodyLength() but I'm affraid that this will work only for BytesMessage instances, which I suppose I don't have..