Startseite > Techblog > Artikel mit dem Tag: softwareentwicklung
nächste Seite
thu

Für alle, die sich mit dem neuen Visual Studio und dem .NET Framework 4.0 vertraut machen  wollen oder mehr erfahren möchten, hat Microsoft das neu aktualisierte Visual Studio 2010 and .NET Framework 4 Training Kit veröffentlicht. Das am 11.01.2010 veröffentlichte 151 MB große Paket enthält eine Vielzahl von Präsentationen, Demos und Tutorials. Genau genommen 17 Präsentationen, 21 Demos und 26 Tutorials sowie 10 Videos. In dieser Version des Kits wird auch auf die Themen Office, SharePoint und Application Lifecycle Management eingegangen. Der Download lohnt sich auf alle Fälle.

Artikel vollständig lesen »

Kommentar Feed Trackback URL
thu

Am 2. Dezember 2009 fand in Düsseldorf der 2.  iX Day rund um SharePoint statt. Nach dem Erfolg des ersten iX Tages im Juli sollte sich diesmal alles rund um Sharepoint, speziell Sharepoint 2010 drehen. In über 25 Sessions kam der ambitionierte Sharepointer voll auf seine Kosten. Das Themengebiet erstreckte sich von entwicklerlastigen Vorträgen, welche sich mit der API Unterstützten Programmierung von Sharepoint befassten über Vorträge der administrativen Art bis hin zur neuen Sharepoint Pie.

Artikel vollständig lesen »

Kommentar Feed Trackback URL
thu

Vom 22 – 24.09.2009 hatte ich, dank meiner Firma, die Gelegenheit zur Shareconnect & Basta 2009 in Mainz zu fahren. Das ist zwar jetzt schon fast einen Monat her, jedoch will ich euch meine Eindrücke nicht vorenthalten.

Die Shareconnect findet im Rahmen der Basta statt und baut auf  den Sharepoint Days auf, welche seit 2007 parallel zur Basta stattfinden. In über 50 Sessions geben Experten Einblicke in die Sharepoint Welt sowohl aus Administratoren Sicht, als auch aus der Sicht von Entwicklern. Da durften auch die Experten von Communardo nicht fehlen.

Nach einem anstrengenen Flug und Bahnerlebnis und einem anschließenden Gewaltmarsch über die Theodor-Heuss-Brücke erreichte ich am 22.09 pünktlich zur ersten Session die Rheingoldhalle in Mainz. Begrüßt wurde jeder Teilnehmer mit dem Basta Survival Pack bestehend aus Rucksack, T-Shirt und allerlei Büromaterial ( Danke nochmal). Danach hat es mich direkt in den Vortrag von Oliver Sturm verschlagen, welcher bereits eifrig über die Zukunft von C# und .NET philosophierte, Co- und Kontravarianz erläuterte und die dynamischen Erweiterungen von .NET 4 vorstellte.

Gott sei dank habe ich mir im Vorfeld bereits die Sessions der Konferenz zusammengestellt, was gar nicht so einfach war.  Das Angebot umfasste rund 90 Sessions, wobei jeweils ca. 9 gleichzeitig liefen. Dank des tollen Zeitplaners konnte man aber den Überblick behalten und keine der Veranstaltungen verpassen.

Nach dem Vortrag von Oliver Sturm zog es mich direkt zu der ersten Sharepoint Session von Björn Schneider : “Planung und Aufbau von hochverfügbaren SharePoint-Infrastrukturen”.

Christian Glessner veranstaltete im Anschluss die Sharepoint Freak Show. Hier wurden richtig coole Ansätze gezeigt, Sharepoint mit jQuery, PowerShell, IronRuby oder IronPyhton zu erweitern. Seit Christians Demos, welche den Umgang  mit Powershell und Sharepoint zeigten, bin ich richtiger Fan der Powershell geworden.

Weiter ging es mit einer Demonstration wie extrem sich Sharepoint bezüglich seines User Interfaces verbiegen lässt. Michael Hofer zeigte anhand eines Fallbeispieles wie Sharepoint mit Hilfe von Bordmitteln zu einem Intranetportal ähnlich der Startseite von www.bbc.com umgebogen werden kann. Auch wenn die Technik an diesem Tag nicht mitspielte , anhand der Screenshots konnte man schon sehr gut erkennen welche Lesitung in diesem Customizing Projekt erbracht wurde.

Für die letzte Session des Tages habe ich mir “(Keine) Zeit für Herzrasen” von Torsten Weber gegönnt. Am besten ist dieses Thema durch Torstens eigene Worte beschrieben:

Es geht um Handlungsmaximen für eine ausgeglichene Work-Life-Balance, “Entschleunigung” für Fortbildung, Freiräume und Erfolg mit Werkzeugen wie MindManager oder Livescribe.

Obwohl dieser Vortrag so rein gar nichts mit Programmierung oder IT zu tun hat, habe ich es genossen Torstens Worte zu folgen. Wer mehr zu dem Vortrag erfahren möchte kann ihn hier nochmal nachlesen.

So ging er zu Ende dieser erste Tag der Shareconnect & Basta in Mainz. Zwischen den Sessions wurde man durch das Konferenz Team mit reichlich Kaffee, Kuchen, Brötchen und warmen Mahlzeiten am Mittag versorgt. Ganz nebenbei konnte ich nette Kontakte knüpfen und Produkte von Firmen bestaunen. Es gab sogar die Möglichkeit sich massieren zu lassen.

Pünktlich 8:30 ging es dann am Mittwoch mit Bus und Bahn zur Reingoldhalle, zum zweiten Tag der Basta. Nach einer kurzen Auffrischung meiner Webpartentwicklungs – Kentnisse mit Renè Hèzser verschlug es mich zu Manfred Steyers Session “Codequalität mittels Code Contracts und PEX”.  Da meine Interessengebiete in Codequalität und Clean Code Development liegen, war ich sehr interessiert daran wie Code mittels Code Contracts besser und sicherer gestaltet werden kann. Zunächst entwickelte Manfred Steyer eine unscheinbare C# Klasse, welche ein Taschengeldkonto verwalten kann. Nach und nach wurden Mängel und Lücken im Quellcode aufgedeckt und anschließend erläutert, wie diese durch Code Contracts und PEX verhindert werden können. Für mich eine der besten Sessions der Basta.

