001 /**
002 *
003 * Copyright 2004 Protique Ltd
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.codehaus.activesoap.transport.jms;
019
020 import org.apache.commons.logging.Log;
021 import org.apache.commons.logging.LogFactory;
022 import org.codehaus.activesoap.SoapService;
023
024 import javax.jms.Destination;
025 import javax.jms.JMSException;
026 import javax.jms.Message;
027 import javax.jms.MessageListener;
028 import javax.jms.MessageProducer;
029 import javax.jms.Session;
030 import javax.jms.TextMessage;
031 import java.io.PrintWriter;
032 import java.io.StringReader;
033 import java.io.StringWriter;
034
035 /**
036 * A SOAP endpoint which listens to JMS messages, processes them with the SOAP stack
037 * and then sends the response to a new destination or replies to the inbound JMSReployTo destination.
038 *
039 * @version $Revision: 1.2 $
040 */
041 public class SoapEndpointMessageListener implements MessageListener {
042 private static final Log log = LogFactory.getLog(SoapEndpointMessageListener.class);
043
044 private SoapService soapService;
045 private Session session;
046 private MessageProducer producer;
047 private Destination deadLetterQueue;
048 private Destination replyToDestination;
049
050 public SoapEndpointMessageListener(SoapService soapService, Session session, MessageProducer producer, Destination deadLetterQueue) {
051 this.soapService = soapService;
052 this.session = session;
053 this.producer = producer;
054 this.deadLetterQueue = deadLetterQueue;
055 }
056
057 public void onMessage(Message message) {
058 if (message instanceof TextMessage) {
059 try {
060 onTextMessage((TextMessage) message);
061 }
062 catch (Exception e) {
063 onException(e, message);
064 }
065 }
066 else {
067 sendToDeadLetterQueue("Expected TextMessage", message);
068 }
069 }
070
071 // Properties
072 //-------------------------------------------------------------------------
073 public SoapService getSoapService() {
074 return soapService;
075 }
076
077 public void setSoapService(SoapService soapService) {
078 this.soapService = soapService;
079 }
080
081 public Destination getDeadLetterQueue() {
082 return deadLetterQueue;
083 }
084
085 public void setDeadLetterQueue(Destination deadLetterQueue) {
086 this.deadLetterQueue = deadLetterQueue;
087 }
088
089 public MessageProducer getProducer() {
090 return producer;
091 }
092
093 public void setProducer(MessageProducer producer) {
094 this.producer = producer;
095 }
096
097 public Destination getReplyToDestination() {
098 return replyToDestination;
099 }
100
101 public void setReplyToDestination(Destination replyToDestination) {
102 this.replyToDestination = replyToDestination;
103 }
104
105 public Session getSession() {
106 return session;
107 }
108
109 public void setSession(Session session) {
110 this.session = session;
111 }
112
113
114 // Implementation methods
115 //-------------------------------------------------------------------------
116 protected void onTextMessage(TextMessage message) throws Exception {
117 StringWriter writer = new StringWriter();
118 soapService.invoke(new StringReader(message.getText()), writer);
119 TextMessage response = session.createTextMessage(writer.toString());
120 Destination destination = findReplyToDestination(message);
121 producer.send(destination, response);
122 }
123
124 protected Destination findReplyToDestination(TextMessage message) throws JMSException {
125 Destination answer = message.getJMSReplyTo();
126 if (answer == null) {
127 answer = getReplyToDestination();
128 if (answer == null) {
129 throw new JMSException("No JMSReployTo destination on the message or reployToDestination property available");
130 }
131 }
132 return answer;
133 }
134
135 protected void onException(Exception reason, Message message) {
136 checkValidDeadLetterQueue(reason.toString(), message);
137 try {
138 Message response = createDuplicateMessage(message);
139 response.setStringProperty("reason", reason.getMessage());
140 StringWriter buffer = new StringWriter();
141 reason.printStackTrace(new PrintWriter(buffer));
142 response.setStringProperty("stackTrace", buffer.toString());
143 producer.send(deadLetterQueue, response);
144 }
145 catch (JMSException e) {
146 log.error("Error sending to deadLetterQueue. Reason: " + reason + ". Exception: " + e + " message: " + message, e);
147 }
148 }
149
150 protected void sendToDeadLetterQueue(String reason, Message message) {
151 checkValidDeadLetterQueue(reason, message);
152 try {
153 Message response = createDuplicateMessage(message);
154 response.setStringProperty("reason", reason);
155 producer.send(deadLetterQueue, response);
156 }
157 catch (JMSException e) {
158 log.error("Error sending to deadLetterQueue. Reason: " + reason + ". Exception: " + e + " message: " + message, e);
159 }
160 }
161
162 protected Message createDuplicateMessage(Message message) throws JMSException {
163 return JMSUtils.createDuplicateMessage(session, message);
164 }
165
166 protected void checkValidDeadLetterQueue(String reason, Message message) {
167 if (deadLetterQueue == null) {
168 log.error("Cannot send message to deadLetterQueue as no destination configured. Reason for failure: " + reason + " message: " + message);
169 throw new RuntimeException("No dead letter queue available");
170 }
171 }
172 }