14Jul

Auch die zweite Veranstaltung der Java User Group Saxony kann als voller Erfolg bezeichnet werden. Shaun Smith, Project Lead des EclipseLink Projektes und Produktmanager für Oracle TopLink, gab am 09.07.2008 einen Überblick über die Features und die Funktionsweise von EclipseLink.

Die Firma ubigrate hat diese Veranstaltung an der Informatik Fakultät der TU-Dresden in Zusammenarbeit mit dem JUG Saxony Team für die hiesige User Group organisiert und somit mehr als 50 Teilnehmern einen informativen und unterhaltsamen Abend ermöglicht.

Shaun Smith ging während seines Vortrages detailliert auf die Java Persistence API und die Referenzimplementierung EclipseLink ein. Dabei ist insbesondere die Vielseitigkeit des Frameworks hervorzuheben. Neben Objekt-Relationalem Mapping (ORM) stellt es Funktionen zum Objekt-XML Mapping (in Version 1.0 noch nicht 100% JAXB 2.0 kompatibel) sowie Unterstützung für Service Data Objects (SDO) 2.1 zur Verfügung. Sollte dies noch nicht genügen kann EclipseLink leicht um weitere Mapping Ziele erweitert werden wie Shaun Smith anhand eines JSON Beispiels demonstriert hat.

Neben der Vorstellung von technischen Details und der ein oder anderen Anekdote aus dem Projektgeschäft (wer sich dafür interessiert sollte die kommenden JUG Veranstaltungen nicht verpassen ;-) ) wurden auch die verschiedenen Mappings und das Zusammenspiel mit den Eclipse Dali JPA Tools im Rahmen von Live Demonstrationen vorgeführt.

Am Tag unserer Veranstaltung wurde EclipseLink 1.0 veröffentlicht und somit für den Produktiveinsatz freigegeben. Einen genaueren Blick ist es auf alle Fälle wert.

Das nächste Treffen der JUG Saxony ist für Oktober 2008 geplant. Das Thema lautet Rich Client Platform (RCP) Entwicklung mit Java.

Informationen zur kommenden Veranstaltung gibt es demnächst auf der Webseite der JUG Saxony unter http://www.jugsaxony.de. Die Folien zum EclipseLink Vortrag sind ebenfalls auf dieser Seite zu finden.

Einen Bericht zum Treffen in englischer Sprache gibt es im ubigrate Blog.

Technorati Tags: , , , , , ,

11Apr

Am 03. April 2008 fand das erste Treffen und damit die Gründungsveranstaltung der Java User Group Saxony in den Räumen der Communardo Software GmbH statt. Diese Gruppe wurde auf Initiative von Torsten Rentsch (Communardo Software GmbH) und Falk Hartmann (ubigrate) Anfang 2008 ins Leben gerufen. Ziel ist es den Wissensaustausch im Java Umfeld zu fördern sowie Kontakte zwischen Firmen und wissenschaftlichen Einrichtungen zu knüpfen.

JUG Saxony Gründungsveranstaltung

Vor 43 interessierten Teilnehmern wurde die Model Driven Architecture (MDA) vorgestellt. Herr Professor Aßmann (Lehrstuhl Softwaretechnik der TU Dresden) gab eine konzeptionelle Einleitung zum Thema und betrachtete dabei insbesondere den Zusammenhang zwischen MDA und Component-based Software Engineering (CBSE) (Folien). Herr Torsten Lunze (Communardo Software GmbH) stellte mit seinem Vortrag (Folien) den Bezug zur Praxis anhand eines Beispiels aus dem Projektgeschäft her und erläuterte u.a. die Vor- und Nachteile von MDA beim Einsatz der Open Source Software AndroMDA. Beim anschließenden Buffet blieb Zeit Kontakte zu knüpfen und das Thema im Gespräch zu vertiefen.
Mindestens einmal pro Quartal wird nun eine Veranstaltung der JUG Saxony stattfinden. Das nächste Treffen ist am 9. Juli 2008 in den Räumen der TU Dresden geplant. Das Thema wird voraussichtlich EclipseLink (JPA 2.0 RI, JSR 317) sein.
Gern können Sie sich als Mitglied der JUG Saxony auf unserer Website http://groups.google.de/group/jug-saxony registrieren. Für Anregungen und Wünsche sind wir stets offen.

Technorati Tags: , , , ,

21Jan

Da es sich bei Axis2 um eine Neuentwicklung gegenüber der Vorgängerversion handelt, wurde ein komplett anderes Data Binding Konzept umgesetzt. Zum Einsatz kommen bestehende Lösungen wie:

