001/*
002 * Copyright 2002-2016 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;
020import javax.jms.JMSException;
021import javax.jms.Session;
022
023import org.springframework.beans.factory.InitializingBean;
024import org.springframework.jms.support.JmsHeaderMapper;
025import org.springframework.jms.support.SimpleJmsHeaderMapper;
026import org.springframework.messaging.Message;
027import org.springframework.messaging.MessageHeaders;
028import org.springframework.messaging.core.AbstractMessagingTemplate;
029import org.springframework.messaging.support.MessageBuilder;
030import org.springframework.util.Assert;
031
032/**
033 * Convert a {@link Message} from the messaging abstraction to and from a
034 * {@link javax.jms.Message} using an underlying {@link MessageConverter}
035 * for the payload and a {@link org.springframework.jms.support.JmsHeaderMapper}
036 * to map the JMS headers to and from standard message headers.
037 *
038 * @author Stephane Nicoll
039 * @since 4.1
040 */
041public class MessagingMessageConverter implements MessageConverter, InitializingBean {
042
043        private MessageConverter payloadConverter;
044
045        private JmsHeaderMapper headerMapper;
046
047
048        /**
049         * Create an instance with a default payload converter.
050         * @see org.springframework.jms.support.converter.SimpleMessageConverter
051         * @see org.springframework.jms.support.SimpleJmsHeaderMapper
052         */
053        public MessagingMessageConverter() {
054                this(new SimpleMessageConverter(), new SimpleJmsHeaderMapper());
055        }
056
057        /**
058         * Create an instance with the specific payload converter.
059         * @param payloadConverter the payload converter to use
060         * @since 4.3.12
061         */
062        public MessagingMessageConverter(MessageConverter payloadConverter) {
063                this(payloadConverter, new SimpleJmsHeaderMapper());
064        }
065
066        /**
067         * Create an instance with the specified payload converter and
068         * header mapper.
069         */
070        public MessagingMessageConverter(MessageConverter payloadConverter, JmsHeaderMapper headerMapper) {
071                Assert.notNull(payloadConverter, "PayloadConverter must not be null");
072                Assert.notNull(headerMapper, "HeaderMapper must not be null");
073                this.payloadConverter = payloadConverter;
074                this.headerMapper = headerMapper;
075        }
076
077
078        /**
079         * Set the {@link MessageConverter} to use to convert the payload.
080         */
081        public void setPayloadConverter(MessageConverter payloadConverter) {
082                this.payloadConverter = payloadConverter;
083        }
084
085        /**
086         * Set the {@link JmsHeaderMapper} to use to map JMS headers to and from
087         * standard message headers.
088         */
089        public void setHeaderMapper(JmsHeaderMapper headerMapper) {
090                this.headerMapper = headerMapper;
091        }
092
093        @Override
094        public void afterPropertiesSet() {
095                Assert.notNull(this.payloadConverter, "Property 'payloadConverter' is required");
096                Assert.notNull(this.headerMapper, "Property 'headerMapper' is required");
097        }
098
099
100        @Override
101        public javax.jms.Message toMessage(Object object, Session session) throws JMSException, MessageConversionException {
102                if (!(object instanceof Message)) {
103                        throw new IllegalArgumentException("Could not convert [" + object + "] - only [" +
104                                        Message.class.getName() + "] is handled by this converter");
105                }
106                Message<?> input = (Message<?>) object;
107                MessageHeaders headers = input.getHeaders();
108                Object conversionHint = (headers != null ? headers.get(
109                                AbstractMessagingTemplate.CONVERSION_HINT_HEADER) : null);
110                javax.jms.Message reply = createMessageForPayload(input.getPayload(), session, conversionHint);
111                this.headerMapper.fromHeaders(headers, reply);
112                return reply;
113        }
114
115        @SuppressWarnings("unchecked")
116        @Override
117        public Object fromMessage(javax.jms.Message message) throws JMSException, MessageConversionException {
118                if (message == null) {
119                        return null;
120                }
121                Map<String, Object> mappedHeaders = extractHeaders(message);
122                Object convertedObject = extractPayload(message);
123                MessageBuilder<Object> builder = (convertedObject instanceof org.springframework.messaging.Message) ?
124                                MessageBuilder.fromMessage((org.springframework.messaging.Message<Object>) convertedObject) :
125                                MessageBuilder.withPayload(convertedObject);
126                return builder.copyHeadersIfAbsent(mappedHeaders).build();
127        }
128
129        /**
130         * Extract the payload of the specified {@link javax.jms.Message}.
131         */
132        protected Object extractPayload(javax.jms.Message message) throws JMSException {
133                return this.payloadConverter.fromMessage(message);
134        }
135
136        /**
137         * Create a JMS message for the specified payload.
138         * @see MessageConverter#toMessage(Object, Session)
139         * @deprecated as of 4.3, use {@link #createMessageForPayload(Object, Session, Object)}
140         */
141        @Deprecated
142        protected javax.jms.Message createMessageForPayload(Object payload, Session session) throws JMSException {
143                return this.payloadConverter.toMessage(payload, session);
144        }
145
146        /**
147         * Create a JMS message for the specified payload and conversionHint.
148         * The conversion hint is an extra object passed to the {@link MessageConverter},
149         * e.g. the associated {@code MethodParameter} (may be {@code null}}.
150         * @see MessageConverter#toMessage(Object, Session)
151         * @since 4.3
152         */
153        @SuppressWarnings("deprecation")
154        protected javax.jms.Message createMessageForPayload(Object payload, Session session, Object conversionHint)
155                        throws JMSException {
156
157                return createMessageForPayload(payload, session);
158        }
159
160        protected final MessageHeaders extractHeaders(javax.jms.Message message) {
161                return this.headerMapper.toHeaders(message);
162        }
163
164}