001/* 002 * Copyright 2002-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.jms.support.converter; 018 019import java.util.Map; 020 021import javax.jms.JMSException; 022import javax.jms.Session; 023 024import org.springframework.beans.factory.InitializingBean; 025import org.springframework.jms.support.JmsHeaderMapper; 026import org.springframework.jms.support.SimpleJmsHeaderMapper; 027import org.springframework.lang.Nullable; 028import org.springframework.messaging.Message; 029import org.springframework.messaging.MessageHeaders; 030import org.springframework.messaging.core.AbstractMessagingTemplate; 031import org.springframework.messaging.support.MessageBuilder; 032import org.springframework.util.Assert; 033 034/** 035 * Convert a {@link Message} from the messaging abstraction to and from a 036 * {@link javax.jms.Message} using an underlying {@link MessageConverter} 037 * for the payload and a {@link org.springframework.jms.support.JmsHeaderMapper} 038 * to map the JMS headers to and from standard message headers. 039 * 040 * @author Stephane Nicoll 041 * @since 4.1 042 */ 043public class MessagingMessageConverter implements MessageConverter, InitializingBean { 044 045 private MessageConverter payloadConverter; 046 047 private JmsHeaderMapper headerMapper; 048 049 050 /** 051 * Create an instance with a default payload converter. 052 * @see org.springframework.jms.support.converter.SimpleMessageConverter 053 * @see org.springframework.jms.support.SimpleJmsHeaderMapper 054 */ 055 public MessagingMessageConverter() { 056 this(new SimpleMessageConverter(), new SimpleJmsHeaderMapper()); 057 } 058 059 /** 060 * Create an instance with the specific payload converter. 061 * @param payloadConverter the payload converter to use 062 * @since 4.3.12 063 */ 064 public MessagingMessageConverter(MessageConverter payloadConverter) { 065 this(payloadConverter, new SimpleJmsHeaderMapper()); 066 } 067 068 /** 069 * Create an instance with the specified payload converter and 070 * header mapper. 071 */ 072 public MessagingMessageConverter(MessageConverter payloadConverter, JmsHeaderMapper headerMapper) { 073 Assert.notNull(payloadConverter, "PayloadConverter must not be null"); 074 Assert.notNull(headerMapper, "HeaderMapper must not be null"); 075 this.payloadConverter = payloadConverter; 076 this.headerMapper = headerMapper; 077 } 078 079 080 /** 081 * Set the {@link MessageConverter} to use to convert the payload. 082 */ 083 public void setPayloadConverter(MessageConverter payloadConverter) { 084 this.payloadConverter = payloadConverter; 085 } 086 087 /** 088 * Set the {@link JmsHeaderMapper} to use to map JMS headers to and from 089 * standard message headers. 090 */ 091 public void setHeaderMapper(JmsHeaderMapper headerMapper) { 092 this.headerMapper = headerMapper; 093 } 094 095 @Override 096 public void afterPropertiesSet() { 097 Assert.notNull(this.payloadConverter, "Property 'payloadConverter' is required"); 098 Assert.notNull(this.headerMapper, "Property 'headerMapper' is required"); 099 } 100 101 102 @Override 103 public javax.jms.Message toMessage(Object object, Session session) throws JMSException, MessageConversionException { 104 if (!(object instanceof Message)) { 105 throw new IllegalArgumentException("Could not convert [" + object + "] - only [" + 106 Message.class.getName() + "] is handled by this converter"); 107 } 108 Message<?> input = (Message<?>) object; 109 MessageHeaders headers = input.getHeaders(); 110 Object conversionHint = headers.get(AbstractMessagingTemplate.CONVERSION_HINT_HEADER); 111 javax.jms.Message reply = createMessageForPayload(input.getPayload(), session, conversionHint); 112 this.headerMapper.fromHeaders(headers, reply); 113 return reply; 114 } 115 116 @SuppressWarnings("unchecked") 117 @Override 118 public Object fromMessage(javax.jms.Message message) throws JMSException, MessageConversionException { 119 Map<String, Object> mappedHeaders = extractHeaders(message); 120 Object convertedObject = extractPayload(message); 121 MessageBuilder<Object> builder = (convertedObject instanceof org.springframework.messaging.Message ? 122 MessageBuilder.fromMessage((org.springframework.messaging.Message<Object>) convertedObject) : 123 MessageBuilder.withPayload(convertedObject)); 124 return builder.copyHeadersIfAbsent(mappedHeaders).build(); 125 } 126 127 /** 128 * Extract the payload of the specified {@link javax.jms.Message}. 129 */ 130 protected Object extractPayload(javax.jms.Message message) throws JMSException { 131 return this.payloadConverter.fromMessage(message); 132 } 133 134 /** 135 * Create a JMS message for the specified payload and conversionHint. 136 * The conversion hint is an extra object passed to the {@link MessageConverter}, 137 * e.g. the associated {@code MethodParameter} (may be {@code null}}. 138 * @since 4.3 139 * @see MessageConverter#toMessage(Object, Session) 140 */ 141 protected javax.jms.Message createMessageForPayload( 142 Object payload, Session session, @Nullable Object conversionHint) throws JMSException { 143 144 return this.payloadConverter.toMessage(payload, session); 145 } 146 147 protected final MessageHeaders extractHeaders(javax.jms.Message message) { 148 return this.headerMapper.toHeaders(message); 149 } 150 151}