Die letzten drei Sessions für diesen Tag waren sehr von Silverlight 3 geprägt. Los ging es mit Christian Wenz, welcher alle prägnanten Neuigkeiten in Silverlight 3 präsentierte. Dazu gehören Features wie Element Data Binding, 3D Unterstützung oder das legendäre Out Of Browser Funktionalität ;)
Oliver Scheer schloss sich den Ausführungen von Christian Wenz fast nahtlos an und erläuterte wie Silverlight 3 für Enterprise Business Aplikationen verwendet werden kann. Silverlight 3 bringt dazu schon einiges an Funktionalität mit, wie etwa die eben genannte Out Of Browser Fähigkeit, smooth streaming oder die neuen RIA Services. Obwohl Olivers Vortrag eher sehr multimedialastig gehalten war und ich den Enterprise Aplikations Teil ein wenig vermisst habe war die Darbietung von Oliver wie immer sehr genial. Jörg Krause beendete den Tag mit einem Überblick der Methoden um Webparts in Kombination mit Silverlight zu verwenden.

Selbst den Abend konnte man auf der Basta verbringen indem man sich beispielsweise direkt auf das BASToberfest gesellte.

Der dritte und somit letzte Tag der Basta war für mich komplett von Silverlight und WPF geprägt. So ging es pünktlich 8:30 mit Oliver Scheer und seinen Ausführungen zu “Design the next RIA Generation” los. Nach diesem Vortrag sollte auch der Letzte alle neuen Features von Silverlight 3 kennen :) Ob Ton, Bild, Streaming ,Styling oder Skinning.
Markus Egger zeigte in den nachfolgenden 2 Sessions wie WPF & Silverlight Business Applications gestylet und anschließend in wiederverwendbare Komponenten ausgelagert werden werden können.  Auch diese beiden Tracks kann ich mit gutem Gewissen zu meinen persönlichen Highlights der Basta zählen. Anhand eines aktuellen Projektes erklärte er wie mit Hilfe von Styling und Skinning die Performance und Usablity einer Applikation gesteigert werden kann. Anschließend zeigte er auf welche Art und Weise Silverlight Komponenten ausgelagert und somit zu wiederverwendbaren Komponenten gewandelt werden können. Auch aus diesen Erläuterungen konnte ich sehr viel für mich mit nach Hause nehmen. Die für mich letzte Session der Basta verbrachte ich bei Jan Blessenohl von Telerik und seinen Ausführungen zu Silverlight und dem RIA Framework.

Vor der täglichen  Mittagspause fanden sogenannte KeyNotes statt in denen Sprecher wie Tony Lanni oder aber auch Frank Fischer von Microsoft die Zuschauer unterhielten.Tonny Lanni erklärte in seiner KeyNote “What can Sharepoint do for you” wie sehr er die Sharepoint Fee mag und diese Figur in seiner Firma wiederspiegelt. :) Hier nochmal für alle das Video

[youtube]http://www.youtube.com/watch?v=lw-OHO3UMco&feature=PlayList&p=328055501A304058&playnext=1&playnext_from=PL&index=36[/youtube]

Abschließend kann ich feststellen, dass sich die Shareconnect und Basta 2009 für mich persönlich sehr gelohnt hat. Ich konnte viele für mich neue Gesichter kennenlernen und auch viele Anregungen mit nach Hause nehmen.

Kommentar Feed Trackback URL
thu

Neugierig geworden von der diesjährigen  Basta! und Oliver Scheers Vortrag über Silverlight und das .NET RIA Framework, wollte ich das Gehörte heute einmal versuchen in die Praxis umzusetzen.

Das .NET Rich Internet Application (RIA) Framework unterstützt  den Entwickler bei der Erstellung  n- schichtiger Applikationen. Die .NET RIA Services bilden dabei ein Datenzugriffsmodell welche aus einem Objektmodell (z.B. ADO.NET Entity Framework) einen sogenannten Domain Service zur Verfügung stellen können. Die Hauptzielgruppe dieser Technologie sind  .NET Entwickler welche sich vorrangig in Silverlight sowie ASP.NET Anwendungen heimisch fühlen.

Die erste Version der .NET RIA Services kann hier heruntergeladen werden. Es sollte beachtet werden, dass es sich dabei um eine frühe CTP Version handelt.

Nach dem ersten Installationsversuch der .NET RIA Services erhielt  ich folgende Fehlermeldung.

The following required components are missing.
Microsoft Silverlight 3 Developer Runtime
Microsoft Silverlight 3 Beta SDK
Microsoft Silverlight 3 Tools.

incompatible versions

Da ich die komplette Silverlight 3 Runtime inkl. Silverlight Tools bereits installiert hatte, erschien mir die Fehlermeldung etwas irreführend.  Nach kurzer Suche fand ich heraus, dass die .NET RIA Services nicht mit einer deutschen Installation von Visual Studio zusammenarbeiten. Aber wie so oft gibt es auch hier einen nicht dokumentierten Weg um an das Ziel zu kommen :)

Voraussetzung:

  • installiertes Visual Studio 2008 SP1
  • Silverlight 3 SDK
  • Silverlight 3 Tools für Visual Studio

1. Nachdem die .NET RIA Services heruntergeladen wurden in das Downloadverzeichnis wechseln
2. Folgenden Befehl ausführen msiexec /i RiaServices.msi NOCHECK=true

  • Dieser Befehl bewirkt, dass der Windows Installer aufgerufen wird, ohne jegliche Prüfung durchzuführen

3. Sofern die Installation fehlerfrei abgelaufen ist, folgen nun weitere wichtige Schritte:

  • Wechsel in das Verzeichnis C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Silverlight\1033
    Darin befinden sich die zwei Zip Dateien BusinessApplication.zip und RIAServicesLibrary.zip.
    Diese beiden Dateien müssen nun in das deutsche Verzeichnis kopiert werden, zum Beispiel für eine deutsche Installation
    C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Silverlight\1031
    Durch diese Aktion kann nun innerhalb des Neu->Projekt Dialoges das RIA Template gewählt werden
  • Um die Funktionen rund um die Domain Service Class und Authentifizierung nutzen zu können, müssen nun noch die Element Vorlagen kopiert werden. Dazu  in den folgenden Ordner wechseln C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\1033 und folgende Dateien in das deutsche Verzeichnis kopieren C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\1031
    - AuthenticationDomainService.zip
    - BusinessLogic.zip
    - SearchSitemap.zip
    - AdoNetDataService_DomainServiceCSharpWap.zip

