07Jan

In einem existierenden Java2 1.4 Projekt sollen generierte XFire-Clientklassen verwendet werden. Der XFire-Codegenerator verwendet JAXB2 und ist damit auf einige Java2 5.0-Features wie Annotations angewiesen. Der Umstieg auf Java2 5.0 ist in dem Projekt keine Option und deshalb habe ich eine Möglichkeit gebraucht, die generierten Klassen mit Java2 1.4 zu verwenden.

Nach ein paar Recherchen habe ich mich für die Verwendung des freien Retrotranslator-Tools entschieden und eine Proof-Of-Concept-Implementierung realisiert. Retrotranslator kann sowohl zur Compile-Zeit als auch zur Laufzeit den Java2 5.0 Bytecode in Java2 1.4 Bytecode umwandeln. Für den eigenen Code habe ich mich für die Umwandlung zur Compilezeit entschieden und für verwendeten Code Dritter für die Umwandlung zur Laufzeit (Just in Time Compilierung).
Artikel vollständig lesen »


05Dez

Mithilfe des Site-Plugins ist es möglich ohne großen Aufwand eine Projekt Homepage mit allen wichtigen Informationen zu erstellen. Neben generierten Code Audits, Unit-Test Reports oder SourceCode Reviews können auch eigene Inhalte problemlos mit eingebunden werden, was die Projektsite zu einer universellen Informationsplattform für Entwickler macht.

Leider gibt es bei Projekten mit mehrenen Modulen häufig Probleme in der Verlinkung der generierten Html-Seiten. Da die Super-Pom zwar alle Sub-Modules kennt aber nicht umgekehrt, sind die Module auf der Projekt-Page auch nur in eine Richtung verlinkt. Möchte man nun zu einem Parent-Modul navigieren, muss man entweder die Browser-Hierarchie bemühen oder die Startseite erneut aufrufen.

Direkte Modulverlinkung

Die Lösung für dieses Problem ist die site.xml. In dieser Datei kann das Aussehen und die Navigation der Projektseite individuell angepasst werden. Den generellen Aufbau der site.xml findet man hier. Damit nun die Verlinkung funktioniert muss in jedem Modul im Verzeichnis src/ ein Ordner site, zusammen mit der Datei site.xml angelegt werden. Eine leere site.xml erzeugt eine blank-page, daher muss für die Standardfunktionalität folgender Content eingebunden werden:

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="Maven">
  <body>
    <menu ref="parent"/> <!-- Erzeugt Link zum Parent-Modul-->
    <menu ref="modules"/>
    <menu ref="reports"/>
  </body>
</project>

Mit mvn site-deploy werden nun die zugehörigen Projektseiten erzeugt. Ein Aufruf der Startseite überrascht noch nicht, es werden wie gewohnt alle Module angezeigt.

                       

Auf den Seiten der Sub-Modules hingegen, erscheint nun ein Link zum jeweiligen Parent-Modul oben in der Navigationsleiste.

                       

 Krümelpfad Verlinkung

Die direkte Verlinkung erfüllt zwar ihren Zweck, ist aber gerade bei mehreren Hierarchiestufen nicht gerade praktisch. Besser wäre da doch ein Krümelpfad mit dem man beliebig zwischen den Seiten wechseln kann. Wieder hilft dabei die site.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="Maven">
  <body>
    <breadcrumbs>
      <item name="<ModulName>" href="index.html" mce_href="index.html"/>
    </breadcrumbs>

    <menu ref="modules"/>
    <menu ref="reports"/>
  </body>
</project>

In dem Item-Tag wird dabei nur der Name des aktuellen Moduls eingetragen und als href die index.html. Maven baut dann automatisch den Pfad synchron zur Modulhierarchie zusammen. Die nachfolgenden Abbildungen zeigen eine Projektseite mit drei Hierarchieebenen.

                       

                       

                       

Technorati Tags: , ,

15Nov

Bei der Verwendung von Spring stellt sich im Buildmanagement die Frage wie mit Properties umgegangen wird. So hat jeder Test-, Live- und Entwicklungsserver seine eigene Datenbank oder andere unterschiedliche Einstellungen. Eine oft gewählte Variante ist die Ersetzung der Properties durch den Buildprozess. Dies hat allerdings den Nachteil, dass für eine Änderung der Properties der Buildprozess neu ausgeführt werden muss.

Mit Spring bietet sich dabei eine Alternative: Hier kann ein Propertyfile welches z. B. im Classpath liegt eingebunden werden:

<bean id="propertyPlaceholder" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location" value="classpath:hibernate.properties" />
</bean>

Die Properties, die dann in dem File ‘hibernate.properties’ definiert sind, können innerhalb der Springkonfiguration genutzt werden:

...
<property name="hibernateProperties">
<props>
<prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
<prop key="hibernate.dialect">${hibernate.dialect}</prop>
<prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
...
</props>
</property>
...

Das Property File selbst ist dabei einfach wie erwartet:

hibernate.show_sql=true
hibernate.dialect=org.hibernate.dialect.PostgreSQLDialect
hibernate.hbm2ddl.auto=update


24Aug

Nach dem gestrigen Erfolg folgte heute eine Anforderung, die den Wechsel zu einem anderen Maven2-Plugin und einer neuen Mapping-Datei führte.