die in Axis2 integriert werden. XMLBeans stammen ursprünglich von BEA Systems und wird von Apache weiterentwickelt. XMLBeans heben den Informationsgehalt eines XML-Infosets während der Verarbeitung auf, so dass Metadaten zur Verfügung stehen, die bspw. für eine Schema-Validierung genutzt werden können. Wenn XMLBeans als Data Binging genutzt werden sollen, muss “-d xmlbeans” als Parameter angegeben werden. (Defaultwert ist ADB):

WSDL2JAVA ... -d xmlbeans meine.wsdl

Das Framework generiert für jeden benutzerdefinierten Datentyp eine Interfaceklasse, mit der man bei der Entwicklung in Berührung kommt. Alle Interfaces erben von XMLObject und erhalten eine interne statische Inner Class “Factory” mit der eine Klasse des jeweiligen Types erzeugt werden kann. Beispiel zur Erzeugung eines Objektes vom Typ Kunde:

KundeDocument kundeDoc = KundeDocument.Factory.newInstance();

Ein XML-Document kann über die Methode “save” in ein XML-Format serialisiert werden. Mit “xmlText” wird ein String als XML zurückgegeben.

String kundeXml = kundeDoc.xmlText();

kundeDoc.save(new File("kundeDoc.xml"));

Andere Data Bindings bilden Datantypen wie bspw. xsd:String, xsd:Token, xsd:anyUrl oder xsd:Name auf String ab. XMLBeans bietet hierfür eigene Datentypen, um die unterschiedlichen Wertebereiche und semantischen Bedeutung zu behalten.

Technorati Tags: , , , , ,

18Jan

Für gezielte Datenbankexporte oder -views möchte man oft eine Zeile für einen Eintrag in der SQL Abfrage erhalten. Beim Verknüpfen von mehreren Tabellen führt dies bei 1:n oder n:m Beziehungen zu dem Nachteil, dass für die Basistabelle mehrere Zeilen entstehen. Zur Verdeutlichung sei folgendes Beispiel (in PostgreSQL) gegeben:

create table account (
ID BIGINT not null,
EMAIL CHARACTER VARYING(1024) not null unique,
primary key (ID)
);


create table history (
ID BIGINT not null,
ACCOUNT_FK BIGINT not null,
ENTRY CHARACTER VARYING(1024) not null unique,
primary key (ID)
);

Ziel soll es sein, ein Abfrage zu erstellen, die alle Accounts und die dazu zugehörigen Historyeinträge zurückliefert. Allerdings soll pro Account nur eine Zeile verwendet werden.

Folgende Abfrage führt nicht zum Ziel:

select account.email, history.entry
from account, history
where account.id = history.account_fk;

Eine Möglichkeit ist es, die Einträge in der History zu verknüpfen, z. B. über ein concat Funktion. Wenn diese als Aggregatfunktion zur Verfügung steht, kann diese in einem group by verwendet werden.

In PostgreSQL ist dies wie folgt möglich:

CREATE AGGREGATE textcat_all(
basetype = text,
sfunc = textcat,
stype = text,
initcond = ''
);

Mit folgender Abfrage kommt man dann zu dem Ziel nur noch eine Zeile pro Account zu erhalten:


select account.email, textcat_all(history.entry || ',')
from account, history
where account.id = history.account_fk;
group by account.email

