Startseite > Techblog > Softwareentwicklung
nächste Seite
dri

Den Auftakt zum letzten Tag auf der Basta! macht für mich Custom Field Types – Entwicklung und Einsatzmöglichkeiten mit Oliver Wirkus. Die Entwicklung eines Custom Field Type für SharePoint ist eher unspektakulär und wer das schon einmal gemacht hat, wird dazu hier nicht viel Neues erfahren. Einen Tipp möchte ich noch weitergeben: Für die Festlegung von Konfigurationseinstellungen bieten sich die Custom Properties in der fldtype_xxx.xml an – allerdings sollte man bedenken, dass diese bei einem Update immer wieder “überbügelt” wird (dennoch sind die Daten dort allemal besser aufgehoben als “hard coded”). Folgende “Unschönheiten” bzgl. Custom Field Types sollte man bei deren Verwendung bedenken: Artikel vollständig lesen »

Kommentar Feed Trackback URL
dri

Auf zum 2. Tag der Basta! Hauptkonferenz – und damit dem ersten der beiden SharePoint Days. Heute gibt es keine morgendliche Keynote, sondern es geht gleich in die Sessions – für mich ist das als erstes Sehenswertes aus SharePoint 2010 mit Tom Wendel. Erstaunlich für mich, dass nur ca. ein Drittel der anwesenden Entwickler Sharepoint 2010 überhaupt schon gesehen hat. Dementsprechend “basic” fällt die Vorstellung der Neuerungen aus – weshalb ich hier auch auf eine detaillierte Auflistung verzichte. Trotzdem ein paar “Bruchstücke”, die mir nennenswert erscheinen: Artikel vollständig lesen »

Kommentar Feed Trackback URL
thu

Dem Einen oder Anderen hat Visual Studio wahrscheinlich schon einmal mit dieser leicht dominierenden Bildschirmausgabe überrascht. Wahrscheinlich aber haben es die Meisten noch nie zu Gesicht bekommen, denn wir sind ja keine Copy & Paste Entwickler. :)

Das ist der besagte Hinweis:

Here you can see the error message thrown by visual studio

RDClip

Randbedingungen:
Ich verwende eine virtuelle Maschine(Windows Server 2003) unter Microsoft Virtual Server 2005 R2.

Das Problem tritt gelegentlich auf, wenn innerhalb der Host Maschine etwas kopiert wird und anschließend versucht wird, das soeben kopierte, in Visual Studio, auf der Entwicklungsmaschine, einzufügen.

Lösung:

Wie kann dieses Problem nun gelöst werden? Anfangs dachte ich, der Übeltäter wäre Visual Studio, und beendete einfach den devenv.exe Prozess. Irgendwann irritierte es mich aber, dass sobald diese Meldung auftauchte überhaupt kein Copy & Paste mehr funktionierte. Zu diesem Zeitpunkt fand ich heraus, dass der eigentliche, anfangs nicht verdächtige, Prozess rdpclip.exe der Schuldige war.

Um also in Visual Studio weiter arbeiten zu können, muss einfach der Prozess rdclip.exe beendet werden. Dies kann leicht über den  Task Manager vollführt werden.

Falls anschließend wieder Copy & Paste verwendet werden soll, nicht vergessen den RdpClip.exe Prozess wieder zu starten. Gefunden werden kann dieser im Verzeichnis C:\Windows\System32

Kommentar Feed Trackback URL
dri

Der erste Tag der Basta! Spring 2010 Hauptkonferenz neigt sich dem Ende entgegen. Begonnen hat er wie üblich mit einer Keynote, in diesem Fall 2010 – Cloud oder Desktop – wohin geht die Reise?.  Adressiert wurde damit das Spannungsfeld zwischen Azure 1.0 als “direkter” Cloud Computing Strategie, Windows 7 (“Hoch lebe der Desktop!”) und Silverlight 4.0 (“Three screens and a cloud“) irgendwo dazwischen. Die Keynote selbst erschöpfte sich dann allerdings hauptsächlich in einer Auflistung/Demonstration neuer (durchaus nicht schlechter) Features hauptsächlich von Visual Studio 2010 und TFS 2010 und blieb für mich eher blass. Artikel vollständig lesen »

