View Javadoc
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.quartz.jobs;
8   
9   import org.mule.api.MuleContext;
10  import org.mule.api.MuleMessage;
11  import org.mule.api.ThreadSafeAccess;
12  import org.mule.api.config.MuleProperties;
13  import org.mule.api.endpoint.EndpointBuilder;
14  import org.mule.api.endpoint.InboundEndpoint;
15  import org.mule.api.transaction.Transaction;
16  import org.mule.api.transaction.TransactionCallback;
17  import org.mule.api.transport.PropertyScope;
18  import org.mule.module.client.MuleClient;
19  import org.mule.transaction.MuleTransactionConfig;
20  import org.mule.transaction.TransactionCoordination;
21  import org.mule.transaction.TransactionTemplate;
22  import org.mule.transport.AbstractMessageReceiver;
23  import org.mule.transport.quartz.QuartzConnector;
24  import org.mule.transport.quartz.QuartzMessageReceiver;
25  import org.mule.transport.quartz.i18n.QuartzMessages;
26  
27  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
28  import org.apache.commons.logging.Log;
29  import org.apache.commons.logging.LogFactory;
30  import org.quartz.Job;
31  import org.quartz.JobDataMap;
32  import org.quartz.JobExecutionContext;
33  import org.quartz.JobExecutionException;
34  import org.quartz.SchedulerException;
35  
36  /**
37   * Will receive on an endpoint and dispatch it to the component set via the Receiver information.
38   */
39  public class EndpointPollingJob implements Job
40  {
41      /**
42       * The logger used for this class
43       */
44      protected transient Log logger = LogFactory.getLog(getClass());
45  
46      public void execute(JobExecutionContext jobExecutionContext) throws JobExecutionException
47      {
48          MuleContext muleContext;
49          try
50          {
51              muleContext = (MuleContext)jobExecutionContext.getScheduler().getContext().get(MuleProperties.MULE_CONTEXT_PROPERTY);
52          }
53          catch (SchedulerException e)
54          {
55              throw new JobExecutionException("Failed to retrieve Mulecontext from the Scheduler Context: " + e.getMessage(), e);
56          }
57  
58          final JobDataMap jobDataMap = jobExecutionContext.getJobDetail().getJobDataMap();
59  
60          String receiverKey = (String) jobDataMap.get(QuartzMessageReceiver.QUARTZ_RECEIVER_PROPERTY);
61          if (receiverKey == null)
62          {
63              throw new JobExecutionException(QuartzMessages.receiverNotInJobDataMap().getMessage());
64          }
65  
66          String connectorName = (String) jobDataMap.get(QuartzMessageReceiver.QUARTZ_CONNECTOR_PROPERTY);
67          if (connectorName == null)
68          {
69              throw new JobExecutionException(QuartzMessages.connectorNotInJobDataMap().getMessage());
70          }
71  
72          final QuartzConnector connector = (QuartzConnector) muleContext.getRegistry().lookupConnector(connectorName);
73          if (connector == null)
74          {
75              throw new JobExecutionException(QuartzMessages.noConnectorFound(connectorName).getMessage());
76          }
77  
78          final AbstractMessageReceiver receiver = (AbstractMessageReceiver) connector.lookupReceiver(receiverKey);
79          if (receiver == null)
80          {
81              throw new JobExecutionException(
82                      QuartzMessages.noReceiverInConnector(receiverKey, connectorName).getMessage());
83          }
84  
85  
86          final EndpointPollingJobConfig jobConfig = (EndpointPollingJobConfig) jobDataMap.get(QuartzConnector.PROPERTY_JOB_CONFIG);
87          if (jobConfig == null)
88          {
89              throw new JobExecutionException(
90                      QuartzMessages.missingJobDetail(QuartzConnector.PROPERTY_JOB_CONFIG).getMessage());
91          }
92  
93  
94          try
95          {
96              logger.debug("Attempting to receive event on: " + jobConfig.getEndpointRef());
97              TransactionTemplate<Void> tt;
98              final AtomicBoolean pollGlobalEndpoint = new AtomicBoolean(false);
99  
100             //TODO MULE-5050 work around because the builder is no longer idempotent, we now cache the endpoint instance
101             InboundEndpoint endpoint = muleContext.getRegistry().lookupObject(jobConfig.getEndpointRef() + ".quartz-job");
102             if(endpoint==null)
103             {
104                 final EndpointBuilder epBuilder = muleContext.getRegistry().lookupEndpointBuilder(jobConfig.getEndpointRef());
105                 pollGlobalEndpoint.set(epBuilder != null);
106 
107                 if (pollGlobalEndpoint.get())
108                 {
109                     // referencing a global endpoint, fetch configuration from it
110                     endpoint = epBuilder.buildInboundEndpoint();
111 
112                     //TODO MULE-5050 work around because the builder is no longer idempotent, we now cache the endpoint instance
113                     muleContext.getRegistry().registerObject(jobConfig.getEndpointRef() + ".quartz-job", endpoint);
114                     tt = new TransactionTemplate<Void>(endpoint.getTransactionConfig(), muleContext);
115                 }
116                 else
117                 {
118                     // a simple inline endpoint
119                     tt = new TransactionTemplate<Void>(new MuleTransactionConfig(), muleContext);
120                 }
121             }
122             else
123             {
124                 tt = new TransactionTemplate<Void>(endpoint.getTransactionConfig(), muleContext);
125             }
126 
127 
128             final InboundEndpoint finalEndpoint = endpoint;
129             TransactionCallback<Void> cb = new TransactionCallback<Void>()
130             {
131                 public Void doInTransaction() throws Exception
132                 {
133                     Transaction tx = TransactionCoordination.getInstance().getTransaction();
134                     if (tx != null)
135                     {
136                         tx.begin();
137                     }
138 
139                     MuleMessage result = null;
140                     if (pollGlobalEndpoint.get())
141                     {
142                         result = finalEndpoint.getConnector().request(finalEndpoint, jobConfig.getTimeout());
143                     }
144                     else
145                     {
146                         MuleClient client = new MuleClient(connector.getMuleContext());
147                         result = client.request(jobConfig.getEndpointRef(), jobConfig.getTimeout());
148                     }
149 
150                     if (result != null)
151                     {
152                         if (logger.isDebugEnabled())
153                         {
154                             logger.debug("Received event on: " + jobConfig.getEndpointRef());
155                         }
156                         if (pollGlobalEndpoint.get())
157                         {
158                             result.applyTransformers(null, finalEndpoint.getTransformers());
159                         }
160 
161                         //we need to do this because
162                         result = (MuleMessage) ((ThreadSafeAccess) result).newThreadCopy();
163 
164                         //Add the context properties to the message.
165                         result.addProperties(jobDataMap, PropertyScope.INVOCATION);
166 
167                         receiver.routeMessage(result);
168                     }
169                     // nowhere to return
170                     return null;
171                 }
172             };
173 
174             tt.execute(cb);
175         }
176         catch (RuntimeException rex)
177         {
178             // rethrow
179             throw rex;
180         }
181         catch (Exception e)
182         {
183             throw new JobExecutionException(e);
184         }
185     }
186 }