@Override @Nullable public Message<byte[]> handleErrorMessageToClient(Message<byte[]> errorMessage) { StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(errorMessage, StompHeaderAccessor.class); Assert.notNull(accessor, "No StompHeaderAccessor"); if (!accessor.isMutable()) { accessor = StompHeaderAccessor.wrap(errorMessage); } return handleInternal(accessor, errorMessage.getPayload(), null, null); }
@Override public void handleMessage(Message<?> message) throws MessagingException { String destination = getDestination(message); if (destination == null) { return; } String lookupDestination = getLookupDestination(destination); if (lookupDestination == null) { return; } MessageHeaderAccessor headerAccessor = MessageHeaderAccessor.getMutableAccessor(message); headerAccessor.setHeader(DestinationPatternsMessageCondition.LOOKUP_DESTINATION_HEADER, lookupDestination); headerAccessor.setLeaveMutable(true); message = MessageBuilder.createMessage(message.getPayload(), headerAccessor.getMessageHeaders()); if (logger.isDebugEnabled()) { logger.debug("Searching methods to handle " + headerAccessor.getShortLogMessage(message.getPayload()) + ", lookupDestination='" + lookupDestination + "'"); } handleMessageInternal(message, lookupDestination); headerAccessor.setImmutable(); }
private MessageBuilder(Message<T> originalMessage) { Assert.notNull(originalMessage, "Message must not be null"); this.payload = originalMessage.getPayload(); this.originalMessage = originalMessage; this.headerAccessor = new MessageHeaderAccessor(originalMessage); }
@Override public Message<?> preSend(Message<?> message, MessageChannel channel) { MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, MessageHeaderAccessor.class); if (accessor != null && accessor.isMutable()) { accessor.setImmutable(); } return message; }
/** * Remove the value for the given header name. */ public void removeHeader(String headerName) { if (StringUtils.hasLength(headerName) && !isReadOnly(headerName)) { setHeader(headerName, null); } }
private void logMessage(Message<?> message) { if (logger.isDebugEnabled()) { SimpMessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, SimpMessageHeaderAccessor.class); accessor = (accessor != null ? accessor : SimpMessageHeaderAccessor.wrap(message)); logger.debug("Processing " + accessor.getShortLogMessage(message.getPayload())); } }
/** * Return the original {@code MessageHeaderAccessor} used to create the headers * of the given {@code Message}, or {@code null} if that's not available or if * its type does not match the required type. * <p>This is for cases where the existence of an accessor is strongly expected * (followed up with an assertion) or where an accessor will be created otherwise. * @param message the message to get an accessor for * @param requiredType the required accessor type (or {@code null} for any) * @return an accessor instance of the specified type, or {@code null} if none * @since 4.1 */ @Nullable public static <T extends MessageHeaderAccessor> T getAccessor(Message<?> message, @Nullable Class<T> requiredType) { return getAccessor(message.getHeaders(), requiredType); }
/** * Copy the name-value pairs from the provided Map. * <p>This operation will <em>not</em> overwrite any existing values. */ public void copyHeadersIfAbsent(@Nullable Map<String, ?> headersToCopy) { if (headersToCopy != null) { headersToCopy.forEach((key, value) -> { if (!isReadOnly(key)) { setHeaderIfAbsent(key, value); } }); } }
@Test public void serializeMutableHeaders() throws Exception { Map<String, Object> headers = new HashMap<>(); headers.put("foo", "bar"); Message<String> message = new GenericMessage<>("test", headers); MessageHeaderAccessor mutableAccessor = MessageHeaderAccessor.getMutableAccessor(message); mutableAccessor.setContentType(MimeTypeUtils.TEXT_PLAIN); message = new GenericMessage<>(message.getPayload(), mutableAccessor.getMessageHeaders()); Message<?> output = (Message<?>) SerializationTestUtils.serializeAndDeserialize(message); assertEquals("test", output.getPayload()); assertEquals("bar", output.getHeaders().get("foo")); assertNotNull(output.getHeaders().get(MessageHeaders.CONTENT_TYPE)); }
/** * Copy the name-value pairs from the provided Map. This operation will overwrite any * existing values. Use { {@link #copyHeadersIfAbsent(Map)} to avoid overwriting * values. Note that the 'id' and 'timestamp' header values will never be overwritten. */ public MessageBuilder<T> copyHeaders(@Nullable Map<String, ?> headersToCopy) { this.headerAccessor.copyHeaders(headersToCopy); return this; }
@Override public Message<?> toMessage(Object payload, @Nullable MessageHeaders headers) { if (headers != null) { MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(headers, MessageHeaderAccessor.class); if (accessor != null && accessor.isMutable()) { return MessageBuilder.createMessage(payload, accessor.getMessageHeaders()); } } return MessageBuilder.withPayload(payload).copyHeaders(headers).build(); }
@Override protected void doSend(String destination, Message<?> message) { Assert.notNull(destination, "Destination must not be null"); SimpMessageHeaderAccessor simpAccessor = MessageHeaderAccessor.getAccessor(message, SimpMessageHeaderAccessor.class); if (simpAccessor != null) { if (simpAccessor.isMutable()) { simpAccessor.setDestination(destination); simpAccessor.setMessageTypeIfNotSet(SimpMessageType.MESSAGE); simpAccessor.setImmutable(); sendInternal(message); return; } else { // Try and keep the original accessor type simpAccessor = (SimpMessageHeaderAccessor) MessageHeaderAccessor.getMutableAccessor(message); initHeaders(simpAccessor); } } else { simpAccessor = SimpMessageHeaderAccessor.wrap(message); initHeaders(simpAccessor); } simpAccessor.setDestination(destination); simpAccessor.setMessageTypeIfNotSet(SimpMessageType.MESSAGE); message = MessageBuilder.createMessage(message.getPayload(), simpAccessor.getMessageHeaders()); sendInternal(message); }
@Test public void convertAndSendWithSimpMessageHeaders() { MessageHeaderAccessor accessor = new MessageHeaderAccessor(); accessor.setHeader("key", "value"); accessor.setLeaveMutable(true); MessageHeaders headers = accessor.getMessageHeaders(); this.template.convertAndSend("channel", "data", headers); List<Message<byte[]>> messages = this.messageChannel.getMessages(); Message<byte[]> message = messages.get(0); assertSame(headers, message.getHeaders()); assertFalse(accessor.isMutable()); }
protected final void doSend(MessageChannel channel, Message<?> message, long timeout) { Assert.notNull(channel, "MessageChannel is required"); Message<?> messageToSend = message; MessageHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, MessageHeaderAccessor.class); if (accessor != null && accessor.isMutable()) { accessor.removeHeader(this.sendTimeoutHeader); accessor.removeHeader(this.receiveTimeoutHeader); accessor.setImmutable(); } else if (message.getHeaders().containsKey(this.sendTimeoutHeader) || message.getHeaders().containsKey(this.receiveTimeoutHeader)) { messageToSend = MessageBuilder.fromMessage(message) .setHeader(this.sendTimeoutHeader, null) .setHeader(this.receiveTimeoutHeader, null) .build(); } boolean sent = (timeout >= 0 ? channel.send(messageToSend, timeout) : channel.send(messageToSend)); if (!sent) { throw new MessageDeliveryException(message, "Failed to send message to channel '" + channel + "' within timeout: " + timeout); } }
private Message<?> outputMessage(Message<?> originalMessage, Message<?> retrievedMessage, MessageHeaderAccessor additionalHeaders) { MessageHeaderAccessor headers = MessageHeaderAccessor .getMutableAccessor(originalMessage); if (originalMessage.getPayload() instanceof MessagingException) { headers.copyHeaders(MessageHeaderPropagation.propagationHeaders( additionalHeaders.getMessageHeaders(), this.tracing.propagation().keys())); return new ErrorMessage((MessagingException) originalMessage.getPayload(), isWebSockets(headers) ? headers.getMessageHeaders() : new MessageHeaders(headers.getMessageHeaders())); } headers.copyHeaders(additionalHeaders.getMessageHeaders()); return new GenericMessage<>(retrievedMessage.getPayload(), isWebSockets(headers) ? headers.getMessageHeaders() : new MessageHeaders(headers.getMessageHeaders())); }
/** * Set the value for the given header name. * <p>If the provided value is {@code null}, the header will be removed. */ public void setHeader(String name, @Nullable Object value) { if (isReadOnly(name)) { throw new IllegalArgumentException("'" + name + "' header is read-only"); } verifyType(name, value); if (value != null) { // Modify header if necessary if (!ObjectUtils.nullSafeEquals(value, getHeader(name))) { this.modified = true; this.headers.getRawHeaders().put(name, value); } } else { // Remove header if available if (this.headers.containsKey(name)) { this.modified = true; this.headers.getRawHeaders().remove(name); } } }
@Nullable private String getDisconnectReceipt(SimpMessageHeaderAccessor simpHeaders) { String name = StompHeaderAccessor.DISCONNECT_MESSAGE_HEADER; Message<?> message = (Message<?>) simpHeaders.getHeader(name); if (message != null) { StompHeaderAccessor accessor = MessageHeaderAccessor.getAccessor(message, StompHeaderAccessor.class); if (accessor != null) { return accessor.getReceipt(); } } return null; }
/** * Copy the name-value pairs from the provided Map. * <p>This operation will overwrite any existing values. Use * {@link #copyHeadersIfAbsent(Map)} to avoid overwriting values. */ public void copyHeaders(@Nullable Map<String, ?> headersToCopy) { if (headersToCopy != null) { headersToCopy.forEach((key, value) -> { if (!isReadOnly(key)) { setHeader(key, value); } }); } }