Kommentar Feed Trackback URL
ast

Im Rahmen eines Projektes sollten XML Mockup Dateien in einer Datenbank gehalten und über eine Webservice-Schnittstelle ausgelesen werden. Für gewöhnlich habe ich aus der XSD per JAXB Java Klassen generiert und in Entity Beans gemappt, die anschließend in die Datenbank geschrieben werden. Um dieses, aus meiner Sicht recht aufwendige und fehleranfällige Mapping in die Entity Beans zu umgehen, habe ich mich nach einem alternativen Framework umgesehen und bin mit Hyperjaxb3 fündig geworden. Hyperjaxb3 geht einen Schritt weiter als JAXB, in dem es die generierten Klassen per Annotation zu vollständigen JPA Entitybeans macht. Aktuell steht Hyperjaxb3 in der Version 0.5.4 unter https://hyperjaxb3.dev.java.net zum Download bereit. Unterstützt werden Hibernate und Oracle TopLink, wobei es mit einigen Anpassungen auch mit OpenJPA und EclipseLink funktioniert. Aus meiner Sicht ist aber der Einsatz von OpenJPA (1.2.2) mit Hyperjaxb3 nicht zu empfehlen, da es zu Problemen mit den Relations kam (Es werden keine bidirektionalen Beziehungen unterstützt). Ein weiteres Problem sind die unterschiedlichen Datentypen, da JAXB und JPA nicht vollständig kompatibel sind. Beispiele kann man auf der z.Z. noch etwas lückenhaften Wiki Seite von Hyperjaxb3 finden. http://confluence.highsource.org/display/HJ3/Home

Der große Vorteil dieses Frameworks  ist, dass die Erzeugung der Klassen sehr leicht ins Maven eingebunden werden kann und das das Persistieren nur wenige Zeilen Code nötig macht.

Einbindung in Maven

Zum erzeugen der Beans ist eigentlich nur die Dependency für Hyperjaxb3 der bestehenden pom.xml hinzuzufügen:

Der Aufruf der Codegenerierung sollte sinnvollerweise in einem Profile-Zweig erfolgen, damit nicht bei jedem Compile die Klassengenerierung neu angestoßen wird.

Die Generierung kann dann per Aufruf des Profiles erfolgen: mvn install -Phyperjaxb


Objekt erzeugen und persistieren

In der Anwendung kann dann das Objekt aus dem XML mithilfe des Unmarshallers erzeugt …

und vom Entitymanager persistiert werden:

Optional kann am Unmarshaller noch die Validierung eingeschaltet werden:

Hyperjaxb3 kann bei der Erzeugung von komplexen Datenmodellen aus einer vogegebenen XSD sehr hilfreich sein. Es werden alle Relations, die persistence.xml mit allen nötigen Konfigurationen und die ObjectFactory erzeugt.

Kommentar Feed Trackback URL
dri

Wie unter meinem letzten Beitrag angekündigt, wurde am 25.01.2010 das PASS Treffen zu SQL Server 2008 R2 mit Georg Urban als Vortragendem nachgeholt. Wer nun (wie ich) bis dahin dachte, die Neuerungen in Release 2 würden sich schwerpunktmäßig auf Business Intelligence konzentrieren, wurde erst einmal eines Besseren belehrt. Um es auf den Punkt zu bringen: Die Schwerpunkte des SQL Server 2008 Release 2 sind Self-Service-BI, Multiserver-Management und Technologien für die Verarbeitung sehr großer Datenmengen.

Georg bot uns an diesem Abend mit einem aus mehreren Präsentationen konsolidierten Vortrag die Quintessenz der Neuerungen in SQL Server 2008 R2 dar.

