View Javadoc

1   /*
2    * $Id: AbstractMessageRequester.java 23247 2011-10-24 17:16:56Z mike.schilling $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.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;
12  
13  import org.mule.DefaultMuleMessage;
14  import org.mule.api.MuleException;
15  import org.mule.api.MuleMessage;
16  import org.mule.api.config.MuleProperties;
17  import org.mule.api.context.WorkManager;
18  import org.mule.api.endpoint.InboundEndpoint;
19  import org.mule.api.lifecycle.InitialisationException;
20  import org.mule.api.transformer.Transformer;
21  import org.mule.api.transport.MessageRequester;
22  import org.mule.api.transport.PropertyScope;
23  import org.mule.api.transport.ReceiveException;
24  import org.mule.context.notification.EndpointMessageNotification;
25  
26  import java.util.List;
27  
28  /**
29   * The Message Requester is used to explicitly request messages from a message channel or
30   * resource rather than subscribing to inbound events or polling for messages.
31   * This is often used programatically but will not be used for inbound endpoints
32   * configured on services.
33   */
34  public abstract class AbstractMessageRequester extends AbstractTransportMessageHandler implements MessageRequester
35  {
36      private List<Transformer> defaultInboundTransformers;
37  
38      public AbstractMessageRequester(InboundEndpoint endpoint)
39      {
40          super(endpoint);
41      }
42  
43      @Override
44      protected ConnectableLifecycleManager createLifecycleManager()
45      {
46          return new ConnectableLifecycleManager<MessageRequester>(getRequesterName(), this);
47      }
48  
49      /**
50       * Method used to perform any initialisation work. If a fatal error occurs during
51       * initialisation an <code>InitialisationException</code> should be thrown,
52       * causing the Mule instance to shutdown. If the error is recoverable, say by
53       * retrying to connect, a <code>RecoverableException</code> should be thrown.
54       * There is no guarantee that by throwing a Recoverable exception that the Mule
55       * instance will not shut down.
56       * 
57       * @throws org.mule.api.lifecycle.InitialisationException if a fatal error occurs
58       *             causing the Mule instance to shutdown
59       * @throws org.mule.api.lifecycle.RecoverableException if an error occurs that
60       *             can be recovered from
61       */
62      @Override
63      public final void initialise() throws InitialisationException
64      {
65          defaultInboundTransformers = connector.getDefaultInboundTransformers(endpoint);               
66          super.initialise();
67      }
68  
69      protected String getRequesterName()
70      {
71          return getConnector().getName() + ".requester." + System.identityHashCode(this);
72      }
73  
74      /**
75       * Make a specific request to the underlying transport
76       *
77       * @param timeout the maximum time the operation should block before returning.
78       *            The call should return immediately if there is data available. If
79       *            no data becomes available before the timeout elapses, null will be
80       *            returned
81       * @return the result of the request wrapped in a MuleMessage object. Null will be
82       *         returned if no data was available
83       * @throws Exception if the call to the underlying protocol causes an exception
84       */
85      public final MuleMessage request(long timeout) throws Exception
86      {
87          try
88          {
89              EndpointMessageNotification beginNotification = null;
90              if (connector.isEnableMessageEvents())
91              {
92                  MuleMessage dummyMessage = new DefaultMuleMessage(NullPayload.getInstance(), connector.getMuleContext());
93                  beginNotification = new EndpointMessageNotification(dummyMessage, endpoint, null, EndpointMessageNotification.MESSAGE_REQUEST_BEGIN);
94              }
95              // Make sure we are connected
96              connect();
97              MuleMessage result = null;
98              result = doRequest(timeout);
99              if (result != null)
100             {
101                 String rootId = result.getInboundProperty(MuleProperties.MULE_ROOT_MESSAGE_ID_PROPERTY);
102                 if (rootId != null)
103                 {
104                     result.setMessageRootId(rootId);
105                     result.removeProperty(MuleProperties.MULE_ROOT_MESSAGE_ID_PROPERTY, PropertyScope.INBOUND);
106                 }
107                 if (beginNotification != null)
108                 {
109                     result.propagateRootId(beginNotification.getSource());
110                 }
111                 if (!endpoint.isDisableTransportTransformer())
112                 {
113                     applyInboundTransformers(result);
114                 }
115                 if (beginNotification != null)
116                 {
117                     connector.fireNotification(beginNotification);
118                     connector.fireNotification(new EndpointMessageNotification(result, endpoint, null,
119                         EndpointMessageNotification.MESSAGE_REQUEST_END));
120                 }
121             }
122             return result;
123         }
124         catch (ReceiveException e)
125         {
126             disposeAndLogException();
127             throw e;
128         }
129         catch (Exception e)
130         {
131             disposeAndLogException();
132             throw new ReceiveException(endpoint, timeout, e);
133         }
134     }
135 
136     protected void applyInboundTransformers(MuleMessage message) throws MuleException
137     {
138         message.applyTransformers(null, defaultInboundTransformers);
139     }
140 
141     @Override
142     protected WorkManager getWorkManager() throws MuleException
143     {
144         return connector.getRequesterWorkManager();
145     }
146     
147     public InboundEndpoint getEndpoint()
148     {
149         return (InboundEndpoint) super.getEndpoint();
150     }
151     
152     /**
153      * Make a specific request to the underlying transport
154      *
155      * @param timeout the maximum time the operation should block before returning.
156      *            The call should return immediately if there is data available. If
157      *            no data becomes available before the timeout elapses, null will be
158      *            returned
159      * @return the result of the request wrapped in a MuleMessage object. Null will be
160      *         returned if no data was avaialable
161      * @throws Exception if the call to the underlying protocal cuases an exception
162      */
163     protected abstract MuleMessage doRequest(long timeout) throws Exception;
164 
165 }