1 /**
2 * Copyright 2005-2006 the original author or authors.
3 *
4 * Licensed under the Gnu General Pubic License, Version 2.0 (the
5 * "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/gpl-license.php
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the Gnu General Public License for more details.
14 */
15 package org.figure8.join.core.messaging;
16
17 import org.figure8.join.util.LogUtil;
18
19 import org.apache.commons.logging.Log;
20 import org.springframework.beans.factory.DisposableBean;
21 import org.springframework.jms.core.support.JmsGatewaySupport;
22
23 import javax.jms.Session;
24 import javax.jms.Connection;
25 import javax.jms.Destination;
26 import javax.jms.JMSException;
27 import javax.jms.MessageConsumer;
28 import javax.jms.ConnectionFactory;
29 /**
30 * This is a base class for JMS messages consumer implementations, based on Spring
31 * JMS templates. This class defines lifecyle methods (<code>start()</code> and
32 * <code>stop()</code>) that deals by connecting/deconnecting to JMS provider and
33 * listened destination.
34 * <br/>
35 * Subclasses should only have to implement the <code>processMessage()</code>
36 * method where real work has to be done. This last method should not throw any
37 * exception. This means that implementation should handle every errors.
38 * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
39 * @version $Revision: 1.2 $
40 */
41 public class JMSConsumerBeanSpringWrapper extends JmsGatewaySupport
42 implements DisposableBean{
43
44
45
46 /** Commons logger. */
47 protected static Log log = LogUtil.getLog(JMSConsumerBeanSpringWrapper.class);
48
49
50
51
52 /** The message selector when listening to messages */
53 private String selector;
54 /** The JMS destination on which to consume messages */
55 private Destination destination;
56
57 /** Created session for listening to messages */
58 private Session session;
59 /** Created connnection for listening to messages */
60 private Connection connection;
61 /** Created consumer for listening to messages */
62 private MessageConsumer consumer;
63
64 /** Wrapped JMSConsumerBean instance */
65 private JMSConsumerBean consumerBean;
66
67
68
69
70 /** Default constructor. */
71 public JMSConsumerBeanSpringWrapper(){
72 }
73
74
75
76
77 /** @return Message selector expression used when listening to messages */
78 public String getSelector(){
79 return selector;
80 }
81 /** @param selector Message selector expression to use for filtering messages */
82 public void setSelector(String selector){
83 this.selector = selector;
84 }
85
86 /** @return JMS destination whose messages are consumed by this object */
87 public Destination getDestination(){
88 return destination;
89 }
90 /** @param destination JMS destination to consume messages for */
91 public void setDestination(Destination destination){
92 this.destination = destination;
93 }
94
95 /** @return */
96 public JMSConsumerBean getConsumerBean(){
97 return consumerBean;
98 }
99 /** @param consumerBean */
100 public void setConsumerBean(JMSConsumerBean consumerBean){
101 this.consumerBean = consumerBean;
102 }
103
104 /**
105 * Lifecycle method. This method is called after bean properties intilization.
106 * It is responsible for connecting to the JMS provider using the connection
107 * factory injected and register the current bean as a message listener for
108 * the specified JMS destination.
109 * @throws JMSException if connection to provider or registration as a listener
110 * is not possible
111 */
112 public void start() throws JMSException{
113 log.info("Start method called on consumer. Trying to connect JMS provider...");
114 try{
115
116 ConnectionFactory factory = getConnectionFactory();
117 connection = factory.createConnection();
118 connection.start();
119 log.info("Connection is started. Trying to register as a message listener...");
120
121 session = connection.createSession(true, Session.AUTO_ACKNOWLEDGE);
122 consumer = session.createConsumer(destination, selector, false);
123 consumer.setMessageListener(consumerBean);
124 log.info("Start listening messages with selector: " + selector);
125 }
126 catch (JMSException e){
127
128 log.error("Caught a JMSException when trying initialize JMSConsumerBeanSpringWrapper", e);
129 throw e;
130 }
131 }
132
133 /**
134 * Lifecycle method. This method is called on destruction of this beans. It
135 * is responsible for closing and releasing all the resources acquired for
136 * connection and registration as a listener (MessageConsumer, Session and
137 * Connection)
138 * @throws JMSException if closing a resource is not possible
139 */
140 public void stop() throws JMSException{
141 log.info("Stop method called con consumer. Trying to close connected resources...");
142
143 if (consumer != null)
144 consumer.close();
145
146 if (session != null)
147 session.close();
148
149 if (connection != null)
150 connection.close();
151 }
152
153
154
155
156 /**
157 * Invoked by a BeanFactory on destruction of a singleton.
158 * @throws Exception in case of shutdown errors.
159 */
160 public void destroy() throws Exception{
161 log.debug("destroy() called on message consumer. Calling stop() method.");
162 consumerBean.stop();
163 stop();
164 }
165
166
167
168
169 /**
170 * Gets called after population of this instance's bean properties, just call
171 * <code>start()</code> method. Convenience method for testing with Spring.
172 * @throws Exception if initialization fails
173 */
174 protected void initGateway() throws Exception{
175 if (consumerBean == null)
176 throw new IllegalArgumentException("consumerBean is a required property");
177 log.debug("initGateway() called on message consumer. Calling start() method");
178 start();
179 }
180 }