The Problem Solver

Tell me and I will forget
Show me and I will remember
Involve me and I will understand
- Confucius -

Google Ads

This Blog

Syndication

Search

Tags

News





  • View Maurice De Beijer's profile on LinkedIn

Community

Email Notifications

Explore

Archives

January 2011 - Posts

As shown previously it isn’t hard to run Workflow Services on Windows Azure. In fact all we need to do is add a bit of extra configuration and we can work as normal. However normally when I am hosting long running workflows in IIS I always add a SqlWorkflowInstanceStore  to store the workflow state when it is not running so we can survive the inevitable IIS AppDomain restarts. Unfortunately this isn’t quite as straightforward as I had hoped.

 

SQL Azure != SQL Server

The important thing to remember is that SQL Azure might be similar to SQL Server but has different capabilities. Normally you can create a SQL Server database, run 2 SQL scripts provided by the workflow team from Microsoft and use the database as the workflow instance store. The problem here is that SQL Azure doesn’t support a number of features use in the provided SQL scripts. One of these features is the use of allow_page_locks = off in the SqlWorkflowInstanceStoreSchema.sql script used to create the database store. A second not supported is setting the maximum degree of parallelization using option (maxdop 1) in SqlWorkflowInstanceStoreLogic.sql.

The first, allow_page_locks = off, causes SQL Azure to throw errors and has to be removed from the SqlWorkflowInstanceStoreSchema script before it can run. The second, option (maxdop 1), doesn’t cause any errors and is actually the value SQL Azure always uses so there is no problem there. Making the first change is trivial but the problem is that we are now using stored procedures that have not been tested and are not supported. Still when I tried, in a test environment, this seemed to work fine and I have heard similar reports from others.

 

The case of the retrying connection

There is however a second potential problem as SQL Azure behaves different under load. The problem is that executing SQL commands may fail even after a connection has been opened successfully and the official solution it retry executing the command several times. See here for more details.

So far this problem hasn’t surfaced for me but I haven’t used this under heavy load so take care.

 

Adding the SqlWorkflowInstanceStore in Windows Azure
Once the database has been created configuring the SqlWorkflowInstanceStore is really no different from a regular workfow serrvice. Just add the sqlWorkflowInstanceStore element to the <serviceBehaviors><behavior> section with the required connection string and you are good to go. Adding the <workflowIdle> element to unload the workflow as soon as it is idle is also advisable as having multiple web roles is the norm and the next request for the workflow service could equally well be serviced another server.

<system.serviceModel>
  <serviceHostingEnvironment aspNetCompatibilityEnabled="true"
                             multipleSiteBindingsEnabled="true">
  </serviceHostingEnvironment>
  <behaviors>
    <serviceBehaviors>
      <behavior>
        <serviceMetadata httpGetEnabled="true" />
        <serviceDebug includeExceptionDetailInFaults="true" />
        <sqlWorkflowInstanceStore connectionStringName="WorkflowInstanceStore" />
        <workflowIdle timeToUnload="00:00:00" />
      </behavior>
    </serviceBehaviors>
  </behaviors>
</system.serviceModel>

With a connection string section like this:
<connectionStrings>
  <add name="WorkflowInstanceStoreConnectionString"
       connectionString="[[your SQL Azure connection string]]"
       providerName="System.Data.SqlClient" />
</connectionStrings>

 

Conclusion

While it isn’t very hard to do this it is unfortunate that we have to go in a change SQL scripts to get this running and as a result be in a, at least for the moment, not supported scenario. After all hosting workflow services in IIS without using the SqlWorkflowInstanceStore is asking for problems as sooner or later IIS is going to recycle the AppDomain and abort our workflows Sad smile

 

www.TheProblemSolver.nl
www.dotnetevents.nl

Posted by Maurice | 1 comment(s)
Filed under: , , , , ,

Windows Azure might not support the WCF and WF4 hosting parts of Windows AppFabric bit that doesn’t mean you can’t run workflow services on Windows Azure. After all a workflow is just a .NET 4 type and Windows Azure runs the .NET framework. As a result running a workflow service is quite easy once you know how to configure it.

 

The web.config file

The first problem is that the machine web.config of an Azure virtual machine is different than that on a regular machine. As a result, by default, IIS doesn’t know what to do with a WorkflowService type, the base type of a workflow service. On a normal Windows machine with the .NET 4 framework installed there is a <system.xaml.hosting> section in the machine web.config taking care of this. As this is missing on Azure we need to make sure we add this to our web.config.

<?xml version="1.0"?>
<configuration>
  <configSections>
    <sectionGroup name="system.xaml.hosting"
                  type="System.Xaml.Hosting.Configuration.XamlHostingSectionGroup, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35">
      <section name="httpHandlers"
               type="System.Xaml.Hosting.Configuration.XamlHostingSection, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </sectionGroup>
  </configSections>
 
  <system.xaml.hosting>
    <httpHandlers>
      <add xamlRootElementType="System.ServiceModel.Activities.WorkflowService, System.ServiceModel.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
           httpHandlerType="System.ServiceModel.Activities.Activation.ServiceModelActivitiesActivationHandlerAsync, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
      <add xamlRootElementType="System.Activities.Activity, System.Activities, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
           httpHandlerType="System.ServiceModel.Activities.Activation.ServiceModelActivitiesActivationHandlerAsync, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
    </httpHandlers>
  </system.xaml.hosting>
  
  <!-- Remainder config removed -->
 
</configuration>

With this piece of config in place we can go and add a Workflow Service, or a XAMLX file, to the web role and call it just like we can with a local workflow service.

 