4. Nun die Kommandozeile aufrufen und in folgendes Verzeichnis wechseln C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE


5. Von dort aus folgenden Befehl ausführen: devenv /installvstemplates

  • Visual Studio installiert nun alle neu gefundenen Templates für Projekte und Elemente

Sollte die nachstehende Fehlermeldung erscheinen: “Der angeforderte Vorgang erfordert erhöhte Rechte”, muss die Kommandozeile als Administrator ausgeführt werden.

Nach dem Neustart von Visual Studio sollte nun in der Projektvorlagenübersicht .NET RIA Service Class Library

ria1
und in dem Dialog Hinzufügen -> Neues Element die Domain Service Class auswählbar sein.

ria2

Neugierig geworden von der diesjährigen Basta! und Oliver Scheers Vortrag über Silverlight und das .NET RIA Framework, wollte ich das Gehörte heute einmal versuchen in die Praxis umzusetzen.

Das .NET Rich Internet Application (RIA) Framework unterstützt  den Entwickler bei der Erstellung  n- schichtiger Applikationen. Die .NET RIA Services bilden dabei ein Datenzugriffsmodell welche aus einem Objektmodell (z.B. ADO.NET Entity Framework) einen sogenannten Domain Service zur Verfügung stellen können. Die Hauptzielgruppe dieser Technologie sind  .NET Entwickler welche sich vorrangig in Silverlight sowie ASP.NET Anwendungen heimisch fühlen.

Die erste Version der .NET RIA Services kann hier heruntergeladen werden. Es sollte beachtet werden, dass es sich dabei um eine frühe CTP Version handelt.

Nach dem ersten Installationsversuch der .NET RIA Services erhielt  ich folgende Fehlermeldung.

The following required components are missing.
Microsoft Silverlight 3 Developer Runtime
Microsoft Silverlight 3 Beta SDK
Microsoft Silverlight 3 Tools.

incompatible versions

Da ich die komplette Silverlight 3 Runtime inkl. Silverlight Tools bereits installiert hatte, erschien mir die Fehlermeldung etwas irreführend.  Nach kurzer Suche fand ich heraus, dass die .NET RIA Services nicht mit einer deutschen Installation von Visual Studio zusammenarbeiten. Aber wie so oft gibt es auch hier einen nicht dokumentierten Weg um an das Ziel zu kommen :)

Voraussetzung:

  • installiertes Visual Studio 2008 SP1
  • Silverlight 3 SDK
  • Silverlight 3 Tools für Visual Studio

1. Nachdem die .NET RIA Services heruntergeladen wurden in das Downloadverzeichnis wechseln
2. Folgenden Befehl ausführen msiexec /i RiaServices.msi NOCHECK=true

  • Dieser Befehl bewirkt, dass der Windows Installer aufgerufen wird, ohne jegliche Prüfung durchzuführen

3. Sofern die Installation fehlerfrei abgelaufen ist, folgen nun weitere wichtige Schritte:

  • Wechsel in das Verzeichnis C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Silverlight\1033
    Darin befinden sich die zwei Zip Dateien BusinessApplication.zip und RIAServicesLibrary.zip.
    Diese beiden Dateien müssen nun in das deutsche Verzeichnis kopiert werden, zum Beispiel für eine deutsche Installation
    C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ProjectTemplates\CSharp\Silverlight\1031
    Durch diese Aktion kann nun innerhalb des Neu->Projekt Dialoges das RIA Template gewählt werden
  • Um die Funktionen rund um die Domain Service Class und Authentifizierung nutzen zu können, müssen nun noch die Element Vorlagen kopiert werden. Dazu  in den folgenden Ordner wechseln C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\1033 und folgende Dateien in das deutsche Verzeichnis kopieren C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\ItemTemplates\CSharp\Web\1031
    - AuthenticationDomainService.zip
    - BusinessLogic.zip
    - SearchSitemap.zip
    - AdoNetDataService_DomainServiceCSharpWap.zip

4. Nun die Kommandozeile aufrufen und in folgendes Verzeichnis wechseln C:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE
5. Von dort aus folgenden Befehl ausführen: devenv /installvstemplates

  • Visual Studio installiert nun alle neu gefundenen Templates für Projekte und Elemente

Sollte die nachstehende Fehlermeldung erscheinen: “Der angeforderte Vorgang erfordert erhöhte Rechte”, muss die Kommandozeile als Administrator ausgeführt werden.

Kommentar Feed Trackback URL
thu

Ein Teil unserer Kernkompetenzen im Umgang mit Sharepoint, ist die Migration von Altsystemen zu Sharepoint. Ein aktuelles Projekt stellte uns vor die Herausforderung, Inhalte, Stylevorgaben und Meta-Daten mittels XML Import aus einem bestehenden Content Management System 1:1 nach SharePoint zu übernehmen. Besonders problematisch war dabei der Fakt, dass sich innerhalb der Daten Parameter für die Businesslogik versteckten. Diese Logik musste in SharePoint zum Teil nachgebaut und beim Import berücksichtigt werden.

Eine Teilaufgabe des Imports bestand in der Übernahme der eigentlichen Inhalte der Seiten. Diese lagen als barrierefreies HTML vor und mussten deshalb original so in die SharePoint Seite importiert werden.

Meine Aufgabe bestand nun darin, den originalen HTML Inhalt der zu migrierenden Seite in eine Sharepoint Seite zu importieren. Möglichst sollten die Optik  (Styles, Bilder, etc.) sowie der Inhalt (inkl. Links, Tabellen etc.) unangetastet bleiben.

Sharepoint bietet dem geneigten Entwickler mit seiner API reichlich Werkzeug um diese Aufgabe zu bewältigen. So kann eine Seite ohne Probleme mit folgenden Programmcode angelegt werden:

PublishingWeb currPublishingWeb = PublishingWeb.GetPublishingWeb(webContext);
PublishingPageCollection pages = currPublishingWeb.GetPublishingPages();
PublishingPage currentPage = pages.Add(pageFileName, layout);

Auf diese Weise ist eine Publishing Page schnell erstellt. Soll diese jetzt auch noch mit Inhalt versehen werden, wird das SPField, das für den Inhalt einer PublishingPage zuständig ist, benötigt.

