Skip to main content

Workflow Server Service

  • 9 minutes to read

The Workflow module that ships with XAF is accompanied by a workflow server service. It is responsible for executing workflow instances based on definitions created via the Workflow module, when appropriate. This topic describes the steps required to configure and deploy the server.

Overview

The server collects active workflow definitions from the database, creates dynamic activities and passes them to a WorkflowServiceHost. The server works by polling the database to regularly perform the following checks.

  1. Workflow definitions stored in the database are rechecked for possible changes. For example, a workflow definition can be deactivated. In this instance, corresponding workflow instances should no longer be executed.
  2. Objects stored in the database are re-checked to see whether or not they match criteria specified in workflow definitions. This is done for each workflow definition with the Object Fits Criteria option enabled.
  3. The server looks for workflow instance execution requests. These requests are created by the StartWorkflowController, which creates them if there is a workflow definition, and which must be performed when an object is created. The StartWorkflowController tracks creation of new objects and creates workflow instance execution requests when necessary. Workflow instance execution requests can also be created manually. See Workflow Design Basics.
  4. The server looks for workflow instance control command requests. These requests are created by the RunningInstanceController in response to an application administrator executing CancelWorkflowInstance, TerminateWorkflowInstance, SuspendWorkflowInstance, and ResumeWorkflowInstance Actions.

Note

  • The Security System is not designed to be used in a Workflow Server. In this environment, security objects will be used simultaneously from different WWF threads, while these objects were not designed for this scenario and the “Cross-thread operation detected” exception may occur. This exception is related to the UnitOfWork class that is not designed to be used in several threads simultaneously and throws this exception when such usage is detected. The ThreadSafeDataLayer is not involved into this scenario and its usage doesn’t help avoid this exception. If you need to detect whether or not your code implemented in an XAF module is being executed in a Worklow Server environment, do not use Security System for this purpose. Instead, you can introduce a static prorerty (e.g. IsWorkflowServer) and initialize it to true from the Workflow Server code. However, you can use Security System together with the Workflow module in a client application with no limitations.
  • The WorkflowInstanceStore class doesn’t support the multiple workflow hosts accessing the same database (for details, see WorkflowOwnershipException Class).

To simplify server creation, XAF ships with a workflow server project template. Note that before deploying it, you must have an application that uses a workflow module and a database with workflow-specific tables. To use the template, right-click your solution in Solution Explorer and select Add | New Project. Choose the DevExpress v23.2 XAF Template Gallery template, specify a meaningful name and press OK. Select Workflow Server Project in the Solution Wizard and press Finish.

Workflow_AddServerProject

This will add a server project into your application. However, before it can be deployed, it must be properly configured.