Artikel vollständig lesen »

Kommentar Feed Trackback URL
rwi

Problem

Beim Aufruf einer Webseite mit integriertem TinyMCE WYSIWYG Editor über eine UMTS-Verbindung, kommt es bei einigen UMTS Providern zu JavaScript-Fehlern und der Editor wird nicht angezeigt. Führt man danach aber ein “Deep-Refresh” der Seite (z.B. über Strg+F5 im Firefox) aus oder verwendet stattdessen eine DSL-Verbindung, wird der Editor vollständig geladen und korrekt dargestellt.

 

Ursache

Die meisten Mobilfunkprovider leiten alle Requests über einen transparenten Proxy, welcher diverse Transformationen an der Response vornimmt, um das Transfervolumen zu senken. Zu diesen Transformationen gehört neben der stärkeren Komprimierung von Bildern meist auch das Einbinden von externen Dateien (CSS und JavaScript) in das Hauptdokument. Dabei werden die script Tags so umgeschrieben, dass jeweils das src Attribut entfernt (oder auch umbenannt wird) und der Inhalt der referenzierten JavaScript Datei als Inline-Skript zwischen dem öffnenden und schließenden Tag eingefügt wird. Dadurch schlägt letztlich die Initialisierung des TinyMCE fehl, da in dieser Phase das src Attribut des script Tags, welches die tiny_mce.js (bzw. tiny_mce_src.js). Datei einbindet, ausgewertet wird. Der Pfad zu dieser Datei wird als Basis-URL für den Download weiterer TinyMCE Dokumente interpretiert (z.B. Skripte der konfigurierten Plugins oder Dateien des eingestellten Themes). Das Fehlen des Attributs führt zu den JavaScript-Fehlern.
Ein “Deep-Refresh” dagegen bewirkt, dass der Browser der Anfrage den Cache-Control Header mit dem Wert no-cache hinzufügt. Dieser Header wird auch von den Proxies berücksichtigt und das Dokument unverändert ausgeliefert, so dass der TinyMCE normal initialisiert werden kann.

 

Lösungsmöglichkeit

Eine Möglichkeit, um das Problem zu lösen, ist es, dem TinyMCE auf einem anderen Weg die Basis-URL zum Download der ergänzenden Skripte mitzuteilen, so dass nicht das src Attribut ausgewertet werden muss. Hierbei muss zwischen den Einbindungsmöglichkeiten des Editors unterschieden werden.

1. Direkte Einbindung

Bei dieser Methode wird der Editor einfach durch Hinzufügen eines script Tags, das auf das Hauptscript tiny_mce.js (bzw. die nicht-komprimierte Variante mit allen Leerzeichen, Zeilenumbrüchen und Kommentaren tiny_mce_src.js) verweist, integriert (vgl. TinyMCE:Installation). Das Setzen der Basis-URL kann durch Initialisieren der globalen Variable tinyMCEPreInit erfolgen. Das Hauptskript erwartet, dass die Variable ein Objekt mit den Eigenschaften suffix, base und query referenziert. Die Member haben dabei die folgende Bedeutung:

  • suffix: entweder ein leerer String oder die Zeichenkette ‘_src’. Letztere sollte gesetzt werden, wenn die nicht-komprimierten Plugin-Skripte in das Dokument eingebunden werden sollen (z.B. zum Debuggen).
  • base: der Wert der zu verwendenden Basis-URL, welche auf das Verzeichnis der TinyMCE Installation zeigt. Wurde z.B. das tiny_mce.js Skript mit der Adresse “http://server.de/javascript/tiny_mce/tiny_mce.js” eingebunden, dann ist die Basis-URL “http://server.de/javascript/tiny_mce”.
  • query: erlaubt die Definition zusätzlicher Anfrageparameter, kann aber meist auf den leeren String gesetzt werden.

Ein vollständiges Beispiel, das die komprimierten Skripte verwendet sieht folgendermaßen aus:

