001    /**
002     *
003     * Copyright 2005 LogicBlaze, Inc.
004     *
005     * Licensed under the Apache License, Version 2.0 (the "License");
006     * you may not use this file except in compliance with the License.
007     * You may obtain a copy of the License at
008     *
009     * http://www.apache.org/licenses/LICENSE-2.0
010     *
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     *
017     **/
018    package org.logicblaze.lingo.jms;
019    
020    import org.logicblaze.lingo.jms.impl.DefaultJmsProducer;
021    import org.logicblaze.lingo.jms.impl.OneWayRequestor;
022    import org.springframework.beans.factory.DisposableBean;
023    import org.springframework.beans.factory.InitializingBean;
024    import org.springframework.remoting.support.RemoteInvocationResult;
025    
026    import javax.jms.ConnectionFactory;
027    import javax.jms.Destination;
028    import javax.jms.JMSException;
029    import javax.jms.Message;
030    import javax.jms.MessageConsumer;
031    import javax.jms.Session;
032    
033    /**
034     * A JMS MessageListener that exports the specified service bean as a JMS service
035     * endpoint, accessible via a JMS proxy.
036     * <p/>
037     * <p>Note: JMS services exported with this class can be accessed by
038     * any JMS client, as there isn't any special handling involved.
039     *
040     * @author James Strachan
041     * @see JmsProxyFactoryBean
042     */
043    public class JmsServiceExporter extends JmsServiceExporterSupport implements InitializingBean, DisposableBean {
044        private JmsProducer producer;
045        private ConnectionFactory connectionFactory;
046        private Destination destination;
047        private MessageConsumer consumer;
048    
049        public void afterPropertiesSet() throws Exception {
050            if (producer == null) {
051                if (connectionFactory == null) {
052                    throw new IllegalArgumentException("requestor or connectionFactory is required");
053                }
054                else {
055                    producer = DefaultJmsProducer.newInstance(connectionFactory);
056                }
057            }
058            Requestor responseRequestor = getResponseRequestor();
059            if (responseRequestor == null) {
060                setResponseRequestor(new OneWayRequestor(producer, null));
061            }
062    
063            // do we have a destination specified, if so consume
064            if (destination != null) {
065                Session session = producer.getSession();
066                consumer = session.createConsumer(destination);
067                consumer.setMessageListener(this);
068            }
069    
070            super.afterPropertiesSet();
071        }
072    
073        public void destroy() throws Exception {
074            if (consumer != null) {
075                consumer.close();
076            }
077        }
078    
079        public JmsProducer getProducer() {
080            return producer;
081        }
082    
083        public void setProducer(JmsProducer producer) {
084            this.producer = producer;
085        }
086    
087        public ConnectionFactory getConnectionFactory() {
088            return connectionFactory;
089        }
090    
091        /**
092         * Used to create a default {@link JmsProducer} if no producer is explicitly
093         * configured.
094         */
095        public void setConnectionFactory(ConnectionFactory connectionFactory) {
096            this.connectionFactory = connectionFactory;
097        }
098    
099        public Destination getDestination() {
100            return destination;
101        }
102    
103        /**
104         * If specified then the service will be auto-subscribed to this destination
105         */
106        public void setDestination(Destination destination) {
107            this.destination = destination;
108        }
109    
110        /**
111         * Send the given RemoteInvocationResult as a JMS message to the originator
112         *
113         * @param message current HTTP message
114         * @param result  the RemoteInvocationResult object
115         * @throws javax.jms.JMSException if thrown by trying to send the message
116         */
117        protected void writeRemoteInvocationResult(final Message message, final RemoteInvocationResult result) throws JMSException {
118            Message responseMessage = createResponseMessage(producer.getSession(), message, result);
119            producer.getMessageProducer().send(message.getJMSReplyTo(), responseMessage);
120        }
121    
122    }