Beiträge für Juli, 2007

29Jul

Bei Microsoft gibt es jetzt Zertifizierungen mit dem Schwerpunkt Enterprise Project Management. Natürlich gemünzt auf die Microsoft-eigenen Produkte Project Professional 2007 und Project Server 2007.

Der Project Professional Kurs ist ab August, der Project Server Kurs ist ab November verfügbar. Kentnisse von Projektmanagement auf Grundlage der PMI Richtlinien werden empfohlen. 

Link to MCTS: Enterprise Project Management with Microsoft Office Project Server 2007


27Jul

Im Verlauf eines JMeter Tests kann es notwendig sein, dynamische Inhalte einer Server Response (Header, Body, URL) auszulesen und als Parameter für eine weiter Anfrage zu übernehmen. Dies ist zum Beispiel erforderlich, wenn innerhalb von Formlaren Werte von HIDDEN-Feldern dynamisch generiert werden.

Für diesen Zweck verfügt JMeter über einen Post-Processor, der als Regular Expression Extractor bezeichnet wird. Er lässt sich unterhalb eines Controllers hinzufügen.

Im Screenshot sind exemplarisch die Einstellungen dargestellt, die vorgenommen werden müssen, um den Wert eines HIDDEN-Feldes auszulesen. Der ‘Reference Name’ dient als Bezeichner für die Variable, die im HTTP-Request referenziert werden kann. Der reguläre Ausdruck erfolgt gemäß Perl Regular Expressions.

Regular Expressions Extractor

JMeter HTTP Requests


25Jul

Beim Umhängen eines MOSS 2007 Servers in eine andere Domäne funktionieren natürlich die Servicekonten nicht mehr, die man bei der Konfiguration des SharePoint Servers angegeben hat. Bevor man jetzt manuell überall die Credentials ändert (IIS, SQL Server), und auch nach einiger Zeit immer wieder über nichtssagende Fehlermeldungen des MOSS stolpert (ich sag nur: An unexpected error has occured), hier ein praktischer Befehl des stsadm.

Stsadm.exe –o updatefarmcredentials –userlogin –password

Danach auf jeden Fall iisreset /noforce aufrufen.


25Jul

Beim Speichern eines Projektplanes auf dem Microsoft Office Project Server 2003 können im Dialog zum Speichern Versionen des Projektplanes ausgewählt werden. Die Version wird als Erweiterung mit dem Projektnamen gespeichert.

Standardmäßig sind die Versionen „published“ und „target“ auf dem Projectserver angelegt – weitere können durch den Serveradministrator angelegt werden (Manage Enterprise Features –> Versions).

Beim Anlegen einer Version kann neben dem Versionsnamen der Archivierungstyp (Version Archived) und der Typ des Gantt-Diagrammes ausgewählt werden. Bedeutsam ist eigentlich nur der Archiverungstyp.

  • Archivierte Versionen (Versionierungstyp: Yes) bilden Momentaufnahmen der aktuellen Version (inklusive Zuordnungen) zu bestimmten Zeitpunkten im Projektlebenszyklus ab. Damit sind diese Versionen besonders zum Erstellen von Sicherungskopien eines Projekts oder zum Vergleichen des Fortschritts geeignet.
  • In Nichtarchivierten Versionen (Versionierungstyp: No) werden die Zuordnungen nicht gespeichert, sondern abhängig vom Ressourcenpool, aktualisiert. Beispielsweise werden nach dem Speichern einer Projektversion vorgenommene Erhöhungen von der Arbeit der Ressourcen und die Veränderungen der Verfügbarkeit in der nichtarchivierten Version widergespiegelt.

Mit welcher Version sollte ein Projekt gespeichert werden?

Wenn Sie eine Version als aktuelles Projekt weiterverwenden möchten, müssen Sie es mit der Version „published“ speichern. Nur diese Version wird mit dem Project Server synchronisiert.

Die Version „target“ hingegen archiviert den Projektstand (in der Standardinstallation, da die Version vom Administrator modifiziert werden kann).

Die Verwendung der spezifischen Versionen hängt von individuellen Regelungen ab. Beispielsweise kann der Lebenszyklus eines Projektes durch verschiedene Versionen nachverfolgt werden, dann sollten Projekte mit einer entsprechenden Version am Ende einer Projektphase gespeichert werden.

Wann verwendet man Basispläne und wann Versionen?

Anstelle der Verwendung von Versionen zu Vergleichszwecken können auch mehrere eines Projekts gespeichert werden. Basispläne können zum Anzeigen von Unterschieden auf Vorgangsebene und im Terminplan eines Projekts verwendet werden. Sie enthalten jedoch nicht alle Informationen, die in einer Version eines Projekts enthalten sind.


