2007-02-27

BPEL-stöd kommer inom kort

I mars kommer en CTP med ett gäng BPEL-aktiviteter för workflow foundation. Detta paket kommer inte helt förvånande att heta BPEL for Windows Workflow Foundation March CTP.

Denna release hanterar version 1.1 av BPEL och den slutgiltiga versionen skall stöda OASIS BPEL 2.0 standard fullt ut.

I verktygslådan kommer det finnas stöd för konvertering mellan XAML->BPEL och BPEL->XAML

Tydligen kommer inte detta att medföra några förändringar i den befintliga runtimen utan detta är en utökning som levereras utanför .NET-framework.

Nästa version av BizTalk kommer att ha samma stöd för BPEL och detta gör att vi i BizTalk får BPEL-stöd i framtiden.

Värt att notera är att så fort BPEL skall användas försvinner en stor del av den rika programmeringsmodell som finns i workflow foundation. Detta kan naturligtvis i många fall vara något bra och vi kan lämna designen av affärsprocesserna till en person som inte är utvecklare.

2007-02-23

Workflows och trådning

Detta är ett intressant ämne och ger stor påverkan i prestanda för en applikation.

Hittils har vi skapat en WorkflowRuntime, startat denna och allt har varit perfekt... men, hur är det irl?

Här är några klasser som är värda att kika närmare på:

DefaultWorkflowSchedulerService
Denna klass används som default och tillåter flera workflowinstanser i trådpoolen, här kan vi styra vissa intressanta delar och exempelvis MaxSimultaneousWorkflows är värd att kika närmare på.

ManualWorkflowSchedulerService
Denna klass ger oss möjlighet att styra trådningen och exempelvis köra en workflowinstans i en egen tråd. Kräver att man manuellt anropar RunWorkflow.

Båda dessa ärver WorkflowSchedulerService som är basen för hur workflows trådas.

Trevlig helg!

2007-02-21

Exempel

I detta exempel skall vi skapa ett flöde med kopplingar till affärslogik och som använder regelmotorn i WF för att avgöra hur flödet skall gå vidare.

1. Skapa ett nytt projekt i Visual Studio av typen Sequential Workflow Console Application.

2. Skapa en klass som heter Bestallning (Kan inte riktigt vänja mig vid tanken på att använda åäö i filnamn, klasser osv)

public class Bestallning

{       

    private int antal;

    private float aPris;

    private string artikelNamn;

 

    public float Summa

    {

        get { return Antal * APris; }           

    }

 

    public int Antal

    {

        get { return antal; }

        set { antal = value; }

    }

 

    public float APris

    {

        get { return aPris; }

        set { aPris = value; }

    }

 

    public string ArtikelNamn

    {

        get { return artikelNamn; }

        set { artikelNamn = value; }

    }

}

 

3. Skapa en klass som heter BestallningsTjanst

Denna klass har flera funktioner

  • Agerar "affärslager"
  • Lagrar våra pågående beställningar
  • Håller vår workflowruntime
  • Startar nya ärenden när en ny beställning registreras
    • Lägg märke till att vi initierar BeställningsId som är en publik property i Workflow1

Som ni ser så genar vi rätt rejält här när det gäller vettig design men det är trots allt ett exempel ;-)

public class BestallningsTjanst

{

    private static int idRaknare = 1;

    private static Dictionary<int, Bestallning> bestallningar = new Dictionary<int, Bestallning>();

    private readonly static WorkflowRuntime workflowRuntime;

 

    static BestallningsTjanst()

    {

        workflowRuntime = new WorkflowRuntime();

        workflowRuntime.StartRuntime();

    }

 

    private static int NyttId()

    {

        return idRaknare++;

    }

 

    public static void LaggBestallning(Bestallning bestallning)

    {

        int nyttId = NyttId();

        lock (bestallningar)

        {

            bestallningar.Add(nyttId, bestallning);

        }

        Dictionary<string, object> parametrar = new Dictionary<string, object>();

        parametrar.Add("BestallningsId", nyttId);

        WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(Workflow1), parametrar);

        instance.Start();

    }

 

    public static Bestallning HamtaBestallning(int id)

    {

        return bestallningar[id];

    }

}

4. Skapa flödet

Start, over, Under är kodaktiviteter som loggar till consolen, koden kommer nedan

KontrolleraSumma är en if-else aktivitet och bilden visar läget där vi skall editera vilkoret för aktivitetens ena ben.

Koden nedan innehåller några riktigt intressanta delar:

  • Den publika propertien BestallningsId som intieras när ärendet startas
  • Den privata propertien bestallning som ger flödet tillgång till den aktuella beställningen som läses upp från "affärslagret".
  • Affärslagret hade naturligtvis kunnat vara en webbtjänst och utnyttjat exemelvis WCF.

public sealed partial class Workflow1: SequentialWorkflowActivity

{

    private int bestallningsId = 0;

 

    private Bestallning bestallning

    {

        get

        {

            return BestallningsTjanst.HamtaBestallning(BestallningsId);

        }

    }

 

    public int BestallningsId

    {

        get { return bestallningsId; }

        set { bestallningsId = value; }

    }

 

