1   /***
2    * 
3    * Copyright 2005 LogicBlaze, Inc.
4    * 
5    * Licensed under the Apache License, Version 2.0 (the "License"); 
6    * you may not use this file except in compliance with the License. 
7    * You may obtain a copy of the License at 
8    * 
9    * http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS, 
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
14   * See the License for the specific language governing permissions and 
15   * limitations under the License. 
16   * 
17   **/
18  package org.jencks;
19  
20  import javax.jms.Destination;
21  import javax.jms.JMSException;
22  import javax.jms.Message;
23  import javax.jms.MessageConsumer;
24  import javax.jms.MessageProducer;
25  import javax.jms.Session;
26  import javax.jms.TemporaryQueue;
27  import javax.jms.TemporaryTopic;
28  
29  /***
30   * A helper class for performing remote method invocations over JMS.
31   * This class is a polymorphic version of the {@link javax.jms.QueueRequestor} and {@link javax.jms.TopicRequestor}
32   * that ship with the JMS API which take advantage of the polymorphism of JMS 1.1 and which also supports timeouts.
33   *
34   * @version $Revision: 1.1.1.1 $
35   */
36  public class Requestor {
37      private Session session;
38      private Destination temporaryDestination;
39      private MessageProducer sender;
40      private MessageConsumer receiver;
41      private long maximumTimeout = 20000L;
42  
43  
44      /***
45       * Constructor for the <CODE>Requestor</CODE> class.
46       * <p/>
47       * <P>This implementation assumes the session parameter to be non-transacted,
48       * with a delivery mode of either <CODE>AUTO_ACKNOWLEDGE</CODE> or
49       * <CODE>DUPS_OK_ACKNOWLEDGE</CODE>.
50       *
51       * @param session     the <CODE>Session</CODE> the queue belongs to
52       * @param destination the destination to perform the request/reply call on
53       * @throws javax.jms.JMSException if the JMS provider fails to create the
54       *                                <CODE>Requestor</CODE> due to some internal
55       *                                error.
56       * @throws javax.jms.InvalidDestinationException
57       *                                if an invalid queue is specified.
58       */
59      public Requestor(Session session, Destination destination) throws JMSException {
60          this.session = session;
61          temporaryDestination = createTemporaryDestination(session);
62          sender = session.createProducer(destination);
63          receiver = session.createConsumer(temporaryDestination);
64      }
65  
66  
67      /***
68       * Sends a request and waits for a reply. The temporary queue is used for
69       * the <CODE>JMSReplyTo</CODE> destination, and only one reply per request
70       * is expected.
71       *
72       * @param message the message to send
73       * @return the reply message
74       * @throws javax.jms.JMSException if the JMS provider fails to complete the
75       *                                request due to some internal error.
76       */
77      public Message request(Message message) throws JMSException {
78          message.setJMSReplyTo(temporaryDestination);
79          sender.send(message);
80          long timeout = getMaximumTimeout();
81          if (timeout > 0) {
82              return receiver.receive(timeout);
83          }
84          else {
85              return receiver.receive();
86          }
87      }
88  
89  
90      /***
91       * Sends a request and waits for a reply up to a maximum timeout. The temporary queue is used for
92       * the <CODE>JMSReplyTo</CODE> destination, and only one reply per request
93       * is expected.
94       *
95       * @param message the message to send
96       * @return the reply message
97       * @throws javax.jms.JMSException if the JMS provider fails to complete the
98       *                                request due to some internal error.
99       */
100     public Message request(Message message, long timeout) throws JMSException {
101         message.setJMSReplyTo(temporaryDestination);
102         sender.send(message);
103         return receiver.receive(timeout);
104     }
105 
106 
107     /***
108      * Closes the <CODE>Requestor</CODE> and its session.
109      * <p/>
110      * <P>Since a provider may allocate some resources on behalf of a
111      * <CODE>Requestor</CODE> outside the Java virtual machine, clients
112      * should close them when they
113      * are not needed. Relying on garbage collection to eventually reclaim
114      * these resources may not be timely enough.
115      * <p/>
116      * <P>Note that this method closes the <CODE>Session</CODE> object
117      * passed to the <CODE>Requestor</CODE> constructor.
118      *
119      * @throws javax.jms.JMSException if the JMS provider fails to close the
120      *                                <CODE>Requestor</CODE> due to some internal
121      *                                error.
122      */
123     public void close() throws JMSException {
124         // producer and consumer created by constructor are implicitly closed.
125         session.close();
126         if (temporaryDestination instanceof TemporaryQueue) {
127             ((TemporaryQueue) temporaryDestination).delete();
128         }
129         else if (temporaryDestination instanceof TemporaryTopic) {
130             ((TemporaryTopic) temporaryDestination).delete();
131         }
132     }
133 
134     public long getMaximumTimeout() {
135         return maximumTimeout;
136     }
137 
138     /***
139      * Sets the maximum default timeout used for remote requests. If set to <= 0 then
140      * the timeout is ignored.
141      *
142      * @param maximumTimeout
143      */
144     public void setMaximumTimeout(long maximumTimeout) {
145         this.maximumTimeout = maximumTimeout;
146     }
147 
148     protected TemporaryQueue createTemporaryDestination(Session session) throws JMSException {
149         return session.createTemporaryQueue();
150     }
151 }