Das SPField für Inhalte ist das PublishingPageContent Field, das über die FieldId Klasse verwendet werden kann.

SPListItem newFileItem = newFile.Item;
newFileItem[FieldId.PublishingPageContent] = htmlContent;
newFileItem.Update();

Bis hier wurde alles ordnungsgemäß von Sharepoint ausgeführt. Die Seite wurde angelegt und der Inhalt wurde auch gesetzt. Beim näheren Betrachten der neu Erstellten Seite wurde ich jedoch misstrauisch:

  • Aus einfachen Links wie zum Beispiel <a href=”../../beispiel.htm”>Beispiel</a> wurde <a>Beispiel</a>.
  • Kommentare wie <!– comment –> wurden einfach gelöscht
  • Auch Attributen wie beispielsweise Ids oder Klassen(class)  in Divs wurden gelöscht
  • Anführungszeichen wurden entfernt – <div style=”test”/> wird zu <div style=test/>

Durch dieses Verhalten wurden die importierten Seiten “wertlos” für mich. Alle darauf folgenden Versuche den Inhalt in die Seite zu schreiben schlug fehl. Versucht habe ich folgende Wege:

  1. Den Inhalt zu encodieren und anschließend wieder zu dekodieren. Prinzipiell hätte diese Variante funktioniert, jedoch hätte ich die Render Methoden des Sharepoint RichtTextEditors überschreiben müssen. Das hätte wiederum den Nachteil das die Editor Funktion nicht mehr ordnungsgemäß arbeitet. Der ausschlagegebende Faktor diese Variante nicht zu verwenden war jedoch die fehlende Möglichkeit der Indexierung des Inhaltes, da bei dieser Variante der Inhalt in Base 64 – codierter Form in der Sharepoint Datenbank gespeichert worden wäre und so durch die Suche nicht mehr indexiert werden kann.
  2. In einem zweiten Versuch, lud ich mir den Stream der neu angelegten Seite (auf File – Ebene) und ersetzte den von Sharepoint beschädigten HTML Inhalt durch den originalen. Leider wurde dieser Inhalt beim Speichern der Datei erneut beschädigt.
  3. Einen dritten Versuch ersparte ich mir, da dieser die Modifizierung der Sharepoint Datenbank vorgesehen hätte. Ich glaube der Erfolg hätte sich auch in Grenzen gehalten?!

Da ich das Problem gerne ohne “Dirty Hacks” lösen wollte, entschied ich mich eine Supportanfrage bei Microsoft zu stellen. Dazu sei erwähnt, dass die Anfragen über den Microsoft Support sehr schnell und kompetent beantwortet und abgewickelt werden.  Ich sollte meine Antwort von Microsoft bekommen; Leider hieß diese “By design” oder kurz auf deutsch: abgewiesen.

Die Begründung: Mirosoft Sharepoint nutzt einen sogenannten XSS (Cross side scripting) Protection Mechanismus. Dieser sollte verhindern das schädlicher Inhalte (Code) in Sharepoint eingepflegt werden kann.

Davon betroffen ist allerdings auch das HTML Texteingabe Control. Beispielsweise würde dieser Programm – Code wie folgt abgeändert:

original:       Das ist ein gutes <SCRIPT>void:alert("hello world")</SCRIPT> Script
verfälscht:     Das ist ein gutes Script

Auch “<” oder “>” Zeichen würden wie folgt abgeändert: &gt – &lt. Ich empfinde dieses Verhalten als vollkommen richtig und auch nachvollziehbar, wenn es dabei bleiben würde. Es stellte sich herraus dass dieser XSS Filter auch für die Kürzung meiner HTML Inhalte zuständig war. Microsoft selbst kann sich nicht erklären warum dieser Filter solch drastische Änderungen am HTML Quellcode vornimmt. Man riet mir von Seiten Microsoft ernsthaft  entweder ein 3rd Party AddOn als Ersatz für den RichTextEditor einzusetzen oder aber die Daten nicht innerhalb Sharepoints zu halten, sondern extern. Keiner der beiden angebotetenen Lösungen erschien mir für unser Projekt auch nur ansatzweise logisch beziehungsweise umsetzbar.

Lösung:

Um die Inhalte dennoch wie gefordert 1:1 importieren zu können, musste nun ein Workaround gefunden werden. Dazu bot sich eine Codierung der beim Import beanstandeten HTML-Tags an. Nach der erfolgreichen Integration der Methoden in unseren Import können nun alle Inhalte wie gefordert übernommen werden.

Kommentar Feed Trackback URL
thu

Beim programmatischen Erstellen von benutzerdefinierten Spalten (SPField) in Sharepoint sind einige Dinge zu beachten und erwarten auch beachtet zu werden. Hält man sich jedoch an die Spielregeln (API Dokumentation) und erzielt trotzdem nicht das gewünschte Ergebniss, ist wahrscheinlich wieder ein Sharepoint Bug gefunden worden. Dies musste ich heute wieder mal schmerzhaft feststellen.

Sharepoint verwendet zwei Namen um Felder zu kennzeichnen. Den internalName sowie den displayName (bzw. Title). Der internalName wird von Sharepoint selbst sowie von dem Sharepoint Objekt Modell verwendet um Spalten(SPField) und Objekte wieder zu erkennen und anzusprechen. Der displayName und die Title – Eigenschaft werden verwendet um die Darstellung der Spalten zu steueren. So können eindeutige Namen Verwendung finden um Objekte eindeutig anzusprechen. Gleichzeitig kann der Anzeigename variabel gestaltet werden.

So hatte ich versucht eine Sharepoint Spalte über die API zu erstellen und anschließend zur SPFieldCollection einer Liste  hinzuzufügen.
Dies funktionierte mit den folgenden Codeschnipseln auch sehr gut.

SPField currField = colFields.CreateNewField(SPFieldTypeString, displayName);
currField.staticName = internalName;
colFields.AddFieldAsXml(currField.SchemaXml, true, SPAddFieldOptions.AddToAllContentTypes);

Anschließend beim Beschreiben der Spalte gingen jedoch die Probleme los.

SPField newField = newItem.Fields.GetFieldByInternalName(internalFieldName);

Laut  API Dokumentation und MSDN welche besagt, dass der staticName dazu dient, um den internalName zu setzen, wäre der obige Programm – Code richtig. (“Gets or sets the internal name of the field.”)

