Dienstag, April 29, 2008

Workflow Foundation Erkenntnisse (Hosting TODOs)

Ich habe die letzten Wochen Beratung unter anderem zum Thema Windows Workflow Foundation gemacht. Dabei sollte das Workflow Designer-Control für die Anpassung der WFs genutzt werden. Im Großen und Ganzen ein super Tool und sehr interessant und mächtig, allerdings hatte die Demo, die wir benutzt haben einige ärgerliche Probleme. Eine Version mit ausführlicher Anleitung kann beim Artikel „Windows Workflow Foundation: Everything About Re-Hosting the Workflow Designer“ heruntergeladen werden.

1.       Bei der Verwendung von Umlauten, bekommt die Anwendung arge Probleme, hier müssen einige Methoden in der Loader-Klasse angepasst werden.

In der Methode PerformFlush sollte das Encoding für den Writer gesetzt werden, hier der Auszug:

   244   if (rootActivity != null )

  245  {

  246      using ( XmlWriter xmlWriter = XmlWriter . Create(

  247          this . xoml

  248          , new XmlWriterSettings () { Encoding = Encoding . UTF8, OmitXmlDeclaration = false }))

  249      {

  250          WorkflowMarkupSerializer xomlSerializer = new WorkflowMarkupSerializer ();

  251          xomlSerializer . Serialize(xmlWriter, rootActivity);

   252      }

  253  }

Außerdem habe ich noch die Methode PerformLoad angepasst, hier der Auszug:

  193   Activity rootActivity = null ;

  194   using ( StreamReader sr = new StreamReader ( this . xoml, Encoding . UTF8, true ))

  195  {

  196      using ( XmlReader reader = XmlReader . Create( this . xoml))

  197      {

  198          WorkflowMarkupSerializer xomlSerializer = new WorkflowMarkupSerializer ();

  199          try

  200          {

  201              rootActivity = xomlSerializer . Deserialize(serializationManager, reader) as Activity ;

  202          }

  203          catch ( Exception ex)

  204          {

  205              Trace . WriteLine(ex);

  206          }

  207      }

  208      if (rootActivity != null && designerHost != null )

  209      {

  210          AddObjectGraphToDesignerHost(designerHost, rootActivity);

  211          Type companionType = rootActivity . GetValue( WorkflowMarkupSerializer . XClassProperty) as Type ;

  212          if (companionType != null )

  213              SetBaseComponentClassName(companionType . FullName);

   214      }

  215  }

Bei der letzen Änderung bin ich mir nicht sicher, aber dennoch der Hinweis. Die Methode GetRootActivity in der Helper-Klasse könnte ebenfalls zu Problemen führen, auch hier eine kleine Anpassung:

   52   internal static Activity GetRootActivity( string fileName, IServiceProvider serviceProvider)

   53  {

   54      Activity rootActivity = null ;

   55      using ( StreamReader sr = new StreamReader (fileName, Encoding . UTF8, true ))

   56      {

   57          using ( XmlReader reader = XmlReader . Create(sr

   58              , new XmlReaderSettings () { XmlResolver = new System . Xml . XmlUrlResolver () }))

   59          {

   60              WorkflowMarkupSerializer xomlSerializer = new WorkflowMarkupSerializer ();

   61              DesignerSerializationManager ser = new DesignerSerializationManager (serviceProvider);

   62              ser . CreateSession();

   63              rootActivity = xomlSerializer . Deserialize(ser, reader) as Activity ;

    64          }

   65      }

   66      return rootActivity;

   67  }

2.       Die Nutzung einer Konfigurationsdatei für die möglichen Controls finde ich mehr als ungünstig, hier sollte man die AddToolboxEntries-Methode der ToolboxService-Klasse anpassen, in dem alle Assemblies (aus dem aktuellen und dessen Unterverzeichnis) durchlaufen werden und geprüft wird, ob Klassen mit der Basis-Klasse „Activity“ vorhanden sind. Außerdem nicht vergessen die Standard Activities zu laden. Das Durchlaufen der Assemblies im Ordner ist in den Code-Zeilen nicht vorhanden.

   546   Assembly assembly = typeof (System . Workflow . Activities . ActiveDirectoryRole ) . Assembly;

  547  LoopAssemblyTypes(lb, assembly);

  548  assembly = typeof ( TerminateActivity ) . Assembly;

  549  LoopAssemblyTypes(lb, assembly);

  550   //VS2008 required

  551  assembly = typeof ( SendActivity ) . Assembly;

   552  LoopAssemblyTypes(lb, assembly);

