Search code examples
spring-websocketspring-messaging

Add STOMP header without recreating Message on ChannelInterceptorAdapter


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;
      }

}

Solution

  • 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;
          }