Das Ausführen der Methode verursachte eine ArgumentException mit der Meldung: Value does not fall within the expected range.

Darfaufhin begann ich ein wenig weiter zu forschen (Danke an Sharepoint Manager) und fand herraus, dass die AddFieldAsXml Methode in Verbindung mit einem SPField welches mit CreateNewField erzeugt wurde einen Bug von Sharepoint hervorruft. AddFieldAsXml setzt den displayName wie angegeben, aber leider auch den internalName mit dem Wert des display Namens. Das hat zur Folge, dass die Spalten nicht mehr über den interalName ansprechbar sind.

Wer jetzt also vor genau diesem Problem stehen sollte, hat zwei schnelle Möglichkeiten.

  1. Die Guid des Feldes speichern und verwenden sofern der Zugriff auf diese besteht.
    Mit Hilfe dieser kann eine Sharepoint Spalte sicher bestimmt werden.
  2. Folgenden Workaround verwenden.

Workaround:

Die Lösung des Problems ist regelrecht simpel. Es wird der gleiche obige Code verwendet um das SPField zu erstellen, jedoch als displayName der internalName gesetzt. Dadurch legt Sharepoint die Spalte mit dem richtigen internalName an. Sobald die Spalte angelegt wurde, muss nur noch der displayName geändert werden.

string internalName = "internerName";
string displayName = "displayName";
SPField currField = colFields.CreateNewField(SPFieldTypeString, internalName);
colFields.AddFieldAsXml(currField.SchemaXml, true, SPAddFieldOptions.AddToAllContentTypes);
SPField rewriteField = colFields[internalName];
rewriteField.Title = displayName;
rewriteField.Update();

Wird die GetField- oder GetFieldByInternalName -  Methode jetzt mit dem internalName aufgerufen liefert sie die gewünschte Spalte.

Kommentar Feed Trackback URL
clu

Gestern Abend fand das erste Treffen der Agile Saxony in Dresden statt. Es fanden sich gleich zum ersten Termin mehr als 40 Personen ein, was die Erwartungen des Organistors Jens Korte deutlich übertraf.

Simon Roberts (Scrum Coach und Certified Scrum Trainer) führte in das Thema mit den Vortag “What the hell is Scrum?” ein und begann mit folgenden Cartoon.

Im im Agilen Manifest u. a. von Ken Schwaber und Jeff Sutherland wurde Scrum wie folgt formuliert:

  1. Individuen und Interaktionen gelten mehr als Prozesse und Tools.
  2. Funktionierende Programme gelten mehr als ausführliche Dokumentation.
  3. Die stetige Zusammenarbeit mit dem Kunden steht über Verträgen.
  4. Der Mut und die Offenheit für Änderungen steht über dem Befolgen eines festgelegten Plans.

Ziel ist es ist mit einer inkrementellen Vorgehensweise, der Organisation von Entwicklungsabschnitten und Meetings in vordefinierten Zeitabschnitten (Time-Boxes) ein funktionierendes Produkt zu entwicklen.

Links zum Thema:

http://www.scrumalliance.org/

http://scrum-master.de/

http://www.agilesaxony.org/

Kommentar Feed Trackback URL
thu

Steht man vor der Aufgabe einen Sharepoint optisch anpassen zu müssen, ist oft die Masterpage anzupassen. Wird der Sharepoint lediglich als interner Portalserver verwendet, welcher nur von einer bestimmten Zielgruppe genutzt wird, reicht dazu meist das Anlegen einer eigenen Masterpage aus.

In einem aktuellen Projekt stand ich jedoch vor dem Problem, Gästen sowie Administratoren jeweils eine eigene Masterpage zur Verfügung zu stellen. Sharepoint selber bietet keine Möglichkeit zu unterscheiden ob gerade ein Gast oder ein Nutzer auf eine Seite zugreift und eine entsprechende Masterpage auszuliefern.

Auf der Suche nach einer Lösung im Internet wurde ich relativ schnell fündig, jedoch funktionierten die angebotenen Lösungen nicht für Publishing Pages oder Template Redirection Pages.

Um die Masterpage dynamisch für Publishing Pages zu ändern, verwendet man die nachfolgende Eigenschaft:

SPContext.Current.Web.CustomMasterUrl

Die nächste Eigenschaft kann nur verwendet werden, wenn es sich nicht um Publishing Pages handelt oder man die “application.master” verändern will.

page.MasterPageFile = "/_catalogs/masterpage/default.master"

Auf Basis dieser Informationen kann nun ein Skript geschrieben werden, welches abhängig davon ob ein Nutzer angemeldet ist oder nicht, die Masterpage setzen kann. Als Ergänzung dazu kann innerhalb der “page_PreInit” die application.master auf eine eigene Masterpage eingestellt werden.

Alles was man dazu tun muss, ist, sich ein neues dll Projekt anzulegen und die fertig kompilierte dll in dem Global Assembly Cache abzulegen. Dabei ist es wichtig die dll zu signieren.

using System;
using System.Web;
using System.Web.UI;
using System.IO;
using Microsoft.SharePoint.Publishing;
using Microsoft.SharePoint;

public class MasterPageSwitch : IHttpModule
{
        public void Init(HttpApplication context)
        {
            context.PreRequestHandlerExecute += new EventHandler(context_PreRequestHandlerExecute);
        }

     void context_PreRequestHandlerExecute(object sender, EventArgs e)
        {
            Page page = HttpContext.Current.CurrentHandler as Page;

            if (page is PublishingLayoutPage || page is TemplateRedirectionPage)
            {
                HttpApplication currentApp = sender as HttpApplication;
                string parameter = "";
                if (HttpContext.Current.User.Identity.IsAuthenticated)
                {
                    parameter = "/_catalogs/masterpage/adminMaster.master";
                }
                else
                {
                    parameter = "/_catalogs/masterpage/guestMaster.master";
                }
                if (parameter != null)
                {
                    SPContext.Current.Web.CustomMasterUrl = parameter;
                }
            }
            else
            {
                if (page != null)
                    page.PreInit += new EventHandler(page_PreInit);
            }
        }

         void page_PreInit(object sender, EventArgs e)
        {
            Page page = sender as Page;
            if (page != null)
            {
                if (page.MasterPageFile != null)
                {
                    if (page.MasterPageFile.Contains("application.master"))
                    {
                      //auskommentiert da wir die Änderung der application.master nicht benötigen
                      //page.MasterPageFile = "/_catalogs/masterpage/default.master";
                    }
                }
            }
        }