<script type="text/javascript">
tinyMCEPreInit = {
    suffix: '',
    base: 'http://server.de/javascript/tiny_mce',
    query: ''
};
</script>
<script type="text/javascript" src="http://server.de/javascript/tiny_mce/tiny_mce.js" />

Hinweis: Die Variable findet sich in den aktuellen Versionen des TinyMCE (geprüft für 3.2.5, 3.2.7 und 3.3b1).

2. Enbindung über einen GZip Compressor

Bei dieser Variante wird nicht das Hauptskript in das Dokument eingebunden sondern ein Skript, das einen serverseitigen Compressor aufruft, der die benötigten TinyMCE JavaScript Dateien (Hauptskript, Plugins, Themes etc.) als ein GZip gepacktes JavaScript Dokument ausliefert (vgl. TinyMCE:Compressor). Das Skript des Compressors (tiny_mce_gzip.js) verwendet ebenfalls das src Attribut, um die Anfrage-URL für die serverseitige Komponente zu generieren. Um hier die Basis-URL zu setzen, muss die init Methode des in diesem Skript definierten tinyMCE_GZ Objekts ein wenig angepasst werden:

init : function(s, cb, sc) {
    var t = this, n, i, nl = document.getElementsByTagName('script');

    for (n in s)
        t.settings[n] = s[n];

    s = t.settings;
    if (s.baseUrl) {
        t.baseURL = s.baseUrl;
    } else {
        for (i=0; i<nl.length; i++) {
            n = nl[i];

            if (n.src && n.src.indexOf('tiny_mce') != -1)
                t.baseURL = n.src.substring(0, n.src.lastIndexOf('/'));
        }
    }
    if (!t.coreLoaded)
        t.loadScripts(1, s.themes, s.plugins, s.languages, cb, sc);
}

Die modifizierte Methode prüft, ob in den Settings eine baseUrl Eigenschaft vorhanden ist. Wird die Eigenschaft gefunden, wird sie als Basis-URL verwendet und die Auswertung des src Attributs übersprungen. Diese Eigenschaft kann dann einfach beim Initialisieren des Compressors gesetzt werden:

<script type="text/javascript">
tinyMCE_GZ.init({
    baseUrl: 'http://server.de/javascript/tiny_mce',
    ... normal init of compressor ...
});
</script>
<script type="text/javascript" src="http://server.de/javascript/tiny_mce/tiny_mce_gzip.js" />

Hinweis: Das Code-Beispiel für den Compressor wurde mit dem JSP Compressor in der Version 2.0.2 getestet, kann aber auch auf die .NET und PHP Compressoren übertragen werden, da der JavaScript Anteil gleich ist.

Kommentar Feed Trackback URL
sdi

Das Bauen und Ausliefern von normalen und eigenständigen Java Anwendungen die nicht in einem Webcontainer oder Applikationserver laufen sollen kann sich als schwierig erweisen. Die größten Probleme beim Erzeugen der Releases sind dabei die folgenden Punkte:

  • es müssen die benötigten Bibliotheken aufgelöst und mit in des Release gepackt werden
  • die Java Applikation muss in den meisten Fällen auf dem Zielsystem als Dienst laufen (Deamon)
  • das Erstellen und Packen des Releases sollte automatisiert erfolgen

Das Maven 2 Plugin appassembler zielt auf diesen Anwendungsfall ab und ermöglicht

  • das automatisierte Erstellen von Skripten zur einfachen Ausführung der Applikation
  • das Erzeugen von Releases die es ermöglichen, die Java Anwendung als Dienst zu betreiben
  • die Erzeugung von Repositories die alle nötigen Bibliotheken für die Anwendung enthalten.

Die Konfiguration des Plugins ist aber leider nicht ganz so einfach da die Dokumentation eher schlecht ist und ich auch auf Bugs im Plugin selber gestoßen bin.

