001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. 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 package org.apache.camel.component.jms;
018
019 import javax.jms.Connection;
020
021 import org.apache.camel.FailedToCreateConsumerException;
022 import org.apache.camel.Processor;
023 import org.apache.camel.SuspendableService;
024 import org.apache.camel.impl.DefaultConsumer;
025 import org.springframework.jms.listener.AbstractMessageListenerContainer;
026 import org.springframework.jms.support.JmsUtils;
027
028 /**
029 * A {@link org.apache.camel.Consumer} which uses Spring's {@link AbstractMessageListenerContainer} implementations to consume JMS messages
030 *
031 * @version $Revision: 16521 $
032 */
033 public class JmsConsumer extends DefaultConsumer implements SuspendableService {
034 private AbstractMessageListenerContainer listenerContainer;
035 private EndpointMessageListener messageListener;
036 private boolean initialized;
037 private boolean suspended;
038
039 public JmsConsumer(JmsEndpoint endpoint, Processor processor, AbstractMessageListenerContainer listenerContainer) {
040 super(endpoint, processor);
041 this.listenerContainer = listenerContainer;
042 this.listenerContainer.setMessageListener(getEndpointMessageListener());
043 }
044
045 public JmsEndpoint getEndpoint() {
046 return (JmsEndpoint) super.getEndpoint();
047 }
048
049 public AbstractMessageListenerContainer getListenerContainer() {
050 if (listenerContainer == null) {
051 createMessageListenerContainer();
052 }
053 return listenerContainer;
054 }
055
056 public EndpointMessageListener getEndpointMessageListener() {
057 if (messageListener == null) {
058 createMessageListener(getEndpoint(), getProcessor());
059 }
060 return messageListener;
061 }
062
063 protected void createMessageListener(JmsEndpoint endpoint, Processor processor) {
064 messageListener = new EndpointMessageListener(endpoint, processor);
065 messageListener.setBinding(endpoint.getBinding());
066 }
067
068 protected void createMessageListenerContainer() {
069 listenerContainer = getEndpoint().createMessageListenerContainer();
070 getEndpoint().configureListenerContainer(listenerContainer);
071 listenerContainer.setMessageListener(getEndpointMessageListener());
072 }
073
074 /**
075 * Starts the JMS listener container
076 * <p/>
077 * Can be used to start this consumer later if it was configured to not auto startup.
078 */
079 public void startListenerContainer() {
080 listenerContainer.start();
081 }
082
083 /**
084 * Pre tests the connection before starting the listening.
085 * <p/>
086 * In case of connection failure the exception is thrown which prevents Camel from starting.
087 *
088 * @throws FailedToCreateConsumerException is thrown if testing the connection failed
089 */
090 protected void testConnectionOnStartup() throws FailedToCreateConsumerException {
091 try {
092 if (log.isDebugEnabled()) {
093 log.debug("Testing JMS Connection on startup for destination: " + getDestinationName());
094 }
095 Connection con = listenerContainer.getConnectionFactory().createConnection();
096 JmsUtils.closeConnection(con);
097
098 log.info("Successfully tested JMS Connection on startup for destination: " + getDestinationName());
099 } catch (Exception e) {
100 String msg = "Cannot get JMS Connection on startup for destination " + getDestinationName();
101 throw new FailedToCreateConsumerException(getEndpoint(), msg, e);
102 }
103 }
104
105 @Override
106 protected void doStart() throws Exception {
107 super.doStart();
108
109 // create listener container
110 if (listenerContainer == null) {
111 createMessageListenerContainer();
112 }
113
114 listenerContainer.afterPropertiesSet();
115
116 // only start listener if auto start is enabled or we are explicit invoking start later
117 if (initialized || getEndpoint().isAutoStartup()) {
118 // should we pre test connections before starting?
119 if (getEndpoint().isTestConnectionOnStartup()) {
120 testConnectionOnStartup();
121 }
122 startListenerContainer();
123 }
124
125 // mark as initialized for the first time
126 initialized = true;
127 }
128
129 @Override
130 protected void doStop() throws Exception {
131 listenerContainer.stop();
132 listenerContainer.destroy();
133
134 // null container and listener so they are fully re created if this consumer is restarted
135 // then we will use updated configuration from jms endpoint that may have been managed using JMX
136 listenerContainer = null;
137 messageListener = null;
138 super.doStop();
139 }
140
141 public void suspend() {
142 if (listenerContainer != null) {
143 listenerContainer.stop();
144 suspended = true;
145 }
146 }
147
148 public void resume() {
149 if (listenerContainer != null) {
150 startListenerContainer();
151 suspended = false;
152 }
153 }
154
155 public boolean isSuspended() {
156 return suspended;
157 }
158
159 private String getDestinationName() {
160 if (listenerContainer.getDestination() != null) {
161 return listenerContainer.getDestination().toString();
162 } else {
163 return listenerContainer.getDestinationName();
164 }
165 }
166
167
168 }