Enjoy!

 

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 1 comment(s)

Ken Levy recently interviewed me for CodeCast on the state of Windows Workflow Foundation 4 and the AppFabric for hosting your workflow services. Its episode 99, I wonder what they are planning for episode 100. You can download the episode here or through iTunes.

 

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | with no comments

Een nieuw jaar betekent, zoals gebruikelijk, weer nieuwe plannen. En voor de DotNed gebruikersgroep is een van deze nieuwe plannen om een podcast te gaan maken en publiceren. Deze DotNed Podcasts worden speciaal voor de Nederlandse .NET ontwikkelaar gemaakt en zullen dan ook zo veel mogelijk Nederlandstalig zijn. Het is de bedoeling dat de onderwerpen die we gaan behandelen heel divers zijn, zolang het maar interessant en relevant is voor een .NET ontwikkelaar.

De eerste van deze serie podcasts staat nu online op de website en is hier te vinden. Om het voor de luisteraars zo makkelijk mogelijk te maken hebben we een RSS feed gemaakt zodat nieuwe afleveringen automatisch binnen komen. Voor de gebruikers van iTunes is hier een directe link te vinden en voor de Zune gebruikers wordt nog gewerkt aan een feed. Zodra de Zune link beschikbaar is zal deze op de site komen te staan.

 

Uiteraard zijn we benieuwd naar wat je van de podcast vindt en wat voor onderwerpen je in de toekomst graag wil horen. Speciaal hiervoor hebben we het email adres podcast@dotned.nl in het leven geroepen. Dus laat van je horen als je suggesties of feedback hebt.

 

Website: http://www.dotned.nl/PodCasts.aspx

RSS: http://www.dotned.nl/podcasts/podcasts.xml

iTunes: http://itunes.apple.com/nl/podcast/dotned-podcast/id413467827

Posted by Maurice | with no comments
Filed under: , ,

The WorkflowApplication is a great way to execute your workflows in process. Usually the fact that the WorkflowApplication is asynchronous is a great thing but there are cases when a little more synchronous execution is nice. For example executing a workflow and updating the state of the user interface is much simpler when the WorkflowApplication.Run() doesn’t finish until all work is done.

The key to creating a synchronous WorkflowApplication is using its SynchronizationContext. Normally you set this to SynchronizationContext.Current so everything executes on the current UI thread. However this is still an asynchronous call and the Run doesn’t block.

Take this very simple workflow and its execution output.

var workflow = new Sequence()
{
    Activities = {
        new WriteLine(){ Text="Workflow is running"}
    }
};
 
var app = new WorkflowApplication(workflow);
 
Console.WriteLine("Before WorkflowApplication.Run()");
app.Run();
Console.WriteLine("After WorkflowApplication.Run()");

image

As you can see the Run() didn’t block and the message after the Run() was printed before the message from the workflow.

 

Executing the workflow synchronously

Making this workflow execute in a synchronous fashion is easy and requires only a very small change by setting the SynchronizationContext to a custom implementation.

var workflow = new Sequence()
{
    Activities = {
        new WriteLine(){ Text="Workflow is running"}
    }
};
 
var app = new WorkflowApplication(workflow);
app.SynchronizationContext = new SynchronousSynchronizationContext();
 
Console.WriteLine("Before WorkflowApplication.Run()");
app.Run();
Console.WriteLine("After WorkflowApplication.Run()");

image

The SynchronousSynchronizationContext used is real simple. The workflow internals always call the Post() method to execute work, so all we need to do is just execute the delegate passed with the state passed.

class SynchronousSynchronizationContext : SynchronizationContext
{
    public override void Post(SendOrPostCallback d, object state)
    {
        d(state);
    }
}

Executing an asynchronous workflow

Using this same SynchronousSynchronizationContext  with an asynchronous workflow works just fine. If I add the following simple bookmarked activity to the workflow and execute it I get the following result:

image

The code to execute the workflow is as follows

var workflow = new Sequence()
{
    Activities = {
        new WriteLine(){ Text="Workflow has started"},
        new MyBookmarkedActivity(),
        new WriteLine(){ Text="Workflow is done"}
    }
};
 
var app = new WorkflowApplication(workflow);
app.SynchronizationContext = new SynchronousSynchronizationContext();
app.Idle = e => Console.WriteLine("WorkflowApplication.Idle called");
 
Console.WriteLine("Before WorkflowApplication.Run()");
app.Run();
Console.WriteLine("After WorkflowApplication.Run()");
Console.WriteLine();
Console.WriteLine("Before WorkflowApplication.ResumeBookmark()");
Console.WriteLine("ResumeBookmark: {0}", app.ResumeBookmark("MyBookmark", null));
Console.WriteLine("After WorkflowApplication.ResumeBookmark()");

 

And the bookmarked activity is as follows:

class MyBookmarkedActivity : NativeActivity
{
    protected override bool CanInduceIdle
    {
        get { return true; }
    }
 
    protected override void Execute(NativeActivityContext context)
    {
        Console.WriteLine("Creating bookmark");
        context.CreateBookmark("MyBookmark", BookmarkResumed);
    }
 
    private void BookmarkResumed(NativeActivityContext context, Bookmark bookmark, object value)
    {
        Console.WriteLine("Bookmark resumed");
    }
}

Conclusion

A simple yet effective addition to the workflow runtime for that special case where the asynchronous behavior is not quite what you want but the WorkflowInvoker is not flexible enough

 

Enjoy!

www.TheProblemSolver.nl
Wiki.WindowsWorkflowFoundation.eu

Posted by Maurice | 3 comment(s)
Filed under: , , ,