Im Folgenden ist  eine Konfiguration als Beispiel aufgelistet die eine Deamonapplikation erzeugt.  Um die Applikation als Dienst betreiben zu können wird vom Plugin  der weit verbreitete Java Service Wrapper eingesetzt.

Beispielkonfiguration

<plugin>
 <groupId>org.codehaus.mojo</groupId>
 <artifactId>appassembler-maven-plugin</artifactId>
 <configuration>
   <repositoryLayout>flat</repositoryLayout>
   <includeConfigurationDirectoryInClasspath>true</includeConfigurationDirectoryInClasspath>
   <target>${project.build.directory}/appassembler</target>
     <daemons>
       <daemon>
         <id>daemon-app</id>
         <mainClass>de.communardo.appassembler.Launcher</mainClass>
         <commandLineArguments>
           <commandLineArgument>start</commandLineArgument>
         </commandLineArguments>
         <platforms>
           <platform>jsw</platform>
         </platforms>
         <jvmSettings>
           <extraArguments>
             <extraArgument>-server</extraArgument>
           </extraArguments>
           <initialMemorySize>64M</initialMemorySize>
           <maxMemorySize>512M</maxMemorySize>
           <systemProperties>
             <systemProperty>property=value</systemProperty>
           </systemProperties>
         </jvmSettings>
         <generatorConfigurations>
           <generatorConfiguration>
             <generator>jsw</generator>
             <includes>
               <include>linux-x86-32</include>
               <include>linux-x86-64</include>
             </includes>
             <configuration>
               <property>
                 <name>configuration.directory.in.classpath.first</name>
                 <value>conf</value>
               </property>
               <property>
                 <name>set.default.REPO_DIR</name>
                 <value>lib</value>
               </property>
               <property>
                 <name>wrapper.logfile</name>
                 <value>logs/wrapper.log</value>
               </property>
               <property>
                 <name>wrapper.logfile.maxsize</name>
                 <value>10m</value>
               </property>
               <property>
                 <name>wrapper.logfile.maxfiles</name>
                 <value>5</value>
               </property>
               <property>
                 <name>wrapper.console.title</name>
                 <value>appassembler application</value>
               </property>
               <property>
                 <name>run.as.user.envvar</name>
                 <value>root</value>
               </property>
               <property>
                 <name>wrapper.working.dir</name>
                 <value>d:\</value>
               </property>
               <property>
                 <name>set.default.APP_BASE</name>
                 <value>d:\</value>
               </property>
             </configuration>
           </generatorConfiguration>
         </generatorConfigurations>
       </daemon>
     </daemons>
   </configuration>
   <executions>
     <execution>
       <id>create-release</id>
       <goals>
         <goal>create-repository</goal>
         <goal>generate-daemons</goal>
       </goals>
       <configuration>
         <assembleDirectory>${project.build.directory}/appassembler/jsw/daemon-app</assembleDirectory>
         <repoPath>lib</repoPath>
       </configuration>
       <phase>package</phase>
     </execution>
   </executions>
</plugin>

Parameter

mainClass Die auszuführende Klasse.
commandLineArguments Parameter die beim Aufruf mit übergeben werden sollen.
platforms Die Liste der Plattformen für die ein Release erzeugt werden soll, hier “jsw” (Java Service Wrapper).
jvmSettings Faßt Konfigurationsparameter für die Java VM zusammen wie z.B. Speichereinstellungen, zusätzliche System Properties die gesetzt werden sollen oder Parameter für den Aufruf der VM
includes Ermöglicht die optionale Definition der Zielumgebungen, hier linux 32 und 64 bit, kann auch weggelassen werden.
configuration.directory.in.classpath.first Legt fest, dass ein bestimmtes Verzeichnis mit in den Classpath der VM aufgenommen wird. Darin lassen sich gut Konfigurationsdateien ablegen die von der Applikation beim Betrieb gebraucht werden.
set.default.REPO_DIR Das Verzeichnis in denen sich die Bibliotheken befinden.
run.as.user.envvar Der Nutzer mit dem die Applikation ausgeführt werden soll, wichtig beim Betrieb in Linuxumgebungen.
wrapper.xxx Einstellungen für den Java Service Wrapper wie z.b. das Arbeitsverzeichnis, Anzahl der Logfiles usw.
assembleDirectory, repoPath Diese Parameter konfigurieren das Zielverzeichnis für das zu erstellende Repository. Leider wird bei den Standardwerten das Repository in einem anderen Verzeichnis erzeugt als der Java Service Wrapper, daher ist eine Anpassung nötig.
<goals>
<goal>create-repository</goal>
<goal>generate-daemons</goal>
</goals>
Erzeugt die definierten Deamons und ein Library Repository mit allen Abhängigkeiten des Projekts.