24Jul

In Visual Studio 2005 gibt es leider einen kleinen Bug in den “Extensions for WF”. Das Debuggen von Workflows, also nicht des Quellcodes, funktioniert oft nur schlecht oder garnicht. Häufig stürzt das Visual Studio sogar ab, wenn man versucht den Debugger an einen Prozess zu hängen, der Workflows verwendet. Einen solchen Prozess erkennt man recht leicht, indem man einen Blick auf den Typ wirft. Steht dort u.a. “Workflow” (siehe Abbildung) sollte man sich besser nicht an den Prozess hängen.

Blog_WF_Debug

Verhindern lässt sich dieser Effekt indem man das Visual Studio bereits an den Prozess hängt, bevor die Assembly des Workflows geladen wurde, wobei ggf. vorher ein iisreset durchgeführt werden muss. Sobald die Assembly geladen wurde, lässt sich der Quelltext wie gewohnt debuggen.


20Jul

Ein gängige Methode in der Workflowentwicklung für Sharepoint 2007 ist es, Infopath-Formulare zu verwenden. Um die Daten dieser Formulare komfortabel zu deserialisieren, werden in der Regel die von Infopath zur Verfügung gestellten XSD-Schemas mittels des XSD-Tools in Klassen umgewandelt. Bei der Weiterverwendung der generierten Klasse kann folgendender Fehler ggf. auch nur sporadisch auftreten:

DehydrateInstance: System.Runtime.Serialization.SerializationException: End of Stream encountered before parsing was completed.
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.ObjectReader.Deserialize(HeaderHandler handler, __BinaryParser serParser, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream)
at System.Workflow.ComponentModel.Activity.Load(Stream stream, Activity outerActivity, IFormatter formatter)
(…)

Das Problem liegt hierbei nicht an den eigentlichen Daten, sondern an einem zusätzlichen Datenfeld, welches von Infopath erzeugt wird:

private System.Xml.XmlAttribute[] anyAttrField;

Da dieses mit keinem Attribut dekoriert ist, kommt es zu Problemen bei der (De-)Serialisierung. Abhilfe schafft das NonSerialized()-Attribut:

[NonSerialized()]
private System.Xml.XmlAttribute[] anyAttrField;


04Jul

Wer schon einmal händig die default.master für eine Site (z.B. im Sharepoint Designer) angepasst hat und diese Änderungen für eine größere Menge vorhandener Sites übernehmen wollte, weiß, wie zeit- und nervtötend dies sein kann: jede Site muss einzeln im Sharepoint Designer aufgerufen und die Masterpage ersetzt werden.Mit einer kleinen Konsolenanwendung kann man hier Abhilfe schaffen: Die Anwendung läuft rekursiv durch alle Sites und Subsites ab einer übergebenen URL, lädt die als Datei auf dem Sharepoint Server (MOSS oder WSS) bzw. einem Fileshare gespeicherte Masterpage in die Masterpage-Galerie der Site hoch und setzt sie als Default Masterpage.

Anwendung: auf dem Sharepoint Server einfach die geänderte Masterpage als Datei speichern und die Anwendung ausführen, dabei die URL der Site, ab der die Masterpage aktualisiert werden soll und den Speicherort der geänderten Masterpage als Parameter übergeben:

ApplyMasterpage.exe “http:/myserver/mysite” “C:\mydefault.master”

ApplyMasterpage

Download der Exe: applymasterpage.exe

Download Quellcode: applymasterpage.zip


03Jul

Um in einer Webanwendung sicherzustellen, dass die Nutzer keinen Viren oder andere Schädlinge durch Uploads einschleusen, gibt es verschieden Möglichkeiten. Eine Möglichkeit ist es, in der Webanwendung selbst eine Virenüberprüfung anzustossen. Eine Alternative ist es, die Virenprüfung in einem vorgeschaltenem Apache vorzunehmen.

Diese Funktionalität kann mit dem Modul ModSecurity für den Apache erreicht werden. Dieses erkennt bei einem Request des Clients mitgesendete Dateien. Durch bestimmte Filterregeln kann ModSecurity so konfiguiert werden, dass ein Script auf dem Server aufgerufen wird:

SecRule FILES_TMPNAMES "@inspectFile /usr/local/share/clamav/modsecurity-clamav.pl" t:none,redirect:'%{REQUEST_FILENAME}?error=virus'