    public Workflow1()

    {           

        InitializeComponent();

    }

 

    private void Start_ExecuteCode(object sender, EventArgs e)

    {

        Console.WriteLine(String.Format("Ärendet har startat för id {0} som berör {1}", BestallningsId, bestallning.ArtikelNamn));

    }

 

    private void Over_ExecuteCode(object sender, EventArgs e)

    {

        Console.WriteLine(String.Format("Ärende id {0} har en summa ({1}) som  är over gränsvärdet", BestallningsId, bestallning.Summa));

    }

 

    private void Under_ExecuteCode(object sender, EventArgs e)

    {

        Console.WriteLine(String.Format("Ärende id {0} har en summa ({1}) som  är under gränsvärdet", BestallningsId, bestallning.Summa));

    }

}

6. Editera Over-grenen i if-else aktiviteten

7. Skapa villkoret

Här har vi tillgång till intellisense och de affärsregler som vi skapar här kan vi enkelt modifiera i framtiden. Många med mig upplever denna regelmotor som otroligt kraftfull. Lägg märke till hur enkelt vi kan komma åt avancerade affärsentiteter från vårt workflow.

8. Editera Program.cs

static void Main(string[] args)

{

    Bestallning bestallning = new Bestallning();

    bestallning.Antal = 5;

    bestallning.APris = 5000;

    bestallning.ArtikelNamn = "Laptop";

    BestallningsTjanst.LaggBestallning(bestallning);           

    Console.ReadLine();

}

9. Kör

Som ni ser är det otroligt enkelt att komma igång och med hjälp av detta exempel kan ni själva bygga vidare och testa regler och kopplingar ut mot affärslager osv.

2007-02-09

Persistence & Tracking

I ett tidigare inlägg pratade vi om hur vi kommer igång med Workflow foundation, nu skall vi prata om persistens och spårbarhet.

Workflow-runtimen har en metod som heter AddService och med denna kan vi lägga till tjänster av olika typer (även egna). Vi kommer nu att titta närmare på WorkflowPersistenceService och TrackingService.

WorkflowPersistenceService
Denna tjänst serialiserar (hydrerar) vår workflowinstans ned till valfritt media (tex sql-server) och tittar sedan på det då och då (konfigurerbart) för att avgöra om det är värt att plocka upp i minnet (dehydrera) för att köra vidare.
En hydrering sker så fort workflowinstansen är idle, exempelvis när den väntar på ett externt event eller om det finns en delay-aktivitet.

TrackingService
Denna tjänst ger oss spårbarhet och vi får även möjlighet att hämta upp kopior av hur flödet såg ut vid vissa tidpunkter. Tracking är avancerat (och användbart) och det finns massor av bra artiklar som beskriver ämnet närmare.

Tracking Services Introduction

Tracking Services Deep Dive

Out-of-the-box finns det två implementationer av ovanstående som arbetar mot Sql-server som enkelt visar hur vi kan komma igång.

private readonly static WorkflowRuntime workflowRuntime;

private readonly static SqlWorkflowPersistenceService persistenceService;

private readonly static SqlTrackingService trackingService;

Vi har sedan tidigare sett hur vi initierar runtimen så det hoppar vi över här.

//Initialize persistence

string persistenceSQLConnectString = ConfigurationManager.ConnectionStrings["PersistanceConnectionString"].ConnectionString;           

bool unloadOnIdle = true;

TimeSpan instanceOwnershipDuration = new TimeSpan(0,0,60);

TimeSpan loadingInterval = new TimeSpan(0, 2, 0);

persistenceService = new SqlWorkflowPersistenceService(persistenceSQLConnectString, unloadOnIdle, instanceOwnershipDuration, loadingInterval);           

workflowRuntime.AddService(persistenceService);

Detta är allt som krävs för att initiera persistance-tjänsten, låt oss nu titta på tracking

//Initialize tracking

string trackingSQLConnectString = ConfigurationManager.ConnectionStrings["TrackingConnectionString"].ConnectionString;

trackingService = new SqlTrackingService(trackingSQLConnectString);

workflowRuntime.AddService(trackingService);

För att få allt att lira krävs naturligtvis sql-server samt att de två databaserna är installerade. Script för detta fick ni "på köpet" med .NET 3.0 i katalogen

%windir%\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\EN

2007-02-05

DinnerNow

Såg på micke's blogg att DinnerNow äntligen har släppts, detta är en otroligt cool demo-applikation som visar i princip all ny teknik live and kicking. Har själv sett denna demo köras bla på LOVE (Lansera Office Vista och Exchange)

http://www.dinnernow.net

"The demo utilizes several technologies including: IIS7, ASP.NET Ajax Extensions, Linq, Windows Communication Foundation, Windows Workflow Foundation, Windows Presentation Foundation, Windows Powershell, and the .NET Compact Framework."

Källkod finns att ladda hem från codeplex och det låter som en trevlig aktivitet för er som har tid att kika närmare på applikationen.
(inom kort kommer en online-demo för er som inte vill/orkar/har tid att installera hela köret)

Vad väntar ni på? GOGOGO!