Hier die aufgerufene Methode (Außerdem wird der Assembly-Name als Titel verwendet):

   555   private void LoopAssemblyTypes( ListBox lb, Assembly assembly)

  556  {

  557      Type [] assemblyTypes = assembly . GetTypes();

  558      bool groupSet = false ;

  559      foreach ( Type assemblyType in assemblyTypes)

  560      {

  561          if (assemblyType . IsAbstract || ! assemblyType . IsClass || ! assemblyType . IsSubclassOf( typeof ( Activity )))

  562          {

  563              Debug . WriteLine( string . Format( "Class '{0}' not a valid Activity!" , assemblyType . FullName), "ToolboxService.LoopAssemblyTypes" );

  564          }

  565          else

  566          {

  567              Trace . WriteLine( string . Format( "Loading '{0}' into toolbox!" , assemblyType . FullName), "ToolboxService.LoopAssemblyTypes" );

  568              SelfHostToolboxItem item = new SelfHostToolboxItem (assemblyType, assemblyType . FullName);

  569              tbItems . Add(item);

  570              if ( ! groupSet)

  571              {

  572                  lb . Items . Add(assembly . FullName . Split( new char [] { ',' }, 2 )[ 0 ]);

  573                  groupSet = true ;

  574              }

  575              lb . Items . Add(item);

   576          }

  577      }

  578  }

