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 }