Diese Regel bewirkt, dass jede mitgesendete Datei auf der Festplatte zwischengespeichert wird, und das Script ausgeführt wird. Das Script selbst wiederrum ruft den Virenscanner auf, und parst das Ergebnis. Je nach dem ob ein Virus erkannt wird, wird ‘0′ oder ‘1′ zurückgegeben. Wenn kein Virus gefunden wurde, wird der Request wie gewohnt fortgesetzt. Im Fehlerfall wird eine definierte Aktion ausgeführt, wie z. B. die Weiterleitung zu einer Fehlerseite, die dem Nutzer eine Fehlermeldung ausgibt. In dem Beispiel wird ein Redirect mit der Request URL und einem Parameter error=virus zum Client gesendet.

Als Virenscanner empfiehlt sich der OpenSource Virenscanner ClamAV der für verschiedenste Systeme zur Verfügung steht. Das bereits oben beschrieben Script modsecurity-clamav.pl übernimmt den Aufruf und das Parsen des Scanneoutputs. Ein Beispiel Script findet sich hier.

Wenn noch keine Apache vorhanden ist, muss dieser als Reverse Proxy konfiguriert werden. Anfragen an den Apache müssen dabei an die eigentliche Webanwendung weitergeleitet werden. Zusätzlich muss ein URL Rewriting der Webanwendungsresponse stattfinden. Dies ist z. B. hier beschrieben.


03Jul

Als Ergänzung zu dem Beitrag “XFire-WebService-Client mit Maven2 generieren” möchte ich heute noch eine Implementierung für den Service vorstellen, damit man das Beispiel aus dem ersten Beitrag lokal nachvollziehen kann.

Die Implementierung benutzt den XFireServer, der auf Jetty basiert und damit recht leichtgewichtig ist. Bei Interesse werde ich in einem weiteren Beitrag noch die Integration mit Tomcat und Spring beschreiben.

Als Basis für dieses Beispiel dient die WSDL und der generierte Java-Code aus dem ersten Artikel. Die benötigten Dateien befinden sich in der Datei xfirefun-service.zip. Die Implementierung liefert angeforderte Dateien aus und benutzt die JaxbServiceFactory für die eigentliche Servicegenerierung.


02Jul

In einem aktuellen Projekt gab es die Erforderniss mehrere WebServices für ein Portal bereitzustellen. Da das Spring-Framework und Maven 2 zur Verfügung standen und ich mich etwas tiefergehend mit den Möglichkeiten des WebService-Frameworks XFire beschäftigen wollte, habe ich mich für eine Realisierung damit entschieden.

Heute stelle ich kurz vor, wie man mit Maven 2 und dem XFire-Plugin aus einer WSDL-Datei einen WebService-Client generieren und dann z.B. in einer Testklasse nutzen kann.

Zuerst benötigt man einmal eine WSDL-Beschreibung eines WebService, dafür stelle ich ein kleines Beispiel (xfirefun.wsdl) bereit, es kann aber prinzipiell eine beliebige valide WSDL-Datei genutzt werden.

Alle Dateien die zum Nachvollziehen dieser kurzen Anleitung benötigt werden, liegen in der Zip-Datei xfirefun.zip.

Für den Build mit Maven 2 das XFire-Maven-Plugin benötigt und konfiguriert. Der entsprechende Abschnitt in der pom.xml sieht folgendermaßen aus:

  ...
  <build>
    ...
    <plugins>
      ...
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>xfire-maven-plugin</artifactId>
        <version>1.0-SNAPSHOT</version>
        <executions>
          <execution>
            <goals>
              <goal>wsgen</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <package>de.communardo.ws.xfirefun</package>
          <profile></profile>
          <binding></binding>
          <outputDirectory>${project.build.directory}/generated-sources/client</outputDirectory>
          <wsdls>
            <wsdl>${basedir}/src/main/wsdl/xfirefun.wsdl</wsdl>
          </wsdls>
        </configuration>
      <plugin>
      ...
    </plugins>
    ...
  </build>
  ...

Wenn man nun mvn install aufruft, generiert Maven im Verzeichnis target/client die Webservice-Endpoint- und Datentypklassen. Die eine eigene Clientklasse (XfireFunClientTest.java) dann einfach folgendermaßen nutzen kann:

...
// Client erzeugen
FunClient client = new FunClient();
// Endpoint festlegen und SOAP-Proxy holen
Fun fun = client.getFun(endpoint);
// Request-Objekt erzeugen und befuellen
FunRequest request = new FunRequest();
request.setFileName(filename);
// Remotezugriff absetzen
try {
  FunResponse response = fun.getFile(request);
  FileOutputStream fos = new FileOutputStream(response.getFileName());
  fos.write(response.getData());
} catch (Exception e) {
  e.printStackTrace(System.err);
}
...