3.       Übergeben der Typen an den TypeProvider dazu die Methode Initialize des Loaders erweitern. (Wird der TypeProvider nicht erweitert mit den Assemblies und dieser auch überall übergeben, so kann das der Grund sein, warum definierte Workflows nicht geladen werden. (Es gibt auch keine Fehlermeldung)

  102   foreach ( SelfHostToolboxItem toolboxItem in toolbox . Items)

   103  {

  104      typeProvider . AddAssembly(toolboxItem . Compon entClass . Assembly);

  105  }

  106  host . AddService( typeof ( ITypeProvider ), typeProvider, true );

4.       Außerdem habe ich einen ToolTip in die Anwendung integriert, der das DescriptionAttribute auswertet und ausgibt. Dazu muss kräftig in die ToolboxService-Klasse eingegriffen werden.

Die erste Änderung in der OnListBoxMouseMove

  692   int currentIndex = listBox . IndexFromPoint( new Point (e . X, e . Y));

  693   if (currentIndex >= 0 )

  694  {

  695      SelfHostToolboxItem item = listBox . Items[currentIndex] as SelfHostToolboxItem ;

  696      if (item == null || string . IsNullOrEmpty(item . Tooltip))

  697      {

  698          this . tooltip = null ;

  699  

  700          currentHighlightItemIndex = Int32 . MinValue;

  701      }

  702      else

  703      {

  704          {

  705              // ToolTip setzen

  706              if (currentHighlightItemIndex != currentIndex)

  707              {

  708                  this . tooltip = item . Tooltip;

  709                  currentHighlightItemIndex = currentIndex;

  710                  this . tp . Show(tooltip, this , new Point (e . X, e . Y));

   711              }

  712          }

  713      }

  714  }

Auf Klassenebene sind die 3 Fields definiert

  717   ToolTip tp = new ToolTip ();

  718   string tooltip;

   719   int currentHighlightItemIndex;

Außer den beschriebenen Anpassungen kann man sich durchaus auch noch kräftig in der OnDrawItem-Methode austoben, hier kann man die Anzeige den eigenen Wünschen anpassen.

Man muss/sollte in seinen Workflows-Assemblies unbedingt das XmlnsDefinitionAttribute verwenden und einen für sich eindeutigen Namespace definieren. Mittels des Attributes wird die Auflösung der Namepsaces im Xml (Xoml-Workflow) und der CLR gesteuert. Kommt es zu Problemen beim Laden der Workflows im Designer, obwohl der TypeProvider überall mitgegeben wird, so kann man sich mit einem Trick weiterhelfen. Das XmlnsDefinitionAttribute wird auf den CLR-Namespace gesetzt, zum Beispiel xmlns:cv="clr-namespace:DE.CapeVision.Workflow.MainActivities;assembly=CapeVisionMainActivityLib". Viel mehr Details dazu unter XAML Namespaces and Namespace Mapping.

Sonntag, April 20, 2008

Wenig geblogged

Ich habe in den letzten 3-4 Wochen noch weniger geblogged als die anderen Wochen zuvor. Ich konnte mich einfach nicht richtig durchringen etwas zu machen. Zu dem habe ich neben der Arbeit dringend ein Buch lesen müssen und so verschwand die Zeit. Zu dem war ich extrem down, wegen meiner Ex, obwohl sich von dem Zustand gar nichts verändert hatte. Einzig das Hotelleben war mal wieder da, so dass da viel Zeit war. L Ich bin so deprimiert, zum einen weil keine Freundin da ist und zum anderen weil ich meine Ex-Freundin immer noch vermisse. Ich mache mir immer noch Vorwürfe, aber ich habe keine Schimmer, wie ich etwas ändern könnte. Ich bin so demotiviert. Nun werde ich mich richtig auf meine Ziele für dieses Jahr stürzen, die aber noch nicht abgestimmt sind. Wenn ich die so, wie ich sie entworfen habe unterschreibe, dann werde ich wohl nur noch arbeiten. Das hat dann auch den Charme, das keine Zeit mehr ist an etwas anderes zu denken.

Im Rahmen der Zielauswertung 2007 musste ich zwangsläufig über das vergangene Jahr nachdenken. Privat war das Jahr zweigeteilt, beruflich dagegen das ganze Jahr ok. Es ist spannender in einem kleinen Unternehmen, was man positiv und negativ auslegen kann, aber ich würde es eher positiv auslegen. Mir macht es Spaß die Abwechslung in den Projekt zu haben, mal schauen, was dieses Jahr spannendes noch auftaucht.

Mittwoch, April 16, 2008

Schleifen in Workflow Foundation

Letzte Woche bin ich auf einen Effekt bei der Workflow Foundation gestoßen, der mir so nicht bewusst war und auch nur bedingt sinnvoll aus meiner Sicht.

Der Effekt tritt auf, wenn man eine Schleife benutzt und Werte innerhalb der Schleife abfragen möchte. Konkret trat das Problem auf, sobald ein IF-Branch verwendet wurde. Versucht man auf Ativitäten innerhalb der Schleife zu zugreifen, so sind die Werte/Variablen nicht gesetzt. Nach etwas Recherche in dem WF Buch von AWP, ist die Ursache klar, der ExecutionContext wird ständig neu Instanziiert. Im ExecutionContext sind alle Informationen enthalten, welchen Status hat die Ativity und Ergebnisse. Wird eine Activity geschlossen, was der normale Zustand nach der Fertigstellung ist, so ist die Activity im Status Closed. Aus dem Status Closed kann man eine Activity nicht wieder zurück in den „Executing“-Status setzen. Aus diesem Grund wird für jeden Schleifendurchlauf ein neuer Context erzeugt. In dem Buch sind entsprechende Code-Beispiele enthalten, wie man selber Schleifen erzeugen kann. Um nun aber an die Daten heranzukommen, die im aktuellen Schleifendurchlauf vorhanden sind, wird bei Schleifen eine Property zur Verfügung gestellt mittels der eine Abfrage des Inhalts möglich ist, für while-Acitivty ist es die Dynamic-Activity-Property. Eine Abfrage könnte dann etwa so aussehen:

    7  (( MyDataActivity )

    8      (( WhileActivity ) this . GetActivityByName ( "MeineWhileSchleife" ))

     9          . DynamicActivity . GetActivityByName ( "MyDataActivity" )) . MyDataProperty

Sieht kompliziert aus, aber leider bekommt man von der GetActivityByName-Methode nur den Activity-Typ, so dass die Casts notwendig sind. Leider habe ich kein Beispiel parat, aber zumindest ein bisschen Code für eine eigene Schleife werde ich nach liefern.

Evtl. morgen dann noch ein Posts zu Trouble mit den Custom-Activity und das laden im Designer (Custom Designer).

Update
Hier ist noch ein kleiner Nachtrag, leider nicht der Code der While-Activity. Ich hatte leider vergessen die entsprechende Anweisung zu erstellen. Dafür kann ich als alternative aber einige Artikel bzw. Auszüge aus dem Buch Essential Windows Workflow Foundation bieten, auf die gestoßen bin. Die Informationen sind unter http://codeidol.com/other/essential-windows-workflow-foundation/ einzusehen.Die While-Activity ist als Beispiel im Artikel Activity Execution Context beschrieben.

Sonntag, April 06, 2008

DAS Tool für Software Configuration Management (SCM)

Wir stellen uns mal wieder, oder besser immer noch, die Frage was das beste SCM-Tool ist. Momentan nutzen wir SVN und TRAC als die SCM-Tools, momentan suchen wir nach weiteren Alternativen. Wir haben noch TFS und OTRS (Wikipedia) aufgetan, die ohne allzu hohe Kosten bei uns eingesetzt werden könnten. Bei TFS haben wir ein wenig Erfahrungen und lehnen es aus diversen Gründen ab.

OTRS ist interessant, es handelt sich dabei um ein Open Source Projekt. Die Installation unter Windows ist sehr einfach und geht recht schnell. Man sollte beachten, dass kein IIS installiert sein sollte. Bei der Installation werden Perl, MySql und Apache mit installiert. Die Installation ist wirklich sehr einfach und kann eigentlich jeder durchführen. Das große Problem war die Konfiguration. Ich bin da einfach nicht durchgestiegen. Vielleicht muss man das auch im ausgeruhten Zustand betrachten. Aber laut der Website gibt das Tool viel her. Zu der Anwendung gibt es auch eine Reihe von Erweiterungen, die man sich anschauen sollte.

Momentan noch mein Fazit, SVN und TRAC ist das BESTE. Übrigens bin ich am Freitag beim schnüffeln im Internet auf eine nette Präsentation zu TRAC und SVN gestoßen, http://www.prestonlee.com/tmp/Subversion%20for%20SCM.pdf.

Sonntag, März 30, 2008

Rings um Oster(n)wochen

Sorry, für die wenigen Posts, aber irgendwie habe ich grad keine Peilung, was ich am besten schreiben soll. Technisch fitze ich mich gerade mal wieder in das Thema Workflow Foundation tiefer rein, ansonsten habe ich nicht viel Zeit nebenbei. Ich schaff es nicht mal meine Technology Review zu lesen.

In den letzten 2 Wochen war ich mal wieder auf Dienstreise, das Gute ist diesmal, dass ich nur 2h weg bin. Das Thema finde ich alles andere als spannend oder interessant, aber eine begrenzte Zeit werde ich das überleben.

Die Osterfeiertage habe ich auch gut überstanden, wobei ich sagen muss, dass es teilweise schon richtig langweilig war. Zum Glück haben wir, meine Freunde und ich, wenigstens 2 Tage zu gebracht. Das Osterfeuer war dieses Jahr ganz schön feucht und kalt und dass ohne meine gute Jacke. Bei Jacke fällt mir ein, dass ich jetzt wieder eine neue Jacke habe. Ich glaube, dieses Ostern war das erste, an dem die ganze Familie Eier gefärbt hat. Ergebnis waren wirklich schöne bunte Eier.

Zu meiner Ex-Beziehung kann ich nur eins sagen, mir fehlt Sie immer noch sehr, meine Motivation ist immer noch äußerst gering und richtig glücklich bin ich auch fast nie, dafür habe ich aber einen größeren Sarkasmus.

Montag, März 24, 2008

Über ein Halbes Jahr Jabber

Diesen Post wollte ich schon vor einer Zeit machen, allerdings hatte ich immer mal wieder was anderes im Kopf. Wir nutzen nun schon über ein halbes Jahr Jabber/XMPP. Jabber war im letzten und auch vorletzten Jahr der Hype, es scheint so als kann sich keiner mehr so richtig vor IM schützen. Nach dem im letzten Jahr auch AIM/ICQ erste Versuche mit XMPP-Server gemacht haben, so bin ich guter Dinge, dass es noch weitere Fortschritte machen wird. Außer der immer größeren Verbreitung wurde letztes Jahr auch endlich die Jingle-Erweiterung für Voice-/Audio-Chat beschlossen. Die Implementierungen für die Funktionalität wird bestimmt sehr schnell Einzug halten. Google-Talk-Nutzer kennen Jingle schon lange. In Deutschland wird Jabber durch große Provider wie web.de und gmx gepuscht, beide bieten jedem Nutzer auch einen Jabber-Zugang an.

Bei uns in der Firma nutzen nicht alle die Funktionalität, da es momentan noch keine Kopplung an unser AD gibt und User momentan erst eingerichtet werden müssen, außerdem mag nicht jeder IM, bzw. kann es wegen Beschränkungen bei Kunden nicht nutzen. Einige Probleme gibt es mit unserem DNS-Provider Hosteurope, offensichtlich sind die SRV-Records nicht immer abfragbar. Allerdings sind die SRV-Records auch das einzige Problem, was momentan mit unserem XMPP-Server existiert. Bei den Clients herrscht immer noch Vielfalt, wobei meistens ein einfacher Client mit wenigen Optionen ausreicht um weniger zu verwirren. Ansonsten ist es recht praktisch eine Hersteller unabhängige Kommunikationslösung zu besitzen, die möglichst universelle Schnittstellen hat. (Transports) Alles in allem ist Jabber praktisch, einfach, universell und hilfreich!

Ich hoffe, dass IM endlich in den deutschen Unternehmen als Ergänzung der Kommunikationsmittel verwendet wird. Leider sehen viele es eher als Ablenkung der Mitarbeiter und Spielerei, nur diese Leute nutzen diese Sachen am wenigsten. Kollegen, die beim Kunden unterwegs sind, haben erhebliche Probleme sich mit dem Server zu verbinden auf Grund der verschiedenen Restriktionen von Unternehmen.

Aus meiner Sicht ist Jabber/XMPP das Protokoll für Messaging die nächsten Jahre, demnächst werden vermutlich auch die Großen (AIM/ICQ/MSN/YAHOO) ihre Pforten öffnen.

Sonntag, März 16, 2008

Die letzten Wochen / Schöne Ostern

Ich hatte in den letzten Wochen das Blogging bisschen vernachlässigt, zumindest habe ich wenig/nix privates geschrieben. In der vorletzten Woche hatte ich einen kleinen Fahrradunfall (siehe Bilder), danach war es etwas anstrengend sich in Berlin fortzubewegen, da die BVG mehr Geld will und Streikt. Ich hatte mir bei Freunden ein Fahrrad ausgeliehen, zum abholen musste ich dann die Skates benutzen, die Wohnen ein Stück von der S-Bahn weg. Zu dem Zeitpunkt sollte am Montag auch noch der S-Bahn Streik beginnen. Nach einer Woche in der Fahrrad-Werkstatt ist mein Fahrrad nun wieder fertig. Lenker, Gabel, Laufrad und Bremsscheibe mussten gewechselt werden.

Für meine Gefühle gehen momentan hin und her, es ist nicht so katastrophal wie noch vor einem Monat, aber gut fühlt sich anders an. Zu erzählen habe ich nicht viel Neues, daher schweige ich und schlucke es einfach herunter. Es gab einen gemeinsamen Bowling-Abend mit Ex-Kollegen in der letzten Woche. Es ist schön mit Freunden oder Kollegen etwas zu unternehmen und etwas abzuschalten von der Arbeit.

Auf Arbeit ist es momentan nicht so spannend, ich soll zwar einen POC machen, aber die Thematik reizt mich irgendwie überhaupt nicht, zumindest momentan. Ich werde die kommende Woche mit einem Kollegen beim Kunden Vorort verbringen und wir versuchen dort die erwünschten Ergebnisse zu erzielen. Auf geht’s in die brandenburgische Pampa, nicht weit wohnt auch ein Kollege.

In der Woche kann ich mich dann hoffentlich gut auf Workflow Foundation und vielleicht auch BizTalk-Zertifizierung vorbereiten. Aber das Zweite hat eine geringere Priorität, ist nur wichtig für mein Geld. Am meisten freue ich mich momentan auf Ostern, wenn ich auch noch nicht weiß, ob ich alle Freunde sehe. Ich muss mir noch überlegen, wie und wann ich zu meinen Eltern fahre. Ich könnte Donnerstag von der Dienstreise durchfahren, muss dann aber viel mitschleppen, ich könnte Donnerstag noch nach Hause und dann weiter oder ich fahre erst am Freitag. Wie es auch immer kommt, ich werde es schon schaffen.

Allen ein schönes Osterfest mit viel Sonne!