View Javadoc

1   /*
2    * $Id: JmsReplyToHandler.java 12172 2008-06-26 14:18:37Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.transport.jms;
12  
13  import org.mule.api.MuleEvent;
14  import org.mule.api.MuleException;
15  import org.mule.api.MuleMessage;
16  import org.mule.api.transformer.Transformer;
17  import org.mule.api.transport.DispatchException;
18  import org.mule.service.AbstractService;
19  import org.mule.transport.DefaultReplyToHandler;
20  import org.mule.transport.jms.i18n.JmsMessages;
21  import org.mule.util.StringMessageUtils;
22  import org.mule.util.StringUtils;
23  
24  import java.util.Iterator;
25  import java.util.List;
26  
27  import javax.jms.Destination;
28  import javax.jms.Message;
29  import javax.jms.MessageProducer;
30  import javax.jms.Queue;
31  import javax.jms.Session;
32  import javax.jms.Topic;
33  
34  /**
35   * <code>JmsReplyToHandler</code> will process a JMS replyTo or hand off to the
36   * default replyTo handler if the replyTo is a URL.
37   * The purpose of this class is to send a result on a ReplyTo destination if one
38   * has been set.
39   * Note that the {@link JmsMessageDispatcher} also contains logic for handling ReplyTo. However,
40   * the dispatcher is responsible attaching the replyTo information to the message and also
41   * receiving on the same replyTo if 'remoteSync' is set. The {@link JmsMessageDispatcher} never
42   * writes to the 'replyTo' destination.
43   */
44  public class JmsReplyToHandler extends DefaultReplyToHandler
45  {
46      private final JmsConnector connector;
47  
48      public JmsReplyToHandler(JmsConnector connector, List transformers)
49      {
50          super(transformers);
51          this.connector = connector;
52      }
53  
54      public void processReplyTo(MuleEvent event, MuleMessage returnMessage, Object replyTo) throws MuleException
55      {
56          Destination replyToDestination = null;
57          MessageProducer replyToProducer = null;
58          Session session = null;
59          try
60          {
61              // now we need to send the response
62              if (replyTo instanceof Destination)
63              {
64                  replyToDestination = (Destination)replyTo;
65              }
66              if (replyToDestination == null)
67              {
68                  super.processReplyTo(event, returnMessage, replyTo);
69                  return;
70              }
71  
72              //This is a work around for JmsTransformers where the current endpoint needs
73              //to be set on the transformer so that a JMSMEssage can be created correctly
74              Class srcType = returnMessage.getPayload().getClass();
75                  for (Iterator iterator = getTransformers().iterator(); iterator.hasNext();)
76              {
77                  Transformer t = (Transformer) iterator.next();
78                  if (t.isSourceTypeSupported(srcType))
79                  {
80                      if (t.getEndpoint() == null)
81                      {
82                          t.setEndpoint(getEndpoint(event, "jms://temporary"));
83                          break;
84                      }
85                  }
86              }
87              returnMessage.applyTransformers(getTransformers());
88              Object payload = returnMessage.getPayload();
89  
90              if (replyToDestination instanceof Topic && replyToDestination instanceof Queue
91                      && connector.getJmsSupport() instanceof Jms102bSupport)
92              {
93                  logger.error(StringMessageUtils.getBoilerPlate("ReplyTo destination implements both Queue and Topic "
94                                                                 + "while complying with JMS 1.0.2b specification. "
95                                                                 + "Please report your application server or JMS vendor name and version "
96                                                                 + "to dev<_at_>mule.codehaus.org or http://mule.mulesource.org/jira"));
97              }
98              
99              final boolean topic = connector.getTopicResolver().isTopic(replyToDestination);
100             session = connector.getSession(false, topic);
101             Message replyToMessage = JmsMessageUtils.toMessage(payload, session);
102 
103             replyToMessage.setJMSReplyTo(null);
104             if (logger.isDebugEnabled())
105             {
106                 logger.debug("Sending jms reply to: " + replyToDestination + "("
107                              + replyToDestination.getClass().getName() + ")");
108             }
109             replyToProducer = connector.getJmsSupport().createProducer(session, replyToDestination, topic);
110 
111             // QoS support
112             MuleMessage eventMsg = event.getMessage();
113             String ttlString = (String)eventMsg.removeProperty(JmsConstants.TIME_TO_LIVE_PROPERTY);
114             String priorityString = (String)eventMsg.removeProperty(JmsConstants.PRIORITY_PROPERTY);
115             String persistentDeliveryString = (String)eventMsg.removeProperty(JmsConstants.PERSISTENT_DELIVERY_PROPERTY);
116             
117             String correlationIDString = (String)eventMsg.getProperty(JmsConstants.JMS_MESSAGE_ID);
118             replyToMessage.setJMSCorrelationID(correlationIDString);
119             
120             if (ttlString == null && priorityString == null && persistentDeliveryString == null)
121             {
122                 connector.getJmsSupport().send(replyToProducer, replyToMessage, topic);
123             }
124             else
125             {
126                 long ttl = Message.DEFAULT_TIME_TO_LIVE;
127                 int priority = Message.DEFAULT_PRIORITY;
128 
129                 if (ttlString != null)
130                 {
131                     ttl = Long.parseLong(ttlString);
132                 }
133                 if (priorityString != null)
134                 {
135                     priority = Integer.parseInt(priorityString);
136                 }
137                 boolean persistent = StringUtils.isNotBlank(persistentDeliveryString)
138                                 ? Boolean.valueOf(persistentDeliveryString).booleanValue()
139                                 : connector.isPersistentDelivery();
140 
141                 connector.getJmsSupport().send(replyToProducer, replyToMessage, persistent, priority, ttl,
142                     topic);
143             }
144 
145             logger.info("Reply Message sent to: " + replyToDestination);
146             ((AbstractService) event.getService()).getStatistics().incSentReplyToEvent();
147         }
148         catch (Exception e)
149         {
150             throw new DispatchException(
151                 JmsMessages.failedToCreateAndDispatchResponse(replyToDestination), returnMessage, null, e);
152         }
153         finally
154         {
155             connector.closeQuietly(replyToProducer);
156             connector.closeQuietly(session);
157         }
158     }
159 }