Die neue Anforderung war, dass Attribute aus der DTD auf andere Typen als String gemappt werden sollen. Da DTDs keine Typisierung wie XML-Schema kennen, muss dies mit einem Mapping-File geschehen. Das Maven2-Plugin aus dem gestrigen Artikel war leider mit dem Mapping der Attribute überfordert.

Jetzt wurde das Maven2-JAXB-Plugin von java.net verwendet, damit ändert sich die pom.xml folgendermaßen:

<?xml version="1.0" encoding="UTF-8"?>
<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.mms-dresden</groupId>
  <artifactId>hsp-search-gen</artifactId>
  <name>Hilfe- und Support-Portal generierter Code fuer die Suche</name>
  <version>0.1-SNAPSHOT</version>
  <parent>
    <groupId>de.mms-dresden</groupId>
    <artifactId>hsp</artifactId>
    <version>0.1-SNAPSHOT</version>
  </parent>
  <description>Generierter Code fuer die Suche im Hilfeportal</description>
  <build>
    <plugins>
      <plugin>
        <groupId>org.jvnet.jaxb2.maven2</groupId>
        <artifactId>maven-jaxb2-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>generate</goal>
            </goals>
            <configuration>
              <generateDirectory>${project.build.directory}/generated-sources/jaxb</generateDirectory>
              <extension>true</extension>
              <schemaLanguage>DTD</schemaLanguage>
              <schemaIncludes>
                <schemaInclude>*.dtd</schemaInclude>
              </schemaIncludes>
              <bindingIncludes>
                <bindingInclude>*.jaxb</bindingInclude>
              </bindingIncludes>
              <verbose>true</verbose>
              <args>
                <arg>-Xinject-listener-code</arg>
              </args>
            </configuration>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>org.jvnet.jaxb2-commons</groupId>
            <artifactId>property-listener-injector</artifactId>
            <version>1.0</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>

  <repositories>
    <repository>
      <id>maven2-repository.dev.java.net</id>
      <url>http://download.java.net/maven/2/</url>
    </repository>
  </repositories>

  <pluginRepositories>
    <pluginRepository>
      <id>maven2-repository.dev.java.net</id>
      <url>http://download.java.net/maven/2/</url>
    </pluginRepository>
  </pluginRepositories>

  <dependencies>
    <dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
    </dependency>
  </dependencies>
</project>

Bei der Angabe der Repository-Pfade muss man aufpassen, weil die Angaben auf der Projektseite des Plugins inzwischen nicht mehr stimmen. Stattdessen mussten die Pfade aus der Repositoryseite von java.net verwendet werden.

Die Dependency-Versionen sind jetzt im Parent-POM definiert, entsprechen aber den Versionen aus dem gestrigen Beitrag.

Das Mapping mappt jetzt das Attribut HITCOUNT des Elements NAVIGATIONENTRY auf den Java-Typ int (genauer gesagt den Wrapper Integer um auch null-Werte darstellen zu können) und sieht jetzt folgendermaßen aus:

<?xml version="1.0" ?>
<!--
	The syntax of the binding file for DTD is defined in the JAXB EA.
	See vendorSchemaLangs.html for details.
-->
<xml-java-binding-schema xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
  xmlns:ci="http://jaxb.dev.java.net/plugin/listener-injector">

  <!-- specify the package name for the generated code -->
  <options package="de.mms_dresden.mip.hsp.base.services.search" />
  <xjc:serializable/>  

  <element name="NAVIGATIONENTRY" type="class">
    <attribute name="HITCOUNT" convert="int" />
  </element>
</xml-java-binding-schema>

22Aug

Heute mussten aus einer existierenden DTD ein paar JAXB2-Binding-Klassen generiert werden. Nach einigem probieren ist dies mit folgender pom.xml und einem passenden Binding-File gelungen.

Hier die pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<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.mms-dresden</groupId>
  <artifactId>hsp-search-gen</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <description>Generierter Code fuer die Suche im Hilfeportal</description>
  <build>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>jaxb2-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>xjc</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <schemaDirectory>${basedir}/src/main/dtd</schemaDirectory>
          <dtd>true</dtd>
          <xmlschema>false</xmlschema>
          <schemaFiles>FastSearchResult.dtd</schemaFiles>
          <strict>false</strict>
          <verbose>true</verbose>
          <explicitAnnotation>true</explicitAnnotation>
          <packageName>de.mms_dresden.mip.hsp.base.services.search</packageName>
        </configuration>
      </plugin>
      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <configuration>
          <source>1.5</source>
          <target>1.5</target>
        </configuration>
      </plugin>
    </plugins>
  </build>
  <dependencies>
    <dependency>
      <groupId>javax.xml.bind</groupId>
      <artifactId>jaxb-api</artifactId>
      <version>2.0</version>
    </dependency>
    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-impl</artifactId>
      <version>2.0.3</version>
    </dependency>
    <dependency>
      <groupId>com.sun.xml.bind</groupId>
      <artifactId>jaxb-xjc</artifactId>
      <version>2.0.3</version>
    </dependency>
  </dependencies>
</project>

und hier noch das passende File FastSearchResult.xjb:

<?xml version="1.0" encoding="UTF-8"?>
<xml-java-binding-schema>
<options package="de.mms_dresden.mip.hsp.base.services.search" />
<element name="SEGMENTS" type="class" root="true" />
</xml-java-binding-schema>

Die generierten Klassen landen damit in target/generated-sources/jaxb

Technorati Tags: , , , ,

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);
}
...