(Siehe dazu auch hier http://archives.postgresql.org/pgsql-novice/2003-09/msg00177.php)

In mysql ist dies noch einfacher, denn hier existiert bereits eine solche Aggregationsfunktion: http://dev.mysql.com/doc/refman/5.0/en/group-by-functions.html#function_group-concat


10Jan

Standardmäßig generiert die Hibernate Andromda Cartridge die Mappingdateien so, dass eine Sequenz für alle Tabellen genutzt wird. Eine Umstellung auf eine Sequenz für jede Tabelle ist dabei sehr einfach möglich. In der andromda.xml muss die Hibernate Cartridge einfach wie folgt angepaßt werden:

<namespace name="hibernate">
<properties>
...
<property name="defaultHibernateGeneratorClass">sequence</property>
<property name="sequenceIdentifierSuffix">_seq</property>
...
</properties>
</namespace>

Der finale Sequzenzname ergibt sich dabei aus dem Tabellennamen plus den Wert, der der Property sequenceIdentifierSuffix zugeordnet ist.


08Jan

Um Webdienste vor Missbrauch durch Webbots zu schutz werden CAPTCHA (Completely Automated Public Turing test to tell Computers and Humans Apart) eingesetzt. Eine javabasierte Lösung, die einfach zu integrieren und implementieren ist, bietet das Framework jCaptcha an (http://jcaptcha.sourceforge.net). Es steht unter LGPL und bietet eine Reihe vordefinierter Captchaimages an. Im folgenden möchte ich beispielhaft erläutern, welche Schritte nötig sind, um eine Captchalösung mithilfe des jCapchta-Frameworks in eine bestehende J2EE Anwendung einzubinden.

japchta1-1

  1. Ein Nutzer fordert im Browser eine Seite an, die durch ein Captcha geschützt werden soll.

  2. Das Template enthält das Captcha-Image und ein Textfeld für die Lösung. Als Source für das Image wird “/jcaptcha„ angegeben.

    japtcha2-1

  3. Die Singleton Captchaservice-Klasse wird aus dem Template heraus aufgerufen. Weil Pattern „/jcaptcha“ aus Template auf die CaptchaService Klasse mapped. Das Mapping muss in der web.xml definiert werden.

    jacptcha3

  4. Beispiel einer einfachen CaptchaService implementation:

    jacptcha4-2

  5. Das generierte Captchaimage in den Response legen und an Template senden. Der Contenttype des Responses muss “jpeg” sein. Beispiel:

    jacptcha5

  6. Zum Schluss muss noch die Klasse zur Überprüfung des Ergebnisses implmentieren werden. Bsp:jcaptcha6

Technorati Tags: , ,

07Jan

Das Webservice Framework Axis2 von Apache steht seit 2005 in der Version 2 zur Verfügung und bietet einige Vorteile gegenüber der Vorgängerversion. Aus meiner Sicht sind es vor allem Performance Steigerung, höhere Flexibilität beim Deployment von Services und eine verbesserte Unterstützung von aktuellen Standards, die einen Einsatz von Axis2 sinnvoll macht.

Anhand eines Beispieles soll im Folgenden schrittweise gezeigt werden, wie eine einfache Axis2 Anwendung mit Eclipse und Web Tools Platform 2.0.1 entwickelt werden kann.

Für dieses Beispiel wird benötigt:

  1. WTP in Version 2.0.1 (http://www.eclipse.org/webtools)
  2. Tomcat 5.5 (http://tomcat.apache.org)
  3. AXIS2 Framework 1.2 als Standard Binary Distribution (http://ws.apache.org/axis2/download.cgi)

 

Vorbereitung im Eclipse:

  1. Tomcat einbinden (Preferences > Server > Installed Runtimes)
  2. Axis2 einbinden (Preferences > Webservices > Axis2 Preferences > Axis2 Runtime Location)

 

Erstellen einer Anwendung

  1. Neues DynamicWeb-Projekt anlegen und Axis2 Funktionalität einbinden (File -> New -> Other… -> Web -> DynamicWeb Project)

     

    new Project

  2. Eigene Serviceklasse erstellen und implementieren. (File -> New -> Class) Beispiel:

     

    bsp_class

  3. Webservice erstellen (File -> New -> Other… -> Web Services -> Web Service) . Im Wizard die Serviceklasse auswählen und Webservice Type: „ Bottom up Java bean Web Service“; Server: „Tomcat v5.5 Server“ ; WICHTIG Web Service Runtime: „Apache Axis2″. Optional kann ein Testclient erstellt werden.

    service

  4. Service.xml erzeugen lassen oder eine Vorhandene einbinden
  5. Server starten, Anwendung deployen und testen. Unter “http://localhost:8080/WebserviceTest/” steht dann eine Administrationsoberfläche von Apache zur Verfügung, auf der alle Services aufgelistet sind.
  6. Optional kann ein Testclient erstellt werden. (New > ohter > Web Services > Web Service Client)

Link Tipp: Eclipse Plug-In zur Codegenerierung für Axis2 (http://ws.apache.org/axis2/tools/1_2/eclipse/wsdl2java-plugin.html)

 

 

Technorati Tags: , , , ,

30Dez

OutOfMemory ist eines der am häufigsten auftretenden Probleme bei Java-basierten Webapplikationen. Die Ursachen dafür sind genau so vielschichtig wie die Möglichkeiten der Analyse. Ziel dieses Artikels ist es, sowohl die Grundlagen wie auch mögliche Lösungswege zu zeigen.

Bevor man jetzt leichtfertig die Software umprogrammiert (da man ja genau weiß, wo das Problem liegt), sollte man mit einer ausführlichen Analyse beginnen. Nicht selten kommt es vor, dass Software (Parameter der JVM) oder sogar das Betriebssystem nicht korrekt konfiguriert sind.

Die Process Size

Die Process Size ist der maximal verfügbare Speicher für den Prozess. Dieser ist abhängig von der Hardware und vom Betriebssystem. In einer 32 Bit-Architektur kann die Process Size maximal 4 GB sein. Für einen Java-Prozess gibt es folgende Bereiche, die im Speicher des Prozesses liegen (siehe Abbildung 1):

  • Java Heap - Der Heap ist der Speicher, in dem die Java Objekte erzeugt und verwaltet werden.
  • Permanent Generation - Die Permanent Generation ist der Speicher, in dem die JVM sich selber verwaltet. In diesem Speicher werden auch die Klassen durch den ClassLoader geladen.
  • Nativ Code - Jeder Java-Prozess benötigt auch Speicher für den Native Code. Das sind C-Bibliotheken des Betriebssystems für den Zugriff auf Systemressourcen. Zum Beispiel der Zugriff aufs Dateisystem.

Abbildung 1: Schematischer Aufbau der Speicherverteilung eines Java-Prozesses

Der Speicher für den Native Code ist nicht explizit einstellbar. Er ergibt sich aus der Differenz zwischen Process Size, Heap und Permanent Generation. Dieser Speicher darf nicht zu knapp bemessen sein, denn es kann auch OutOfMemory im Native Code geben.

Die Java Heap Size

Die Java Heap Size gibt die Größe des Speichers an, der für die Erzeugung und Verwaltung der Java-Objekte verwendet werden kann. Die Größe des Heaps ist begrenzt. Wird keine Größe explizit angegeben, wird die Defaulteinstellung verwendet. Diese variiert von Betriebssystem zu Betriebssystem. Wenn man wirklich sicher gehen möchte, stellt man die Größe explizit ein:

    -Xms[Bytes]m : initiale Größe des Heaps beim Starten des Prozesses
    -Xmx[Bytes]m : maximale Größe des Heaps über den gesamten Lebenszeitraum

Der Heap teilt sich in zwei große Bereiche: der New Generation und der Old Generation (siehe Abbildung 2).
Wie die Namen schon vermuten lassen, befinden sich in der New Generation die ganzen neuen, jungen und kurzlebigen Java-Objekte und in der Old Generation die langlebigen Java-Objekte.

Abbildung 2: Aufteilung der Speicherbereiche im Heap

Das Verhältnis zwischen New und Old Generation ist aus Speichersicht der größte Unterschied zwischen einer Desktop- und einer Serveranwendung. Eine Desktopanwendung läuft in der Regel einen Arbeitstag, also ca. 8 h. Eine Serveranwendung läuft 24 h, 7 Tage die Woche und das mehrere Monate. Daran kann man schon erkennen, dass es bei einer Desktopanwendung mehr jüngere Objekte und bei einer Serveranwendung mehr ältere Objekte gibt. Mit dem Servermodus stellt man das Verhältnis zwischen New und Old Generation auf 1:3 ein.

    -server :Servermodus für die VM

Permanent Generation

Die Permanent Generation wird von der JVM für das Laden der Klassen durch den ClassLoader verwendet. Normalerweise ist die Defaulteinstellung der Größe ausreichend. Wenn allerdings viele Klassen dynamisch durch die Applikation geladen werden (z.B. durch Reflection), kann die Defaulteinstellung zu Problemen führen. Auch die Verwendung von Persistenz- oder Caching-Frameworks führt zu größerem Speicherverbrauch in der Permanent Generation.
Über folgende Parameter kann die Defaultgröße der Permanent Generation angepasst werden:

    -XX:PermSize=[Bytes]m : initiale Größe der Permanent Generation
    -XX:MaxPermSize=[Bytes]m : maximale Größe der Permanent Generation

Garbage Collection

Man unterscheidet bei der Garbage Collection in die („einfache“) Garbage Collection und in die Full Garbage Collection. Bei der Garbage Collection werden nicht mehr referenzierte Objekte aus der New Generation freigegeben. Des Weiteren werden noch „lebende“ Objekte, die durch mehrere Garbage Collection nicht freigegeben wurden, in die Old Generation kopiert. Bei einer Full Garbage Collection werden auch Objekte aus der Old Generation aufgeräumt.
Eine Full Garbage Collection ist sehr zeitintensiv (bei 2 GB Heap Size = mehrere Sekunden). Während dieser Zeit reagiert die Applikation nicht mehr.
Ist die Heap Size zu gering eingestellt, findet eine Full Garbage Collection nach der anderen statt. Dies führt zu einer sehr schlechten Performance und zu langen Antwortszeiten.
In einer Multiprozessor-Maschine ist es deshalb ratsam, die Garbage Collection („einfache“ und Full) parallel arbeiten zu lassen.

    -XX:+UseParallelGC: parallele Garbage Collection und Full Garbage Collection

Ausblick

Nachdem in diesem Artikel die Grundlagen erläutert wurden, werden im nächsten Artikel konkrete Analyse-Möglichkeiten besprochen.

Technorati Tags: , , ,

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