View Javadoc

1   /*
2    * $Id: SedaService.java 20088 2010-11-05 16:51:41Z aperepel $
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.config.ChainedThreadingProfile;
23  import org.mule.config.QueueProfile;
24  import org.mule.config.i18n.CoreMessages;
25  import org.mule.config.i18n.MessageFactory;
26  import org.mule.lifecycle.processor.ProcessIfStartedWaitIfSyncPausedMessageProcessor;
27  import org.mule.management.stats.ServiceStatistics;
28  import org.mule.processor.SedaStageInterceptingMessageProcessor;
29  import org.mule.processor.builder.InterceptingChainMessageProcessorBuilder;
30  import org.mule.service.AbstractService;
31  import org.mule.service.processor.ServiceInternalMessageProcessor;
32  import org.mule.service.processor.ServiceLoggingMessageObserver;
33  import org.mule.service.processor.ServiceOutboundMessageProcessor;
34  import org.mule.service.processor.ServiceOutboundStatisticsObserver;
35  import org.mule.service.processor.ServiceSetEventRequestContextMessageObserver;
36  import org.mule.service.processor.ServiceStatisticsMessageObserver;
37  
38  /**
39   * A Seda service runs inside a Seda Model and is responsible for managing a Seda
40   * Queue and thread pool for a Mule sevice service. In Seda terms this is equivilent
41   * to a stage.
42   */
43  public class SedaService extends AbstractService
44  {
45      /**
46       * Serial version/
47       */
48      private static final long serialVersionUID = 7711976708670893015L;
49  
50      /**
51       * The time out used for taking from the Seda Queue.
52       */
53      protected Integer queueTimeout;
54  
55      /**
56       * The threading profile to use for this service. If this is not set a default
57       * will be provided by the server
58       */
59      protected ThreadingProfile threadingProfile;
60  
61      /**
62       * The queue profile to use for this service. If this is not set a default will
63       * be provided by the server
64       */
65      protected QueueProfile queueProfile;
66  
67      protected WorkManager workManager;
68  
69      public SedaService(MuleContext muleContext)
70      {
71          super(muleContext);
72      }
73  
74      @Override
75      protected MessageProcessor getServiceStartedAssertingMessageProcessor()
76      {
77          return new ProcessIfStartedWaitIfSyncPausedMessageProcessor(this, lifecycleManager.getState());
78      }
79  
80      protected void addMessageProcessors(InterceptingChainMessageProcessorBuilder builder)
81      {
82          builder.chain(new ServiceLoggingMessageObserver(this));
83          builder.chain(new ServiceStatisticsMessageObserver(this));
84          builder.chain(new ServiceSetEventRequestContextMessageObserver());
85          if (getThreadingProfile().isDoThreading())
86          {
87              builder.chain(new SedaStageInterceptingMessageProcessor(getName(), queueProfile, queueTimeout,
88                  new WorkManagerSource()
89                  {
90                      public WorkManager getWorkManager() throws MuleException
91                      {
92                          return workManager;
93                      }
94                  }, lifecycleManager.getState(), stats, muleContext));
95          }
96          builder.chain(new ServiceInternalMessageProcessor(this));
97          if (asyncReplyMessageSource.getEndpoints().size() > 0)
98          {
99              builder.chain(createAsyncReplyProcessor());
100         }
101         builder.chain(new ServiceOutboundMessageProcessor(this));
102         builder.chain(new ServiceOutboundStatisticsObserver(this));
103         builder.chain(outboundRouter);
104     }
105 
106     /**
107      * Initialise the service. The service will first create a Mule component from
108      * the Service and then initialise a pool based on the attributes in the Service.
109      * 
110      * @throws org.mule.api.lifecycle.InitialisationException if the service fails to
111      *             initialise
112      */
113     @Override
114     protected synchronized void doInitialise() throws InitialisationException
115     {
116         if (threadingProfile == null)
117         {
118             threadingProfile = muleContext.getDefaultServiceThreadingProfile();
119         }
120         // Create thread pool
121         // (Add one to maximum number of active threads to account for the service
122         // work item that is running continuously and polling the SEDA queue.)
123         ChainedThreadingProfile threadingProfile = new ChainedThreadingProfile(this.threadingProfile);
124         threadingProfile.setMuleContext(muleContext);
125         threadingProfile.setMaxThreadsActive(threadingProfile.getMaxThreadsActive() + 1);
126         // TODO it would be nicer if the shutdown value was encapsulated in the
127         // Threading profile, but it is more difficult than it seems
128 
129         final MuleConfiguration config = muleContext.getConfiguration();
130         final boolean containerMode = config.isContainerMode();
131         final String threadPrefix = containerMode
132                 ? String.format("[%s].%s", config.getId(), getName())
133                 : 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 }