001/*
002 * Copyright 2006-2007 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.batch.item.jms;
018
019import org.apache.commons.logging.Log;
020import org.apache.commons.logging.LogFactory;
021import org.springframework.batch.item.ItemReader;
022import org.springframework.beans.factory.InitializingBean;
023import org.springframework.jms.core.JmsOperations;
024import org.springframework.jms.core.JmsTemplate;
025import org.springframework.util.Assert;
026
027import javax.jms.Message;
028
029/**
030 * An {@link ItemReader} for JMS using a {@link JmsTemplate}. The template
031 * should have a default destination, which will be used to provide items in
032 * {@link #read()}.<br>
033 * <br>
034 * 
035 * The implementation is thread-safe after its properties are set (normal
036 * singleton behavior).
037 * 
038 * @author Dave Syer
039 * 
040 */
041public class JmsItemReader<T> implements ItemReader<T>, InitializingBean {
042
043        protected Log logger = LogFactory.getLog(getClass());
044
045        protected Class<? extends T> itemType;
046
047        protected JmsOperations jmsTemplate;
048
049        /**
050         * Setter for JMS template.
051         * 
052         * @param jmsTemplate a {@link JmsOperations} instance
053         */
054        public void setJmsTemplate(JmsOperations jmsTemplate) {
055                this.jmsTemplate = jmsTemplate;
056                if (jmsTemplate instanceof JmsTemplate) {
057                        JmsTemplate template = (JmsTemplate) jmsTemplate;
058                        Assert.isTrue(template.getReceiveTimeout() != JmsTemplate.RECEIVE_TIMEOUT_INDEFINITE_WAIT,
059                                        "JmsTemplate must have a receive timeout!");
060                        Assert.isTrue(template.getDefaultDestination() != null || template.getDefaultDestinationName() != null,
061                                        "JmsTemplate must have a defaultDestination or defaultDestinationName!");
062                }
063        }
064
065        /**
066         * Set the expected type of incoming message payloads. Set this to
067         * {@link Message} to receive the raw underlying message.
068         * 
069         * @param itemType the java class of the items to be delivered. Typically
070         * the same as the class parameter
071         * 
072         * @throws IllegalStateException if the message payload is of the wrong
073         * type.
074         */
075        public void setItemType(Class<? extends T> itemType) {
076                this.itemType = itemType;
077        }
078
079    @Override
080        @SuppressWarnings("unchecked")
081        public T read() {
082                if (itemType != null && itemType.isAssignableFrom(Message.class)) {
083                        return (T) jmsTemplate.receive();
084                }
085                Object result = jmsTemplate.receiveAndConvert();
086                if (itemType != null && result != null) {
087                        Assert.state(itemType.isAssignableFrom(result.getClass()),
088                                        "Received message payload of wrong type: expected [" + itemType + "]");
089                }
090                return (T) result;
091        }
092
093    @Override
094        public void afterPropertiesSet() throws Exception {
095                Assert.notNull(this.jmsTemplate, "The 'jmsTemplate' is required.");
096        }
097}