Archiv für die Kategorie ‘IDE’

“Code First, Contract Last” Soap Web Services mit Spring

Donnerstag, 14. August 2008

Möchte man einen Web Service veröffentlichen, der von Springs Dependency Injection Mechanismus Gebrauch macht, so muss der Web Service auf den Spring Application Context zugreifen können.

Spring liefert ein eigenes Web Services Framework “Spring-WS” mit. Allerdings ist dieses Framework darauf ausgerichtet, dass die Web Services dem “Contract First, Code Last” – Ansatz nach entwickelt werden. D.h. man schreibt zunächst das XML Schema und das WSDL-Dokument, welche den Web Service definieren und implementiert anschließend, den aufgestellten Vorschriften entsprechend, die Service-Klassen. Für diesen Weg bietet Spring-WS einige Unterstützung. So kann man sich z.B. aus einem definierten XML-Schema eine WSDL generieren lassen.

Hat man aber bereits die Service-Klassen implementiert und möchte deren Funktionalität nun als Web Services veröffentlichen, so bieten sich andere Hilfsmittel dafür an. Im Folgenden wird beschrieben, wie man mit XFire und JSR 181 Annotations den “Code First, Contract Last” – Ansatz zur Entwicklung von Spring Web Services verfolgen kann. Dazu wird ein einfacher “Hello World” – Web Service erstellt, der von Spring verwaltete Beans verwendet.

Zunächst schreibt man sich eine Java-Klasse, die die helloWorld-Methode implementiert.

package de.baderjene.backend.webServiceAPI;
 
import org.springframework.stereotype.Component;
 
@Component("helloWorldCore")
public class HelloWorldCore {
 
  public String helloWorld() {
    return "hello world!";
  }
}

Anschließend implementiert man die annotierte Web Service Klasse, die die Klasse HelloWorldCore per Dependency Injection erhält.

package de.baderjene.backend.webServiceAPI;
 
import javax.jws.WebMethod;
import javax.jws.WebResult;
import javax.jws.WebService;
 
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
 
@WebService(name = "ExampleWebService", targetNamespace = "http://pegasus/services/ExampleWebService")
@Component("exampleWebService")
public class ExampleWebService {
 
  @Autowired
  HelloWorldCore helloWorldCore;
 
  @WebMethod(operationName = "helloWorld", action = "urn:helloWorld")
  @WebResult(name = "result")
  public String helloWorld() {
    return helloWorldCore.helloWorld();
  }
}

Nun schreibt man noch die benötigten Konfigurationsdateien:
1. Spring Application Context

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:context="http://www.springframework.org/schema/context"
  xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
                               http://www.springframework.org/schema/context
                               http://www.springframework.org/schema/context/spring-context-2.5.xsd">
 
 <context:component-scan base-package="de.baderjene.backend"/>
 
<context:annotation-config/>
 
</beans>

2. xfire-servlet.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
<beans>
    <import resource="backendContext.xml"/>
    <bean id="webAnnotations"
        class="org.codehaus.xfire.annotations.jsr181.Jsr181WebAnnotations" />
    <bean id="jsr181HandlerMapping"
        class="org.codehaus.xfire.spring.remoting.Jsr181HandlerMapping">
        <property name="typeMappingRegistry">
            <ref bean="xfire.typeMappingRegistry" />
        </property>
        <property name="xfire" ref="xfire" />
        <property name="webAnnotations" ref="webAnnotations" />
    </bean>
</beans>

3. web.xml