Kommentar Feed Trackback URL
lli

Sucht man im Internet nach Lösungsmöglichkeiten für das Testfallmanagement mit Atlassian JIRA, so findet man ein paar Vorschläge wie den im Artikel „Customise JIRA For Test Case Management“. Bei dieser Lösung werden die Testfälle als eigene Vorgänge erfasst und für jede Testausführung wird ein neuer Untervorgang angelegtDarstellung des Testfallmanagement nach Atlassian Documentations und der entsprechenden Release-Version zugeordnet. Die Vorgänge sind mit der Anforderung verknüpft, haben allerdings keinen direkten Einfluss auf diese (wie es bei Untervorgängen die Möglichkeit ist). Über angepasste Bildschirme für die Eingabe, Bearbeitung, Ansicht und den Statusübergang sowie eigene Workflows wird die Sache abgerundet. Im praktischen Einsatz bei Communardo hat sich diese Lösung allerdings nicht durchgesetzt, da sie sehr Aufwendig ist und ein paar wichtige Merkmale fehlen, wie z.B. die Testausführungsreihenfolge oder die direkte Statusabfrage der Testergebnisse aus der Anforderung heraus.

Nach weiteren Testphasen anderer Lösungsmöglichkeiten haben wir uns eine eigene Lösungsmöglichkeit überlegt. Es wird ein neuer Untervorgang „Testfall“ angelegt, welcher mit benutzerdefinierten Spalten (z.B. für Testschritte, erwartetes Ergebnis) versehen wird und über einen eigenen Workflow verfügt.Darstellung Testfallmanagement nach Communardo Nun werden unter der jeweiligen Anforderung  die Testfälle erfasst und bei der Ausführung entsprechend die Ergebnisse darin vermerkt und der Status verändert. Damit kann der Projektleiter sehen, wie der Stand bezüglich der Anforderung ist und der Aufwand seitens Testfallerfassung ist sehr gering. Außerdem kann so die Ausführungsreihenfolge mit der Sortierung von Untervorgängen festgelegt werden. Es gibt natürlich auch hier Abstriche, wie z.B. die Sichtbarkeit der Testfälle für die Entwickler, aber mit etwas Anstrengung kann auch dieses Problem über die sogenannten Sicherheitsstufen gelöst werden.

Zusammenfassend kann man sagen, es gibt verschiedene Lösungsmöglichkeiten um mit Atlassian JIRA ein Testfallmanagement zu betreiben. Welches davon die richtige Lösung für das eigene Unternehmen ist, muss analysiert und auch probiert werden. Kleine Projekte eignen sich am Anfang sehr gut, um unter realen Bedingungen Erfahrungen zu sammeln.

Kommentar Feed Trackback URL
tis

Pünktlich gegen 10:000 Uhr startet am 21.01.2010 das erste Liferay User Group Treffen in Frankfrut/Main im neuen Jahr. Der Raum in der Geschäftsstelle des Planungsverbandes Ballungsraum Frankfurt/Main war gut besucht.
  
Im ersten Vortrag des Tages stellten Mitarbeiter der Firma form4 aus Berlin eine Integration des CMS Alfresco in Liferay vor. Artikel vollständig lesen »

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