Jan 072013
 

Ich hoffe Folgendes hilft dem ein oder anderen beim Schnelleinstieg in die Erstellung eines Contract First RESTful Service unter folgenden Kriterien:

  • JAX-RS (im Speziellen Jersey)
  • Maven-basiert

Contract First bedeutet hier, dass die Maven-Phase “generate-sources” mittels JAXB-Plugin aus XML Schema (XSD) die notwendigen Java-Klassen generiert, welche als Datentypen in einem Service verwendet werden. Daher wähle ich den Contract First Ansatz, um ein Schema zur Schnittstellenabstimmung mit meinen Schnittstellenpartner zu verwenden.

Alle Code-Auszüge findet Ihr in Gänze in meinem Beispielprojekt.

Für die Code-Generierung folge ich Empfehlungen zur Nutzung des jaxb2-maven-plugin in meiner pom.xml:

   1: <build>

   2:   <plugins>

   3:     <plugin>

   4:       <groupId>org.codehaus.mojo</groupId>

   5:       <artifactId>jaxb2-maven-plugin</artifactId>

image

XSD und Binding-Dateien liegen in den separaten Verzeichnissen src/main/xsd und xjb (Default von jaxb2-maven-plugin).

Die XSD enthält die Datentyp-Definitionen (complexType) aus denen das jaxb2-maven-plugin die Datentypklassen generiert. Für die Verwendung als eigenständige Payload für Request bzw. Response eines Service muss die generierte Datentypklasse die JAXB-Annotation @XmlRootElement erhalten. Hierzu muss die XSD zusätzlich zum “xs:complexType” ein “xs:element” unter Verwendung des Typs definieren und…

   1: <xs:element name="businessPartner" type="BusinessPartner"/>

   2: <xs:complexType name="BusinessPartner">

   3:   ...

   4: </xs:complexType>

… das JAXB-Plugin muss eine Binding-Datei (.xjb) vorfinden, welche den Simple-Mode mittels “xjc:simple” aktivitert. Das Binding referenziert in schemaLocation relativ die betreffende XSD.

   1: <?xml version="1.0"?>

   2: <jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">

   3:   <jxb:bindings node="/xs:schema" schemaLocation="../xsd/businessPartner.xsd">

   4:     <jxb:globalBindings>

   5:       <xjc:simple />

   6:     </jxb:globalBindings>

   7:   </jxb:bindings>

   8: </jxb:bindings>

Für das JAXB-Plugin ist zu definieren, dass Vendor-spezifische JAXB-Bindings (hier xjc:simple) erlaubt sind:

   1: <plugin>

   2:   ...

   3:   <artifactId>jaxb2-maven-plugin</artifactId>

   4:   <configuration>

   5:      <extension>true</extension>

