1 /*
2 * Copyright (c) MuleSoft, Inc. All rights reserved. http://www.mulesoft.com
3 * The software in this package is published under the terms of the CPAL v1.0
4 * license, a copy of which has been included with this distribution in the
5 * LICENSE.txt file.
6 */
7 package org.mule.transport;
8
9 import org.mule.api.MuleException;
10 import org.mule.api.MuleMessage;
11 import org.mule.api.context.WorkManager;
12 import org.mule.api.endpoint.InboundEndpoint;
13 import org.mule.api.lifecycle.InitialisationException;
14 import org.mule.api.transformer.Transformer;
15 import org.mule.api.transport.MessageRequester;
16 import org.mule.api.transport.ReceiveException;
17 import org.mule.context.notification.EndpointMessageNotification;
18
19 import java.util.List;
20
21 /**
22 * The Message Requester is used to explicitly request messages from a message channel or
23 * resource rather than subscribing to inbound events or polling for messages.
24 * This is often used programatically but will not be used for inbound endpoints
25 * configured on services.
26 */
27 public abstract class AbstractMessageRequester extends AbstractTransportMessageHandler implements MessageRequester
28 {
29 private List<Transformer> defaultInboundTransformers;
30
31 public AbstractMessageRequester(InboundEndpoint endpoint)
32 {
33 super(endpoint);
34 }
35
36 @Override
37 protected ConnectableLifecycleManager createLifecycleManager()
38 {
39 return new ConnectableLifecycleManager<MessageRequester>(getRequesterName(), this);
40 }
41
42 /**
43 * Method used to perform any initialisation work. If a fatal error occurs during
44 * initialisation an <code>InitialisationException</code> should be thrown,
45 * causing the Mule instance to shutdown. If the error is recoverable, say by
46 * retrying to connect, a <code>RecoverableException</code> should be thrown.
47 * There is no guarantee that by throwing a Recoverable exception that the Mule
48 * instance will not shut down.
49 *
50 * @throws org.mule.api.lifecycle.InitialisationException if a fatal error occurs
51 * causing the Mule instance to shutdown
52 * @throws org.mule.api.lifecycle.RecoverableException if an error occurs that
53 * can be recovered from
54 */
55 @Override
56 public final void initialise() throws InitialisationException
57 {
58 defaultInboundTransformers = connector.getDefaultInboundTransformers(endpoint);
59 super.initialise();
60 }
61
62 protected String getRequesterName()
63 {
64 return getConnector().getName() + ".requester." + System.identityHashCode(this);
65 }
66
67 /**
68 * Make a specific request to the underlying transport
69 *
70 * @param timeout the maximum time the operation should block before returning.
71 * The call should return immediately if there is data available. If
72 * no data becomes available before the timeout elapses, null will be
73 * returned
74 * @return the result of the request wrapped in a MuleMessage object. Null will be
75 * returned if no data was available
76 * @throws Exception if the call to the underlying protocol causes an exception
77 */
78 public final MuleMessage request(long timeout) throws Exception
79 {
80 try
81 {
82 // Make sure we are connected
83 connect();
84 MuleMessage result = null;
85 result = doRequest(timeout);
86 if (result != null && !endpoint.isDisableTransportTransformer())
87 {
88 applyInboundTransformers(result);
89 }
90
91 if (result != null && connector.isEnableMessageEvents())
92 {
93 connector.fireNotification(new EndpointMessageNotification(result, endpoint, null,
94 EndpointMessageNotification.MESSAGE_REQUESTED));
95 }
96 return result;
97 }
98 catch (ReceiveException e)
99 {
100 disposeAndLogException();
101 throw e;
102 }
103 catch (Exception e)
104 {
105 disposeAndLogException();
106 throw new ReceiveException(endpoint, timeout, e);
107 }
108 }
109
110 protected void applyInboundTransformers(MuleMessage message) throws MuleException
111 {
112 message.applyTransformers(null, defaultInboundTransformers);
113 }
114
115 @Override
116 protected WorkManager getWorkManager() throws MuleException
117 {
118 return connector.getRequesterWorkManager();
119 }
120
121 public InboundEndpoint getEndpoint()
122 {
123 return (InboundEndpoint) super.getEndpoint();
124 }
125
126 /**
127 * Make a specific request to the underlying transport
128 *
129 * @param timeout the maximum time the operation should block before returning.
130 * The call should return immediately if there is data available. If
131 * no data becomes available before the timeout elapses, null will be
132 * returned
133 * @return the result of the request wrapped in a MuleMessage object. Null will be
134 * returned if no data was avaialable
135 * @throws Exception if the call to the underlying protocal cuases an exception
136 */
137 protected abstract MuleMessage doRequest(long timeout) throws Exception;
138
139 }