Basic Configuration

  1. Open the service’s App.config file and note the ConnectionString entry. This connection string points to the database that contains service workflow tables, as well as business class tables for which workflow instances can be executed. Replace this connection string with your application’s database connection string.
  2. Open the WorkflowServerService.cs (WorkflowServerService.vb) file containing a System.ServiceProcess.ServiceBase descendant declaration. In the overridden OnStart method, change the serverApplication.ApplicationName property value to the XafApplication.ApplicationName of the application, whose connection string you have used in the previous step.
  3. Add the required Modules to the serverApplication.Modules collection after the serverApplication.Modules.BeginInit method is called:

    public partial class MySolutionWorkflowService : System.ServiceProcess.ServiceBase {
        // ...
        protected override void OnStart(string[] args) {
            //...
            // The service can only manage workflows for those business classes that are contained in Modules specified by the serverApplication.Modules collection.
            // So, do not forget to add the required Modules to this collection via the serverApplication.Modules.Add method.
            serverApplication.Modules.BeginInit();
            serverApplication.Modules.Add(new SecurityModule());
            serverApplication.Modules.Add(new MySolutionModule());
            //...
        }
    }
    

    Important

    The server application should include all the modules from the client apps (both WinForms and ASP.NET Web Forms). Otherwise, the server will throw the CompatibilityException and fail to start.

  4. Customize the time periods specifying how frequently the server service checks the database.

    Period

    Default Value

    Description

    StartWorkflowListenerService.DelayPeriod

    15 seconds

    Specifies how frequently the server checks the database for objects satisfying the condition for workflow execution.

    StartWorkflowByRequestService.DelayPeriod

    15 seconds

    Specifies how frequently the server checks the database for newly created objects for which a workflow instance should be executed.

    RefreshWorkflowDefinitionsService.DelayPeriod

    15 minutes

    Specifies how frequently the workflow definitions are reloaded from the database.

    WorkflowInstanceStore.RunnableInstancesDetectionPeriod

    30 seconds

    Specifies how frequently the database is checked for suspended workflow instances that should be resumed.

    HostManager.CloseHostTimeout

    TimeSpan.Zero

    Specifies a necessary timeout to close an opened WorkflowServerHost object. When the default value is set to this property, the CommunicationObject.Close() method is used. The CommunicationObject.Close(TimeSpan) method is used when another value is assigned.

    public partial class MySolutionWorkflowService : System.ServiceProcess.ServiceBase {
        // ...
        protected override void OnStart(string[] args) {
            //...
            server.StartWorkflowListenerService.DelayPeriod = TimeSpan.FromSeconds(15);
            server.StartWorkflowByRequestService.DelayPeriod = TimeSpan.FromSeconds(15);
            server.RefreshWorkflowDefinitionsService.DelayPeriod = TimeSpan.FromHours(1);
            server.HostManager.CloseHostTimeout = System.TimeSpan.FromSeconds(20);     
    
            server.CustomizeHost += delegate(object sender, CustomizeHostEventArgs e) {
                e.WorkflowInstanceStoreBehavior.WorkflowInstanceStore.RunnableInstancesDetectionPeriod = 
                    TimeSpan.FromSeconds(15);
                };
            //...
        }
    }
    

    The current Workflow Service implementation is not designed for a scenario when workflow definitions are changed very frequently (every minute), and an updated version should be started in a short amount of time. The refresh operation is executed with the help of the HostManagerActivityProvider class that creates activities from XAML strings by using the AssemblyBuilder class. This approach allows end-users to add runtime activities in the toolbox and reuse these activities as components in the runtime workflow designer. Thus, with each refresh operation, a new assembly is created and loaded into the current AppDomain. This operation requires additional unmanaged memory (about 100Kb per assembly). All the loaded assemblies are unloaded when the entire AppDomain object is unloaded. The HostManagerActivityProvider class does not perform any checks, and always creates a new assembly. That is why the used unmanaged memory grows constantly. To avoid this, set the RefreshWorkflowDefinitionsService.DelayPeriod period to one hour, and manually force the refresh operation when necessary. You can also adjust autorestart for your service. Alternatively, you can implement a custom HostManagerActivityProvider class that does not require additional memory, but does not allow the reuse of runtime activities (see How to: Reduce the Memory Consumption of the Workflow Service).

  5. If you need to perform custom handling of exceptions, change the server.CustomHandleException delegate declaration. By default, the delegate logs an exception and stops the server by setting the e.Handled property to false.

    public partial class MySolutionWorkflowService : System.ServiceProcess.ServiceBase {
        // ...
        protected override void OnStart(string[] args) {
            //...
            server.CustomHandleException += delegate(object sender, _
            DevExpress.ExpressApp.Workflow.ServiceModel.CustomHandleServiceExceptionEventArgs e) {
                Tracing.Tracer.LogError(e.Exception);
                e.Handled = false;
                };
            //...
        }
    }
    

Deploy the Workflow Server

After you have configured and built the service, you are ready to deploy it. Since the workflow server service is a regular .NET service, the deployment steps are the same as for any other .NET service.

  1. Run the Visual Studio Command Prompt. Service installation requires elevated privileges, so you may need to use the Run as administrator option.
  2. Change the current directory to the service executable path and invoke the installutil myservice.exe command, where myservice.exe is the name of your service executable file.
  3. In the command prompt, invoke the services.msc command to open the service management console. Locate your service and start it by right-clicking on it and choosing Start. Alternatively, you can type net start <service_name> in the command prompt. You can copy the service name from the installutil output in the previous step, or open the ProjectInstaller.cs (ProjectInstaller.vb) file and check the serviceInstaller.ServiceName value.

    Important

    Ensure that the database exists and is correctly initialized before running the service. Run the client application in the Debug mode once, or pass its configuration file to the DBUpdater tool (as it is described in the Set Up the Database Connection tutorial) for this purpose.

When you need to update the service, uninstall the previous version first by issuing the installutil myservice.exe /u command. Then install it using the steps described above.

Debug the Workflow Server

Workflow Server is a regular Windows Service. To learn how to debug it, refer to the How to: Debug Windows Service Applications topic in MSDN. If the service could not be started via the net start command, start the Event Viewer application and open the Application log to find out what is the issue. You can also refer to the MSDN topics listed below.

See Also