3

I need to add header to a STOMP message currently it is working as below but i am recreating the message , is it possible to just add native header without having to recreate the message for performance .

public class MyChannelInterceptor extends ChannelInterceptorAdapter {


    @Override
      public Message<?> preSend(Message<?> message, MessageChannel channel) {
        StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);

        StompCommand command = accessor.getCommand();
        if(command != null) {
            log.debug("Receiving msg {} from {}",command,accessor.getUser().getName());
            if(command == StompCommand.SEND) {
                log.debug("Adding expires header to  msg {} from {}",command,accessor.getUser().getName());
                String ttlString = accessor.getFirstNativeHeader("ttl");
                long ttl = 30000;
                try {
                    ttl = Long.parseLong(ttlString);
                } 
                catch(Exception ex) {
                    log.error("TTL header received but not in correct format {}",ttlString);
                }
                accessor.addNativeHeader("expires", Long.toString(System.currentTimeMillis() + ttl));

                return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
            }
        }
        return message;
      }

}
Shahbour
  • 1,323
  • 1
  • 16
  • 42

2 Answers2

6

This is what i was looking for

StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);

The above code will get the actual StompHeaderAccessor of the message so if you manipulate the native headers they are directly reflected on the message while

StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);

will get a clone of the headers and you have to create a new message with the new cloned headers

full fixed code below

@Override
      public Message<?> preSend(Message<?> message, MessageChannel channel) {

        StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class);
       // StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
        if(accessor != null) {
            StompCommand command = accessor.getCommand();
            if(command != null) {
                log.debug("Receiving msg {} from {}",command,accessor.getUser().getName());
                if(command == StompCommand.SEND) {

                    log.debug("Adding expires header to  msg {} from {}",command,accessor.getUser().getName());
                    String ttlString = accessor.getFirstNativeHeader("ttl");
                    long ttl = 30000;
                    if(ttlString != null) {
                        try {
                            ttl = Long.parseLong(ttlString);
                        } 
                        catch(Exception ex) {
                            log.error("TTL header received but not in correct format {}",ttlString);
                        }
                    }

                    accessor.addNativeHeader("expires", Long.toString(System.currentTimeMillis() + ttl));
                     // I don't need any more to create a new message
                    //return MessageBuilder.createMessage(message.getPayload(), accessor.getMessageHeaders());
                }
            }
        }
        return message;
      }
Shahbour
  • 1,323
  • 1
  • 16
  • 42
0

Since addNativeHeader succeeds, that indicates the message is still mutable - see addNativeHeader().

In any case, since the NATIVE_HEADERS message header is a MultiValueMap-valued header, you can update the header contents in-place.

Hence, there is no need to create a new message.

You would have to create a new message if you add a new header to the message itself (rather than updating the mutable contents of an existing header).

EDIT

I just ran a test; as long as the message is still mutable, you can change it...

@Test
public void test() {
    Map<String, Object> map = new HashMap<String, Object>();
    MutableMessageHeaders headers = new MutableMessageHeaders(map);
    Message<String> message = MessageBuilder.createMessage("foo", headers);
    StompHeaderAccessor accessor = StompHeaderAccessor.wrap(message);
    accessor.addNativeHeader("foo", "bar");
    System.out.println(message.getHeaders().get(NativeMessageHeaderAccessor.NATIVE_HEADERS));
    accessor.setImmutable();
    try {
        accessor.addNativeHeader("baz", "qux");
        fail("expected IllegalStateException");
    }
    catch (IllegalStateException e) {

    }
}

That said, are you experiencing a performance problem or is this just a perceived issue. Message creation is not expensive.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
  • How will I then tell the message to get updated with the new accessor and it is not getting the new headed added – Shahbour Mar 18 '16 at 13:45
  • I am not sure what you mean; the accessor simply wraps the message; as long as the message is still mutable, you can add new headers. If it was already immutable, the `addNativeHeader` would fail. – Gary Russell Mar 18 '16 at 14:16
  • i made assumption that creating message is heavy , what i tried is commenting out return MessageBuilder.createMessage ... , but the result is message is returned exactly as it came without the expires header added – Shahbour Mar 18 '16 at 15:11