View Javadoc

1   /*
2    * $Id: SedaService.java 20531 2010-12-08 21:34:21Z dzapata $
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.model.seda;
12  
13  import org.mule.api.MuleContext;
14  import org.mule.api.MuleException;
15  import org.mule.api.config.MuleConfiguration;
16  import org.mule.api.config.ThreadingProfile;
17  import org.mule.api.context.WorkManager;
18  import org.mule.api.context.WorkManagerSource;
19  import org.mule.api.lifecycle.InitialisationException;
20  import org.mule.api.lifecycle.LifecycleException;
21  import org.mule.api.processor.MessageProcessor;
22  import org.mule.api.processor.MessageProcessorChainBuilder;
23  import org.mule.config.ChainedThreadingProfile;
24  import org.mule.config.QueueProfile;
25  import org.mule.config.i18n.CoreMessages;
26  import org.mule.config.i18n.MessageFactory;
27  import org.mule.interceptor.ProcessingTimeInterceptor;
28  import org.mule.lifecycle.processor.ProcessIfStartedWaitIfSyncPausedMessageProcessor;
29  import org.mule.management.stats.ServiceStatistics;
30  import org.mule.processor.SedaStageInterceptingMessageProcessor;
31  import org.mule.service.AbstractService;
32  import org.mule.service.processor.ServiceInternalMessageProcessor;
33  import org.mule.service.processor.ServiceLoggingMessageProcessor;
34  import org.mule.service.processor.ServiceOutboundMessageProcessor;
35  import org.mule.service.processor.ServiceOutboundStatisticsMessageProcessor;
36  import org.mule.service.processor.ServiceSetEventRequestContextMessageProcessor;
37  import org.mule.service.processor.ServiceStatisticsMessageProcessor;
38  import org.mule.util.concurrent.ThreadNameHelper;
39  
40  /**
41   * A Seda service runs inside a Seda Model and is responsible for managing a Seda
42   * Queue and thread pool for a Mule sevice service. In Seda terms this is equivilent
43   * to a stage.
44   */
45  public class SedaService extends AbstractService
46  {
47      /**
48       * Serial version/
49       */
50      private static final long serialVersionUID = 7711976708670893015L;
51  
52      /**
53       * The time out used for taking from the Seda Queue.
54       */
55      protected Integer queueTimeout;
56  
57      /**
58       * The threading profile to use for this service. If this is not set a default
59       * will be provided by the server
60       */
61      protected ThreadingProfile threadingProfile;
62  
63      /**
64       * The queue profile to use for this service. If this is not set a default will
65       * be provided by the server
66       */
67      protected QueueProfile queueProfile;
68  
69      protected WorkManager workManager;
70  
71      public SedaService(MuleContext muleContext)
72      {
73          super(muleContext);
74      }
75  
76      @Override
77      protected MessageProcessor getServiceStartedAssertingMessageProcessor()
78      {
79          return new ProcessIfStartedWaitIfSyncPausedMessageProcessor(this, lifecycleManager.getState());
80      }
81  
82      protected void addMessageProcessors(MessageProcessorChainBuilder builder)
83      {
84          builder.chain(new ProcessingTimeInterceptor(null, this));
85          builder.chain(new ServiceLoggingMessageProcessor(this));
86          builder.chain(new ServiceStatisticsMessageProcessor(this));
87          builder.chain(new ServiceSetEventRequestContextMessageProcessor());
88          if (getThreadingProfile().isDoThreading())
89          {
90              builder.chain(new SedaStageInterceptingMessageProcessor(getName(), queueProfile, queueTimeout,
91                  new WorkManagerSource()
92                  {
93                      public WorkManager getWorkManager() throws MuleException
94                      {
95                          return workManager;
96                      }
97                  }, lifecycleManager.getState(), stats, muleContext));
98          }
99          builder.chain(new ServiceInternalMessageProcessor(this));
100         if (asyncReplyMessageSource.getEndpoints().size() > 0)
101         {
102             builder.chain(createAsyncReplyProcessor());
103         }
104         builder.chain(new ServiceOutboundMessageProcessor(this));
105         builder.chain(new ServiceOutboundStatisticsMessageProcessor(this));
106         builder.chain(outboundRouter);
107     }
108 
109     /**
110      * Initialise the service. The service will first create a Mule component from
111      * the Service and then initialise a pool based on the attributes in the Service.
112      * 
113      * @throws org.mule.api.lifecycle.InitialisationException if the service fails to
114      *             initialise
115      */
116     @Override
117     protected synchronized void doInitialise() throws InitialisationException
118     {
119         if (threadingProfile == null)
120         {
121             threadingProfile = muleContext.getDefaultServiceThreadingProfile();
122         }
123         // Create thread pool
124         // (Add one to maximum number of active threads to account for the service
125         // work item that is running continuously and polling the SEDA queue.)
126         ChainedThreadingProfile threadingProfile = new ChainedThreadingProfile(this.threadingProfile);
127         threadingProfile.setMuleContext(muleContext);
128         threadingProfile.setMaxThreadsActive(threadingProfile.getMaxThreadsActive() + 1);
129         // TODO it would be nicer if the shutdown value was encapsulated in the
130         // Threading profile, but it is more difficult than it seems
131 
132         final MuleConfiguration config = muleContext.getConfiguration();
133         final String threadPrefix = ThreadNameHelper.sedaService(muleContext, getName());
134         workManager = threadingProfile.createWorkManager(threadPrefix, config.getShutdownTimeout());
135 
136         if (queueProfile == null && model != null)
137         {
138             queueProfile = ((SedaModel) model).getQueueProfile();
139         }
140         if (queueTimeout == null && model != null)
141         {
142             setQueueTimeout(((SedaModel) model).getQueueTimeout());
143         }
144 
145         try
146         {
147             if (name == null)
148             {
149                 throw new InitialisationException(
150                     MessageFactory.createStaticMessage("Service has no name to identify it"), this);
151             }
152         }
153         catch (Throwable e)
154         {
155             throw new InitialisationException(CoreMessages.objectFailedToInitialise("Service Queue"), e, this);
156         }
157         super.doInitialise();
158     }
159 
160     @Override
161     protected void doStart() throws MuleException
162     {
163         try
164         {
165             workManager.start();
166         }
167         catch (Exception e)
168         {
169             throw new LifecycleException(CoreMessages.failedToStart("Service: " + getName()), e, this);
170         }
171         super.doStart();
172     }
173 
174     @Override
175     protected void doStop() throws MuleException
176     {
177         super.doStop();
178         workManager.dispose();
179     }
180 
181     @Override
182     protected void doForceStop() throws MuleException
183     {
184         doStop();
185     }
186 
187     @Override
188     protected void doDispose()
189     {
190         super.doDispose();
191         if (workManager != null)
192         {
193             workManager.dispose();
194         }
195     }
196 
197     @Override
198     protected ServiceStatistics createStatistics()
199     {
200         return new ServiceStatistics(getName(), threadingProfile.getMaxThreadsActive());
201     }
202 
203     public QueueProfile getQueueProfile()
204     {
205         return queueProfile;
206     }
207 
208     public void setQueueProfile(QueueProfile queueProfile)
209     {
210         this.queueProfile = queueProfile;
211     }
212 
213     public Integer getQueueTimeout()
214     {
215         return queueTimeout;
216     }
217 
218     public void setQueueTimeout(Integer queueTimeout)
219     {
220         this.queueTimeout = queueTimeout;
221     }
222 
223     public ThreadingProfile getThreadingProfile()
224     {
225         return threadingProfile;
226     }
227 
228     public void setThreadingProfile(ThreadingProfile threadingProfile)
229     {
230         this.threadingProfile = threadingProfile;
231     }
232 
233 }