Da jaxb2-maven-plugin vom Maven-Eclipse-Plugin m2e im Maven-Live-Cycle unterstützt wird, wird unmittelbar Java-Quellcode für die Datentypen generiert, z.B.

   1: ...

   2: @XmlAccessorType(XmlAccessType.FIELD)

   3: @XmlType(name = "BusinessPartner", propOrder = {

   4:     "addresses"

   5: })

   6: @XmlRootElement(name = "businessPartner")

   7: public class BusinessPartner {

   8:

   9:     @XmlElement(name = "address")

  10:     protected List<Address> addresses;

  11:     ...

Der RESTful Service ist für JAX-RS händisch implementiert und referenziert die generierten Datentypen:

   1: @Path("/businessPartner")

   2: @Consumes(MediaType.APPLICATION_JSON)

   3: @Produces(MediaType.APPLICATION_JSON)

   4: public class BusinessPartnerResource {

   5:

   6:     ...

   7:

   8:     @POST

   9:     public void create(BusinessPartner bupa) {

  10:         ...

  11:     }

  12:

  13:     ...

  14:

  15: }

Damit Eclipse WTP den Maven-default der web-Dateistruktur  verwendet, muss in .settings/org.eclipse.wst.common.component das Verzeichnis “src/main/webapp”  statt “WebContent” angegeben werden:

   1: <?xml version="1.0" encoding="UTF-8"?><project-modules id="moduleCoreId" project-version="1.5.0">

   2:     <wb-module deploy-name="testservices">

   3:         <wb-resource deploy-path="/" source-path="/src/main/webapp" tag="defaultRootSource"/>

   4:         ...

   5:     </wb-module>

   6: </project-modules>

Damit steht dem Deployment über die Eclipse-Server-View und anschließendem Test nichts mehr im Weg.

image

Feedback ist willkommen!

Oct 212008
 

Schneller, höher, weiter! Das Entwickeln von JEE-Applikationen ist bestimmt durch Round-Trips aus Code-Änderung, Kompilierung, Re-Deployen und Testen. Da sich diese Round-Trips in kurzen Abständen (Minutenbereich) wiederholen, sollte das Kompilieren und Re-Deployen so wenig Zeit möglich in Anspruch nehmen. Zum einen lässt das schlicht mehr Zeit zum Programmieren und Testen. Zum anderen macht das Arbeiten den Programmierern so einfach mehr Spaß! (… und die Zufriedenheit des Programmierers ist direkt proportional zur Lebensdauer seiner Tastatur).

Continue reading »

Oct 032008
 

Durch zeitgesteuerte Aktionen kann ein Softwaresysteme bestimmte Anforderungen umsetzen. Zum Beispiel könnte eine Anforderung sein, dass eine Applikation jede Nacht bestimmte Datenbereinigungen durchführt. Bei OpenWishes prüfen wir beispielsweise periodisch, ob Geburtstagserinnerungen per E-Mail versendet werden müssen. Dies sind natürlich nur triviale Beispiele. Der Faktor Zeit kann nicht nur Aktionen auslösen, sondern auch das Verhalten von Geschäftslogik beeinflußen. Beispielsweise kann der Kunde im Support-Portal nach Ablauf der Garantiezeit eines gekauften Artikels keinen Reklamationsvorgang mehr einleiten.

Continue reading »

Apr 262008
 

Überaschenderweise finden Java Applets auch heute noch immer wieder ihre Nische in Systemlandschaften. Wenn es darum geht, aus einer Web-Anwendung heraus eine Schnittstelle zum lokalen System des Anwenders zu etablieren, sind Applets keine schlechte Wahl. Über die HTML-Seite in welche das Applet eingebunden ist, können Parameter an das Applet übergeben werden. Ebenso ist die bidirektionale Kommunikation zwischen Applet und Javascript möglich (siehe Netscape Live Connect). Ein signiertes Applet erlaubt es, lokale Dateien zu lesen und zu schreiben. Ebenso kann ein signiertes Applet mit entfernten Servern kommunizieren, obwohl es nicht von diesen geladen wurde.

Diese Möglichkeiten sind der Grund für den Einsatz von Applets in meinem aktuellen Projekt in München. Bei einem großen deutschen Automobilhersteller sind Applets ein (sehr kleiner) Teil derSystemlandschaft zum Produktdatenmanagement. Das nur am Rande.

Unter dem Strich erlauben wir dem Anwender mittels eines Applets Dateien zu und vom Server zu laden. Es handelt sich dabei um Office-Dokumente, Messergebnisdaten und CAD-Dateien. Die Dateien können also recht groß – gar bis über einem Gigabyte groß – sein.

Speicherproblem beim Versenden großer Datenmengen über HTTP

Die Übertragung der Dateien zum Server ist unter Verwendung der JDK-Klasse HttpURLConnection realisiert. Bei sehr großen Dateien wurde auffällig, dass die JVM sehr viel Speicher allokiert und irgendwann mit einen OutOfMemoryError die Ausführung des Applets das zeitliche segnet. Die Ursache war schnell gefunden: Die HttpURLConnection puffert sämtliche in einem HTTP-Post-Request zu übermittelnden Daten um die Anzahl der zu sendenden Bytes zu ermitteln. Diese Angabe muss die Implementierung von HttpURLConnection im Request-Header-Feld “content-length” übermitteln. Der Header muss vor den Nutzdaten beim HTTP-POST-Request gesendet werden. Die zu sendende Datei wird zwar mittels InputStream gelesen und direkt in den OutputStream von HttpURLConnection geschrieben, aber HttpURLConnection puffert die gesamte Datei im Hauptspeicher bevor auch nur ein Byte an den Ziel-HTTP-Server gesendet wird. Dies führt natürlich unweigerlich zu Problemen. Leider bietet die API von HttpURLConnection keine Möglichkeit die Content-Length zu setzen, so dass die zu versendenden Daten nicht gepuffert werden.

Continue reading »

Sep 022007
 

Eine nicht funktionale Anforderung an Software-Systeme wird gemeinhin mit dem Begriff “Security” umrissen. Ein Teilaspekt betrifft die Authorisierung von Benutzern / Fremdsystemen gegenüber bestimmten Diensten oder Daten. Bei mehrschichtigen Softwaresystemen, die eine Datenbank in der Ressourcenschicht einbinden, ist die Authorisierung oft Aufgabe der Geschäftsschicht.

Ein anderer Ansatz stellt die Realisierung der Authorisierung direkt in der Datenbank dar. Diesen Ansatz findet man oft in Alt-Systemen, bei denen zumal auch Geschäftslogik in der Datenbank in Form von Stored Procedures umgesetzt ist. Damit die Datenbank Authorisierungsfunktionen übernehmen kann, muss der tatsächliche Benutzer an die DB propagiert werden.

Oracle Logo   BEA Logo

Im Rahmen dieses Artikels möchte ich ein wenig Know-How für die Implementierung dieses Ansatzes in Verbindung mit dem Oracle-DBMS (Datenbankmanagementsystem), Connection Pooling im Weblogic Application Server und JDBC weitergeben. Dieses Know-How entstammt der Anbindung einer Produktdatenbank bei einem großen Deutschen Automobilhersteller. Zum Einsatz kommt eine proprietäres Feature des Oracle-DBMS – die Oracle-Proxy-Sessions.

Continue reading »

Jul 212007
 

Moderne Web-Anwendungen setzen Ajax ein um die Usability zu verbessern – das weiß doch jedes Kind! Eine tolle Sache zur Verbesserung der Usability ist es, für kurze Benutzerinteraktionen einen Popup-Dialog einzublenden, der vom Benutzer einfach wieder geschlossen werden kann. Unter Umständen besteht der Popup aus einer Folge von Dialogen (Wizard-Stil). Der Popup soll kein neues Browser-Fenster sein, sondern per Div über der aktuellen Seite als modaler Dialog “schweben”. Dieser Artikel zeigt eine angenehme Lösung für derartige Popup-Wizard-Dialoge unter Verwendung von Java Server Faces (JSF) und Ajax4JSF (A4J).

Continue reading »

Jul 172007
 

Das Singleton-Pattern – meiner Erfahrung nach, ein sehr häufig verwendetes Pattern, welches nahezu jeder Entwickler in seinem Wortschatz hat. Die Implementierung des Singleton-Patterns für eine bestimmte Klasse sieht vor, dass eine statisches Feld in der Klassen die Referenz der einzigen Instanz derselben Klasse speichert. Eine Methode “getInstance” liefert diese Referenz zurück und instanziiert falls nötig die Klasse. Der dazu notwendige Code muss jedes mal von Hand implementiert werden. Mit AspectJ und einer Java Annotation soll das Erstellen von Singletons vereinfacht werden. Im folgenden wird eine Lösung vorgestellt mit der eine beliebige Klasse zum Singleton gemacht wird, indem diese die Annotation “@Singleton” erhält. Fortan liefert das Instanziieren der Klasse (“new”) immer ein und dieselbe Instanz. Continue reading »

Jul 032007
 

Mehrfach verwendet man im Datenmodell / Domänenmodell ein Attribut, welches “dateCreated” oder ähnlich heisst. Für eine Entität soll also hinterlegt sein, wann diese erstellt worden ist. Hat man erst einmal ein solches Attribut an einer Entität, so muss das Erstellungsdatum auch beim erstmaligen Persistieren der Entität gesetzt werden. Wie kann man derartiges unter Verwendung der Java Persistence API effizient umsetzen?

Continue reading »