        public void Dispose()
        {
        }
}

Als letzten Schritt fügt man innerhalb der web.config unter der Sektion folgenden Eintrag hinzu :

<add name="MasterPageSwitch" type="MasterPageSwitch, MasterPageSwitch, Version=1.0.0.0, Culture=neutral, PublicKeyToken=................"/>

Kommentar Feed Trackback URL
are

In meisten Fällen beim Entwickeln von Confluence Plugins ist es nicht notwendig die von Confluence zur Verfügung gestellten Core-Klassen (z.B. diverse Manager: ContentEntityManager, SmartListManager oder Daos: LabelDao, PageDao) zu überschreiben. Zwei Paradebeispiele, bei denen es allerdings unumgänglich wäre, sind die Änderung des Datenbankschemas oder die Erweiterung der Managerfunktionalität.

Atlassian Confluence selbst bietet neben dem Erweitern von Actions mittels atlassian-plugin.xml (siehe Erweitern von Actions in Confluence) keinerlei Möglichkeiten direkt die Core-Klassen zu überschreiben. Aus diesem Grund ist es notwendig in die Spring Context-Dateien, die für die Registrierung der einzelnen Klassen verwendet werden, einzugreifen. Dies kann auf zwei Wegen bewerkstelligt werden:

  • Man entpackt das Confluence JAR, nimmt die Änderungen vor und erzeugt ein neues Archiv.
  • Man überschreibt die web.xml und verweist auf die eigenen Context-Dateien.

Die erste Variante erweist sich als deutlich unpraktikabel, da dadurch offensichtlich das Testen, die Wartbarkeit sowie die Updatefähigkeit leiden würden.

Bei der zweiten Möglichkeit hingegen verhält es sich etwas anders, da das JAR-Archiv zu keiner Zeit direkt manipuliert wird. Wie das funktioniert, wird in den nachfolgenden zwei Schritten demonstriert.

1. Anpassung der web.xml

In der confluence/WEB-INF/web.xml befindet sich folgender Abschnitt (hier verkürzt dargestellt):

	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>
			classpath:/databaseSubsystemContext.xml,
			...
			classpath:/applicationContext.xml,
			...
			classpath:/jmxContext.xml
		</param-value>
	</context-param>

Hevorzuheben wären die Dateien databaseSubsystemContext.xml, die für die Entity-Mappings zuständig ist, sowie die applicationContext.xml, die die Registrierung sämtlicher Manager- und Dao-Klassen vornimmt.

Nun muss lediglich der Pfad bzw. der Name der zu bearbeitenden Datei geändert werden. Prinzipiell ist es im übrigen auch möglich eine neue Context-Datei einzutragen, in der zusätzliche Beans registriert werden können.

2. Context-Dateien erstellen und in den Classpath einbetten

Als Ausgangspunkt beim Erstellen einer neuen Context-Datei bietet sich an den Inhalt der anzupassenden Datei zu kopieren, um darin die gewünschten Änderungen vorzunehmen. Wie die einzelnen Anpassungen bzw. Erweiterungen einer Spring-Bean vorzunehmen sind, ist aus der sehr guten, einschlägigen Dokumentation von Spring zu entnehmen. (siehe Spring Dokumentation)

Abschließend verbleibt noch das Erzeugen eines JAR-Archivs und das Kopieren jenes in das confluence/WEB-INF/lib Verzeichnis des Apache Tomcats.

Kommentar Feed Trackback URL
jdi

In einem aktuellen Kundenprojekt hatten wir die Anforderung eine Message-Queue zu implementieren, die neben dem reinen Queuing eine garantierte Zustellung zum Zielsystem gewährleisten sollte. Es musste sichergestellt werden, dass auch bei Nichtverfügbarkeit des Zielsystems keine Nachrichten verloren gehen.

Da keine zusätzlichen Kosten für Softwarelizenzen anfallen sollten und ich das Rad nicht neu erfinden wollte, habe ich nach einer Lösung im OpenSource-Bereich gesucht. Mit Apache ActiveMQ bin ich fündig geworden. Innerhalb der verteilten Applikation wurde Axis2 verwendet. Das Zielsystem ist per SOAP/HTTP zu erreichen, während ActiveMQ eine Message-Queue auf JMS-Basis darstellt.

Um das Queuing zu implementieren, war folgende Reihenfolge der Nachrichtenübermittlung erforderlich:

  • Webapplikation erzeugt SOAP-Nachrichten (mit Attachments) und verpackt diese in JMS-Nachrichten
  • JMS-Nachrichten werden von der Webapplikation in eine ActiveMQ-Queue geschrieben
  • Eine selbstentwickelte Komponente holt die SOAP-Nachrichten aus der Queue
  • die selbe Komponente baut HTTP-Verbindungen zum Zielsystem auf und schickt die SOAP-Nachrichten über die HTTP-Verbindung

Initial sah die Implementierung ziemlich trivial aus, allerdings ergaben sich im Projektverlauf einige Schwierigkeiten.

Axis2 Stubs mit Maven 1 erzeugen

Da es für Axis2 kein Maven 1 Plugin gibt, bin ich für die Generierung der Stubklassen auf Maven 2 ausgewichen und habe dies in unseren Maven 1 Buildprozess integriert.

WSDL-Beschreibung

Der Service wird durch folgende WSDL beschrieben:

<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions
  xmlns:types="http://jdi.communardo.de/swatesttypes/2008-01"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:ref="http://ws-i.org/profiles/basic/1.1/xsd" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
  xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" targetNamespace="http://jdi.communardo.de/swatest/2008-1"
  xmlns:tns="http://jdi.communardo.de/swatest/2008-1">
  <wsdl:types>
    <xsd:schema targetNamespace="http://ws-i.org/profiles/basic/1.1/xsd"
      xmlns:xsd="http://www.w3.org/2001/XMLSchema">
      <xsd:simpleType name="swaRef">
        <xsd:restriction base="xsd:anyURI" />
      </xsd:simpleType>
    </xsd:schema>
    <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"
      xmlns:ref="http://ws-i.org/profiles/basic/1.1/xsd" targetNamespace="http://jdi.communardo.de/swatesttypes/2008-01">
      <xsd:import namespace="http://ws-i.org/profiles/basic/1.1/xsd" />
      <xsd:complexType name="swatestMessageType">
        <xsd:sequence>
          <xsd:element name="requestId" type="xsd:string" />
          <xsd:element name="clientNr" type="xsd:string" />
          <xsd:element name="formFields"
            type="types:formField" minOccurs="0" maxOccurs="unbounded" />
          <xsd:element name="attachmentForm" type="ref:swaRef"
            minOccurs="0" maxOccurs="1" />
          <xsd:element name="fileName" type="xsd:string" />
        </xsd:sequence>
      </xsd:complexType>
      <xsd:complexType name="formField">
        <xsd:all>
          <xsd:element name="name" type="xsd:string" />
          <xsd:element name="value" type="xsd:string" />
        </xsd:all>
      </xsd:complexType>
      <xsd:element name="newMessage" type="types:swatestMessageType" />
    </xsd:schema>
  </wsdl:types>
  <wsdl:message name="createNewMessageRequest">
    <wsdl:part name="newMessageRequest" element="types:newMessage" />
    <wsdl:part name="attachment" type="xsd:base64Binary" />
  </wsdl:message>
  <wsdl:portType name="swatestPortType">
    <wsdl:operation name="createNewMessage">
      <wsdl:input message="tns:createNewMessageRequest"></wsdl:input>
    </wsdl:operation>
  </wsdl:portType>
  <wsdl:binding name="swatestBinding" type="tns:swatestPortType">
    <soap:binding style="document"
      transport="http://schemas.xmlsoap.org/soap/http" />
    <wsdl:operation name="createNewMessage">
      <soap:operation
        soapAction="http://jdi.communardo.de/swatest/2008-1/createNewMessage" />
      <wsdl:input>
        <mime:multipartRelated>
          <mime:part>
            <soap:body parts="newMessageRequest" use="literal" />
          </mime:part>
          <mime:part>
            <mime:content part="attachment" type="*/*" />
          </mime:part>
        </mime:multipartRelated>
      </wsdl:input>
    </wsdl:operation>
  </wsdl:binding>
  <wsdl:service name="swatestService">
    <wsdl:port name="swatestPort" binding="tns:swatestBinding">
      <soap:address location="http://jdi.communardo.de/" />
    </wsdl:port>
  </wsdl:service>
</wsdl:definitions>

Der Service stellt eine Operation createNewMessage zur Verfügung, die ein Attachment nach dem SwA-Standard sowie ein paar andere Parameter erwartet.

Erzeugen der Typklassen und Stubs mit Maven 2

Für die Erzeugung der Axis2-Typklassen und -Stubklassen wird wie oben schon erwähnt Maven 2 eingesetzt. Für Maven 2 gibt es das axis2-wsdl2code-maven-plugin. Mit dem folgenden Maven 2 pom und mvn package können die Klassen aus der obigen WSDL generiert werden:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>de.communardo.jdi</groupId>
  <artifactId>techblog-wsgen</artifactId>
  <name>Techblog WSDL Axis2 Testprojekt</name>
  <version>1.0-SNAPSHOT</version>
  <description>Techblog WSDL Axis2 Testprojekt</description>
  <build>
    <plugins>
      <plugin>
        <groupId>org.apache.axis2</groupId>
        <artifactId>axis2-wsdl2code-maven-plugin</artifactId>
        <version>1.4</version>
        <executions>
          <execution>
            <id>wsdl2codeSwA</id>
            <goals>
              <goal>wsdl2code</goal>
            </goals>
            <configuration>
              <packageName>de.communardo.jdi.swatest</packageName>
              <wsdlFile>${basedir}/src/main/wsdl/MySwA.wsdl</wsdlFile>
              <databindingName>adb</databindingName>
              <generateAllClasses>true</generateAllClasses>
              <generateServerSide>true</generateServerSide>
              <generateServerSideInterface>true</generateServerSideInterface>
            </configuration>
          </execution>
        </executions>
      </plugin>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>org.apache.axis2</groupId>
      <artifactId>axis2</artifactId>
      <version>1.4</version>
      <scope>provided</scope>
    </dependency>
    <!--AXIOM Dependencies-->
    <dependency>
      <groupId>org.apache.ws.commons.axiom</groupId>
      <artifactId>axiom-impl</artifactId>
      <version>1.2.7</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.ws.commons.axiom</groupId>
      <artifactId>axiom-api</artifactId>
      <version>1.2.7</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.ws.commons.axiom</groupId>
      <artifactId>axiom-dom</artifactId>
      <version>1.2.7</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.neethi</groupId>
      <artifactId>neethi</artifactId>
      <version>2.0.2</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>commons-logging</groupId>
      <artifactId>commons-logging</artifactId>
      <version>1.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.13</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>commons-httpclient</groupId>
      <artifactId>commons-httpclient</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>wsdl4j</groupId>
      <artifactId>wsdl4j</artifactId>
      <version>1.6.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.apache.ws.commons.schema</groupId>
      <artifactId>XmlSchema</artifactId>
      <version>1.3.2</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>stax</groupId>
      <artifactId>stax-api</artifactId>
      <version>1.0.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>org.codehaus.woodstox</groupId>
      <artifactId>wstx-asl</artifactId>
      <version>3.2.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>backport-util-concurrent</groupId>
      <artifactId>backport-util-concurrent</artifactId>
      <version>2.1</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <version>1.3</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>commons-fileupload</groupId>
      <artifactId>commons-fileupload</artifactId>
      <version>1.1.1</version>
      <scope>provided</scope>
    </dependency>
    <!-- JMS Dependencies -->
    <dependency>
      <groupId>org.apache.activemq</groupId>
      <artifactId>activemq-core</artifactId>
      <version>5.1.0</version>
    </dependency>
  </dependencies>
</project>

Aufruf von Maven 2 aus dem Maven 1 Buildprozess

Da der Buildprozess in dem Projekt noch auf Maven 1 basiert und ich trotzdem nicht auf die Codegenerierung verzichten wollte, habe ich aus dem Maven 1 Buildprozess heraus Maven 2 aufgerufen. Dazu waren folgende Einträge in der Maven 1 project.xml und maven.xml erforderlich:

project.xml:

  ...
  <build>
    <defaultGoal>jdi:build</defaultGoal>
    <sourceDirectory>${basedir}/target/generated-sources/axis2/wsdl2code</sourceDirectory>
    <sourceDirectory>${basedir}/src/main/java</sourceDirectory>
  </build>
  ...

maven.xml:

  ...
  <goal name="jdi:build"
      description="Installiert zip in lokale Repos"
      prereqs="jdiInternal:generate,jar:install">
  </goal>

  <!-- Ruft Maven 2 auf, um den Sourcecode zu generieren. -->
  <goal name="jdiInternal:generate">
      <ant:echo message="${os.name}" />
      <ant:exec executable="mvn.bat" os="Windows 2000, Windows XP" dir="${basedir}">
        <arg line="package" />
      </ant:exec>
      <ant:exec executable="mvn" os="Linux, SunOS, Unix" dir="${basedir}">
        <arg line="package" />
      </ant:exec>
  </goal>
  ...

Die Unterscheidung nach Betriebssystem ist leider nötig, da ant:exec unter Windows nicht die Dateiendung ergänzt, wie man dies von der Kommandozeile gewohnt ist.

Axis2 1.4 und JMS

Für Axis2 gibt es einen mitgelieferten JMS-Connector, allerdings stellte sich heraus, dass dieser für unsere Zwecke unbrauchbar war. Der Connector konnte weder mit unidirektionalen WebServices umgehen noch konnte er unsere SwA-Nachricht transportieren. Um trotzdem JMS nutzen zu können, habe ich die Stub-Klassen angepasst, so dass sie die Attachments korrekt im MessageContext integrieren und das eine eigene AXIOM-basierte JMS-Client-Implementierung die JMS-Nachrichten in der überschriebenen invoke(MessageContext)-Methode zusammenbaut. Im Gegensatz zum bei Axis2 mitgelieferten JMS-Connector wird dabei ein JMSByteMessage verwendet und die SwA-Serialisierung von Axis2 genutzt. Als Proof-of-Concept habe ich das Gleiche auch mit einer MTOM-Nachricht hinbekommen, dies wurde allerdings von dem WebService-Endpoint auf der Gegenseite nicht unterstützt.

Wichtig ist, dass der Stub folgendermaßen initialisiert wird:

JMSSwaTestStub stub = new JMSSwaTestStub(config, jmsEndpointUrl.toString());
stub._getServiceClient().getOptions().setUseSeparateListener(false);
stub._getServiceClient().getOptions().setProperty(Constants.Configuration.ENABLE_SWA, Constants.VALUE_TRUE);
stub._getServiceClient().getOptions().setProperty(Constants.Configuration.ENABLE_MTOM, Constants.VALUE_FALSE);

Das Attachment wird folgendermaßen in den MessageContext geschrieben:

    try {
      String contentId = _messageContext.addAttachment(attachmentData);
      SwaRef swaref = new SwaRef();
      swaref.setSwaRef(new URI("cid:" + contentId));
      newMessage5.getNewMessage().setAttachmentForm(swaref);
    } catch (MalformedURIException mue) {
      throw new AxisFault(mue.getLocalizedMessage(), mue);
    }

Die Verwendung einer ByteMessage wird folgendermaßen erzwungen:

    _messageContext.setProperty(JMSConstants.JMS_MESSAGE_TYPE, JMSConstants.JMS_BYTE_MESSAGE);

ActiveMQ-Überwachung

ActiveMQ bietet mehrere Möglichkeiten zur Überwachung der Queues dazu gehören

  • WebInterface
  • RSS- und Atom-Feeds
  • JMX

Per JMX lassen sich sehr leicht die Namen der Queues und ihr Füllstand überwachen. Bei Fehlern werden Nachrichten in eine spezielle Dead Letter Queue geschrieben. Zusätzlich haben wir für Applikationsfehler noch eine Error-Queue definiert, die der Konsument der JMS-Nachrichten genutzt hat, um auf Fehler von der HTTP/SOAP-Gegenstelle zu reagieren.

Fazit

Der Einsatz von ActiveMQ als Message-Queuing Middleware hat sich für das Projekt gelohnt, auch wenn uns der schlechte JMS-Support in Axis2 einige Stolpersteine in den Weg gelegt hat.

ActiveMQ bietet auch eine ganze Reihe von Möglichkeiten, die wir im Rahmen des Projektes nicht ausschöpfen konnten. Interessant sind dabei z.B. die Konnektoren zu anderen Transportprotokollen als JMS, z.B. XMPP (Jabber), OpenWire und Stomp. Die Dokumentation auf der ActiveMQ Webseite (http://activemq.apache.org/) ist sehr umfangreich, aber insbesondere im Hinblick auf die Konfiguration nicht immer ganz aktuell und vollständig. Hier mussten wir gelegentlich einen Blick in den zum Glück verfügbaren Sourcecode werfen, um alles richtig zu konfigurieren.

Bei Axis2 sieht das Bild etwas getrübter aus. Für “normale” Einsatzgebiete wie reine HTTP/SOAP-WebServices ist die Unterstützung sehr gut, allerdings stößt man bei Attachments und insbesondere der Nutzung anderer Transportprotokolle, in unserem Fall JMS, schnell an Grenzen und Fehler und muss sich selbst helfen. Auch die Dokumentation auf der Projektwebseite (http://ws.apache.org/axis2/) ist recht lückenhaft. Axis2 hat allerdings eine große und aktive Entwicklercommunity, so dass zu hoffen ist, das sich diese Situation im Laufe der Zeit verbessert.

Kommentar Feed Trackback URL
nächste Seite

Tag Cloud

Unsere Themen

Kommentare

  • SharePoint_Team: Rückblick zum Treffen der .NET Usergroup Dresden am 24.02.2010: im #Communardo #Techblog...
  • TorstenHu: Rückblick zum Treffen der .NET Usergroup Dresden am 24.02.2010: im #Communardo #Techblog...
  • SharePoint_Team: Neuer Blogpost zur #BastaCon im #Communardo #TechBlog: http://tinyurl.com/yjqyqpb This comment was...
  • SharePoint_Team: Nur noch etwa 1 Stunde, dann beginnt die .NET Usergroup… http://bit.ly/dxDoKg This comment was...
  • SharePoint_Team: RT @TorstenHu: ViS is waiting for an operation oder Warum Copy & Paste schlecht ist: #Communardo...

Twitter