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.spring.integration;
018
019 import org.apache.camel.Exchange;
020 import org.apache.camel.Processor;
021 import org.apache.camel.impl.DefaultConsumer;
022 import org.apache.camel.spring.SpringCamelContext;
023 import org.apache.camel.util.ObjectHelper;
024 import org.springframework.integration.MessageChannel;
025 import org.springframework.integration.core.MessageHandler;
026 import org.springframework.integration.core.SubscribableChannel;
027 import org.springframework.integration.support.channel.BeanFactoryChannelResolver;
028 import org.springframework.integration.support.channel.ChannelResolver;
029
030 /**
031 * A consumer of exchanges for the Spring Integration
032 * Please specify the inputChannel in the endpoint url for this consumer.
033 * If the message pattern is inOut, the outputChannel property
034 * should be set for the outgoing message.
035 *
036 * @version
037 */
038 public class SpringIntegrationConsumer extends DefaultConsumer implements MessageHandler {
039 private final SpringCamelContext context;
040 private final ChannelResolver channelResolver;
041 private SubscribableChannel inputChannel;
042 private MessageChannel outputChannel;
043
044 public SpringIntegrationConsumer(SpringIntegrationEndpoint endpoint, Processor processor) {
045 super(endpoint, processor);
046 this.context = (SpringCamelContext) endpoint.getCamelContext();
047 this.channelResolver = new BeanFactoryChannelResolver(context.getApplicationContext());
048 }
049
050 @Override
051 public SpringIntegrationEndpoint getEndpoint() {
052 return (SpringIntegrationEndpoint) super.getEndpoint();
053 }
054
055 protected void doStop() throws Exception {
056 inputChannel.unsubscribe(this);
057 super.doStop();
058 }
059
060 protected void doStart() throws Exception {
061 super.doStart();
062
063 if (getEndpoint().getMessageChannel() == null) {
064 String inputChannelName = getEndpoint().getDefaultChannel();
065 if (ObjectHelper.isEmpty(inputChannelName)) {
066 inputChannelName = getEndpoint().getInputChannel();
067 }
068
069 ObjectHelper.notEmpty(inputChannelName, "inputChannelName", getEndpoint());
070 inputChannel = (SubscribableChannel) channelResolver.resolveChannelName(inputChannelName);
071 } else {
072 inputChannel = (SubscribableChannel) getEndpoint().getMessageChannel();
073 }
074
075 if (inputChannel == null) {
076 throw new IllegalArgumentException("Cannot resolve InputChannel on " + getEndpoint());
077 }
078
079 // if we do in-out we need to setup the input channel as well
080 if (getEndpoint().isInOut()) {
081 // we need to setup right inputChannel for further processing
082 ObjectHelper.notEmpty(getEndpoint().getOutputChannel(), "OutputChannel", getEndpoint());
083 outputChannel = channelResolver.resolveChannelName(getEndpoint().getOutputChannel());
084
085 if (outputChannel == null) {
086 throw new IllegalArgumentException("Cannot resolve OutputChannel on " + getEndpoint());
087 }
088 }
089
090 inputChannel.subscribe(this);
091 }
092
093 public void handleMessage(org.springframework.integration.Message<?> siInMessage) {
094 // we received a message from spring integration
095 // wrap that in a Camel Exchange and process it
096 Exchange exchange = getEndpoint().createExchange();
097 exchange.setIn(new SpringIntegrationMessage(siInMessage));
098
099 // process the exchange
100 try {
101 getProcessor().process(exchange);
102 } catch (Exception e) {
103 getExceptionHandler().handleException("Error processing exchange" , exchange, e);
104 return;
105 }
106
107 // reply logic
108 if (getEndpoint().isInOut()) {
109 MessageChannel reply = null;
110
111 // get the output channel from message header
112 Object returnAddress = siInMessage.getHeaders().getReplyChannel();
113 if (returnAddress != null) {
114 if (returnAddress instanceof String) {
115 reply = (MessageChannel) context.getApplicationContext().getBean((String)returnAddress);
116 } else if (returnAddress instanceof MessageChannel) {
117 reply = (MessageChannel) returnAddress;
118 }
119 } else {
120 reply = outputChannel;
121
122 // we want to do in-out so the inputChannel is mandatory (used to receive reply from spring integration)
123 if (reply == null) {
124 throw new IllegalArgumentException("OutputChannel has not been configured on " + getEndpoint());
125 }
126 }
127
128 if (reply == null) {
129 throw new IllegalArgumentException("Cannot resolve ReplyChannel from message: " + siInMessage);
130 }
131
132 // put the message back the outputChannel if we need
133 org.springframework.integration.Message siOutMessage =
134 SpringIntegrationBinding.storeToSpringIntegrationMessage(exchange.getOut());
135
136 // send the message to spring integration
137 if (log.isDebugEnabled()) {
138 log.debug("Sending " + siOutMessage + " to ReplyChannel: " + reply);
139 }
140 reply.send(siOutMessage);
141 }
142 }
143
144 }