<?xml version="1.0" encoding="ISO-8859-1"?>
<!DOCTYPE web-app
    PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
    "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:org/codehaus/xfire/spring/xfire.xml
            /WEB-INF/xfire-servlet.xml
        </param-value>
    </context-param>
 
   <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
       </listener-class>
    </listener>
 
    <servlet>
        <servlet-name>XFireServlet</servlet-name>
        <servlet-class>
            org.codehaus.xfire.spring.XFireSpringServlet
        </servlet-class>
    </servlet>
    <servlet-mapping>
        <servlet-name>XFireServlet</servlet-name>
        <url-pattern>/servlet/XFireServlet/*</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>XFireServle</servlet-name>
        <url-pattern>/services/*</url-pattern>
    </servlet-mapping>
</web-app>

Zum Ausprobieren kann man nun ein War-Packet erstellen, dieses z.B. in das webapps-Verzeichnis vom Tomcat legen und den Tomcat starten.


Christian Borkowski


Eclipse Shortcuts

Donnerstag, 26. Juni 2008

Eclipse bietet eine Fülle von Funktionen und nahezu so viele Shortcuts. Ich möchte ein paar (für mich) wichtige Shortcuts vorstellen, die vielleicht noch unbekannt sind.

Ein Überblick über die wichtigsten Shortcuts gibt es mit Hilfe von STRG+SHIFT+L, die Einstellungen finden sich im Menü unter Window→Preferences… General→Keys.

Besonders durch Firefox, aber auch durch andere Anwendungen, sind Tabs (”Reiter”) zur Organisation von mehreren Darstellungsflächen innerhalb einer Anwendung populär geworden.  Es etablierte sich der Quasistandard STRG+TAB für das Wechseln zwischen den einzelnen Darstellungen (STRG+SHIFT+TAB rückwärts). Das Wechseln zwischen verschiedenen Fenstern (ALT+TAB) verhält sich analog. Um dieses verhalten in Eclipse zu erreichen, müssen wir die Einstellungen von “Previous Editor” und “Next Editor” auf die gewünschte Tastenkombination stellen.

Besonders bei großen Projekten dauert es oft lange eine geöffnete Datei im “Package Explorer” zu lokalisieren. Dies erleichtert der Command “Show in menu”. Durch ALT+SHIFT+W erscheint ein Menü direkt am Cursor, in dem man “Package Explorer” auswählt. Dieser springt nun an die richtige Stelle. Nicht jedoch mit STRG+ALT+W zu verwechseln, dieses Kürzel schließt alle offenen Editoren.

Kennt man den Namen einer Resource, weiß aber nicht wo im Projekt sie zu finden ist hilft der Dialog “Open Resource”. Mit STRG+SHIFT+R öffnet sich eine Suchmaske mit sofortiger Rückmeldung.

Beim Erstellen neuer Klassen, gerade bei Datenhaltungs-Objekten (ValueObjects) mit vielen Intstanzvariablen, wird Programmieren zur reinen Schreibarbeit. Hier ist es sehr Hilfreich, dass Eclipse erlaubt, getter- und setter-Methoden sowie Kontruktoren zu generieren.  Mit ALT+SHIFT+S öffnet sich das “Source”-Menü, mit der Taste R wird der Dialog zum Generieren der getter und setter Methoden geöffnet (ALT+SHIFT+S, R). Ähnlich erreicht man den Dialog zum Erzeugen eines Constructors (ALT+SHIFT+S, O).

Welches sind eure am häufigsten genutzten Shortcuts (STRG+S zählt nicht)?


Jan Kuenstler


Maven2 in Eclipse nutzen

Dienstag, 29. April 2008

Viele Projekte verwenden mittlerweile Maven2 für Build, Deployment, usw. Um Maven aus Eclipse heraus relativ komfortabel zu nutzen, sind nicht unbedingt Plugins nötig. Mit wenigen Handgriffen ist das lokale Repository konfiguriert und häufig genutzte Goals eingerichtet.
Plugins bieten zwar Vorteile, z.B. bei der Verwaltung der Dependencies, sind aber leider (noch) an vielen Stellen unflexibel, nicht stabil und umständlich zu benutzen.

Voraussetzung ist eine lauffähige Maven2 Version (Kommandozeile) und im Betriebssystem die Path-Variable MAVEN_HOME, die auf das Maven Installationsverzeichnis verweist (dort wo man Maven entpackt hat).
Die folgenden Schritte wurden mit Eclipse 3.3 durchgeführt.

Lokales Repository zum Buildpath hinzufügen

Damit in Eclipse das Maven Repository gefunden wird, muss die Classpath-Variable M2_REPO angelegt und auf das lokale Repository verlinkt werden.
Das geschieht über das Menü:
Window – Preferences – Java – Build Path – Classpath Variables
Hier mit “New” die Variable M2_REPO anlegen und den Path auf das lokale Maven Repository setzen.
Unter Windows liegt das lokale Repository in der Regel unter:
C:\Dokumente und Einstellungen\<Benutzername>\.m2\repository
Bei Linux unter:
/home/<Benutzername>/.m2/repository

Maven Goals konfigurieren

Hierfür bietet es sich an die “External Tools Launch Configuration” von Eclipse zu nutzen mit der, wie der Name vermuten lässt, externe Programme aufgerufen werden können.

1. Über die Schaltfläche External Tools den Open External Tools Dialog … öffnen.

2. Unter Program eine New launch configuration anlegen.

3. Location: ${env_var:MAVEN_HOME}\bin\mvn.bat
Hiermit wird über die Systemvariable MAVEN_HOME die aktuelle Maven Version aufgerufen.
Z.B. liegt die Maven Installation im Verzeichnis: c:/dev/maven-2.0.7 auf welches die Variable MAVEN_HOME verweist. Eine neuere Maven Version packt man im Verzeichnis c:/dev/maven-2.0.8 aus und stellt nur die MAVEN_HOME Variable entspr. um.

4. Working Directory: ${project_loc}
Nun wollen wir nicht für jedes Projekt eine eigene Launch Configuration anlegen. Das nervt und wird schnell sehr unübersichtlich. Auch hierfür biete Eclipse eine eigene Variable an: ${project_loc} verweist auf das aktuell ausgewählte Projekt.

5. Arguments: install -DcreateChecksum=true
Hier werden Maven die Kommandozeilen-Argumente übergeben. In diesem Fall also ein einfaches install mit Erzeugen der Checksum. Ein weiteres gutes Beispiel ist das eclipse:eclipse Goal. Mit diesen beiden Goals sind schon mal die Grundbedürfnisse erfüllt.

Ausführen eines Maven Goal

Im z.B. Package Explorer ein Maven Projekt auswählen (anklicken), hierdurch wird die Eclipse Variable ${project_loc} gesetzt. Anschließend aus den External Tools das gewünschte Goal auswählen und Maven startet in der Console.
Fertig :-)

Ein typischer Arbeitsschritt wäre z.B.:

  • Anpassungen am pom.xml machen
  • Goal eclipse:eclipse ausführen
  • Refresh des Projekts (F5) -> kann man auch durch die Launch Configuration auto. durchführen lassen
  • Goal install ausführen

BTW: Zusätzlich fügt man diese Launch Configurations noch zu den Favoriten hinzu, dann geht es noch schneller.

Beispiele:
Folgende Goals verwende ich wie oben beschrieben.

  • install -DcreateChecksum=true
  • eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true
  • Da ab maven 2.0.10 beim eclipse Goals auch Projekte referenziert werden, dies aber nicht immer gewünscht ist, kann man dieses Feature abschalten

  • eclipse:eclipse -DdownloadSources=true -DdownloadJavadocs=true -Declipse.useProjectReferences=false

Viel Spaß und Erfolg beim Ausprobieren und Anwenden


Christof Aenderl


Eclipse – Save Actions

Montag, 21. April 2008

In der Entwicklungsumgebung Eclipse gibt es einige Features, die mancher Entwickler zu schätzen weiß, so er sie denn auch entdeckt hat – dazu zählen z.B. die Save Actions, die in diesem Artikel vorgestellt werden.

Save Actions sind, wie es der Name erahnen läßt, Aktionen, die mit dem Speichern einer Java-Datei ausgeführt werden. Zu finden ist die Konfiguration entweder unter dem Menüpunkt Window -> Preferences… -> Java ->Editor -> Save Actions oder im Kontextmenü eines Projektes unter Properties -> Java Editor -> Save Actions. Über den zweiten Weg lassen sich nur die projektbezogenen Einstellungen ändern, nicht die globalen.
Die ersten beiden Punkte Format source code und Organize imports tun genau das, was zu erwarten ist: Den Code entsprechend dem vorgegebenen Code Style Formatter zu formatieren bzw. die Importanweisungen entsprechend dem Code Style zu ordnen. Beide können unter Code Style angepasst werden. Sehr interessant ist der Punkt Additional actions unter dem diverse Regeln zur Code-Änderung selektiert werden können. Hier ein Beispiel:
Wie gerne spart man sich die Klammerung einzeiliger Anweisungen nach einem if-Statement? Durch Aktivierung der entsprechenden Regel wird folgende Änderung im Code durchgeführt:

//vorher
if (condition)
    doSomething();
//nachher
if (condition) {
    doSomething();
}

Zur Warnung sei gesagt, dass es nicht unbedingt sinnvoll ist, alle Regeln zu aktivieren, da sie eventuell zu unerwünschten Änderungen führen können – ein Beispiel sind die Regeln unter Unnecessary Code: Sind diese Regeln aktiviert, könnte folgendes passieren: Wird zum Testen eine Code-Passage auskommentiert, so werden nur dort benutzte Variablen und Importe ungewollterweise entfernt – meist ist dies aber erst festzustellen, wenn nach dem Reaktivieren der Codepassage der Compiler Fehler meldet. Desweiteren sollten die Save-Actions natürlich mit dem Code Style des Projektes harmonieren.

Ein weiterer Aspekt, der bei der Einführung von Save Actions bedacht werden sollte: Wird das nützliche Tool erst später in einem Projekt aktiviert, so wird es sehr wahrscheinlich zu Problemen beim Nachvollziehen von “echten” Code-Änderungen zwischen zwei Versionsständen geben.

Save Actions gibt es seit der Eclipse Version 3.3 (Europa)


Andreas Siepert