9.2. WebServices als normale Java-Klassen

Man kann einen WebService mit Axis als ganz einfache Java-Klasse (plain old java object oder POJO) realisieren. Alles was zusätzlich gebraucht wird, ist ein Deployment-Descriptor. Damit man diesen aber nicht immer getrennt von den Java-Quellcodes pflegen muss, werde ich ihn hier mit XDoclet-Kommentaren erzeugen.

Neben der eigentlichen Java-Klasse braucht man hierzu noch zwei Dinge: ein Ant-Script und ein XDoclet-Template.

Damit Eclipse die kompilierten Class-Files immer gleich an die richtige Stelle schreibt, muss in den Projekteigenschaften das Ausgabeverzeichnis auf den Web-Container geändert werden (siehe Beispiel-Projekt):

Abbildung 9.1. Ändern des Ausgabeverzeichnises

9.2.1. Ein WebService

Im beigefügten Beispiel-Projekt ist ein primitiver WebService realisiert:

/**
 * @author sr
 * @axis.service name="MyTestService" scope="Request" enable-remote-admin="true"1
 * @axis.useHandler name="track"
 */
public class TestService {

    /**
     * calcs a sum.
     * @axis.method2
     * @param p1 first parameter
     * @param p2 second parameter
     * @return the sum of both parameters
     */
    public int sum( int p1, int p2 ) {
        return p1+p2;
    }
    
    /**
     * gets the address
     * @axis.method
     * @param id
     * @return the address
     */
    public String getAddress( int id){
        return null; 
    }

}
1 Mit diesen XDoclet-Tags wird die Klasse als WebService deklariert
2 @axis.method markiert die Methode als exportierte WebService-Methode. Diese Methode ist damit „von aussen“ aufrufbar.

9.2.2. Das XDoclet-Template

Im Beispiel-Projekt ist ein spezielles Template für XDoclet enthalten, welches einen Deployment-Descriptor für Axis erzeugt. Es wertet die im Kapitel 10 beschriebenen Tags aus und erzeugt so ein „deploy.wsdd“ File.

<?xml version="1.0" encoding="utf-8"?>

<deployment
 xmlns="http://xml.apache.org/axis/wsdd/"
 xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
 xmlns:xsi="http://www.w3.org/2000/10/XMLSchema-instance">

<XDtClass:forAllClasses>

<!-- ... check for Handlers -->

</XDtClass:forAllClasses>

<XDtClass:forAllClasses>

<XDtClass:ifHasClassTag tagName="axis.service" paramName="name">

 <service name="<XDtClass:classTagValue tagName="axis.service" paramName="name"/>"

<!-- ... -->

     <XDtClass:ifDoesntHaveClassTag tagName="axis.service" paramName="provider">
       <XDtType:ifIsOfType type="javax.ejb.EntityBean,javax.ejb.SessionBean">
       provider="java:EJB"
       </XDtType:ifIsOfType>
       <XDtType:ifIsNotOfType type="javax.ejb.EntityBean,javax.ejb.SessionBean">
       provider="java:RPC"
       </XDtType:ifIsNotOfType>
       >
     </XDtClass:ifDoesntHaveClassTag>

     <XDtClass:ifHasClassTag tagName="axis.useHandler" paramName="name">
     <requestFlow>
         <handler type="<XDtClass:classTagValue tagName="axis.useHandler" paramName="name"/>"/>
     </requestFlow>
     </XDtClass:ifHasClassTag>

     <parameter name="className" value="<XDtClass:fullClassName/>" />

    <!-- check if remoteAdmin param is present -->
     <XDtClass:ifHasClassTag tagName="axis.service" paramName="enable-remote-admin">
       <parameter name="enableRemoteAdmin" value="<XDtClass:classTagValue tagName="axis.service" paramName="enable-remote-admin"/>" />
     </XDtClass:ifHasClassTag>

     <parameter name="allowedMethods"

     <XDtClass:ifDoesntHaveClassTag tagName="axis.service" paramName="include-all">
       <XDtEjbSession:ifStatelessSession>
                value="create"
       </XDtEjbSession:ifStatelessSession>

       <XdtEjbSession:ifStatefulSession>
                value="<XDtMethod:forAllMethods><XDtEjbHome:ifIsCreateMethod><XDtMethod:methodName/> </XdtEjbHome:ifIsCreateMethod></XDtMethod:forAllMethods>"
       </XDtEjbSession:ifStatefulSession>

       <XDtType:ifIsNotOfType type="javax.ejb.SessionBean">
                value="<XDtMethod:forAllMethods><XDtMethod:ifHasMethodTag tagName="axis.method"><XDtMethod:methodName/>
 </XDtMethod:ifHasMethodTag></XDtMethod:forAllMethods>"
       </XDtType:ifIsNotOfType>

     </XDtClass:ifDoesntHaveClassTag>

     <XDtClass:ifHasClassTag tagName="axis.service" paramName="include-all">
                value="*"
     </XDtClass:ifHasClassTag>
     />

     <parameter name="scope" value="<XDtClass:classTagValue tagName='axis.service' paramName='scope' value='request,session,application' default='request'/>"/>

 </service>

</XDtClass:ifHasClassTag>

</XDtClass:forAllClasses>

</deployment>

9.2.3. Das Build-Script

Das Ant-Script steuert die Erzeugung des Deployment-Descriptor mit XDoclet und kann anschließend gleich das Deployment in das laufende Axis Anwendung hinein vornehmen. Hierzu werden aus der Axis-Distrubution die Ant-Tasks in axis-ant.jar eingebunden und mit der „Admin-Task“ das Deployment vorgenommen. Das Script wird noch parametriert über build.properties, welche alle lokalen Einstellungen enthält.

<project name="webmodulebuilder" default="axis-deploy" basedir=".">

 <!-- set global properties for this build -->
 <property file="build.properties"/>
 <property name="dist" value="../../dist" />
 <property name="web" value="../" />

 <property name="src" value="../../src/" />
 <property name="output" value="${basedir}" />

 <path id="xdoclet.class.path">1
    <fileset dir="${xdocletlib.dir}">
        <include name="*.jar"/>
    </fileset>
 </path>

 <path id="axis.classpath">2
     <!-- use the webapps lib path, where all axis jars are present -->
     <fileset dir="${basedir}/lib">
         <include name="**/*.jar" />
     </fileset>
 </path>

 <target name="axisdoclet">
         <taskdef3
             name="templatedoclet"
             classname="xdoclet.DocletTask"
             classpathref="xdoclet.class.path"
         />

         <tstamp>
             <format property="TODAY" pattern="d-MM-yy"/>
         </tstamp>

         <templatedoclet destdir="${output}" verbose="1">4
            <fileset dir="${src}">
                <include name="**/*.java" />5
            </fileset>

            <template templateFile="axis-wsdd.xdt.xml" destinationFile="deploy.wsdd">
                <configParam name="Xmlencoding" value="utf-8" />
            </template>

         </templatedoclet>
 </target>

 <target name="axis-deploy" depends="axisdoclet">6

     <taskdef resource="axis-tasks.properties" classpathref="axis.classpath" />7

     <axis-admin8
         port="${target.port}"
         hostname="${target.server}"
         failonerror="true"
         servletpath="${target.appname}/services/AdminService"
        debug="true"
         xmlfile="deploy.wsdd"
     />

 </target>
</project>
1 Diese Pfad-Definition legt den Classpath für XDoclet fest. Um mit Ant XDoclet-Tasks zu benutzen müssen die XDoclet-Bibliotheken verfügbar sein. Die build.property „xdocletlib.dir“ legt somit das Verzeichnis fest, in dem die Xdoclet-Bibliotheken zu finden sind.
2 Diese Pfad-Definition legt den Classpath für Axis fest. Um mit Ant Axis-Tasks nutzen zu können müssen die Axis-Bibliotheken verfügbar sein. Hier verwende ich einfach einen Verweis auf das WEB-INF/lib-Verzeichnis, weil dort in diesem Projekt sowieso alle Axis-Bibliotheken installiert sein müssen.
3 Dieses Taskdef-Tag definiert die Template-Task für XDoclet.
4 Das „templatedoclet“-Tag führt das XDoclet-Template aus, um den Deployment-Descriptor zu erzeugen.
5 Das Fileset legt fest, dass alle Java-Dateien im src-Verzeichnis betrachtet werden.
6 Das „axis-deploy“ Target führt das Deployment aus. Es hängt von „axisdoclet“ ab, d.h. ggf. wird der Deployment-Descriptor vorher neu erzeugt.
7 Dieses Taskdef-Tag definiert alle Ant-Tasks die von Axis unterstützt werden (siehe Axis-Dokumentation).
8 Durch die „axis-admin“ Task wird das Deployment durchgeführt. Hierzu müssen in den build.properties alle Parameter wie target.port, target.server usw. Richtig eingestellt sein. Ausserdem muss der Server natürlich laufen und das AdminServlet muss aktiviert sein (siehe web.xml im Beispiel-Projekt).

Welche WebServices gerade aktiviert sind kann jederzeit mit einem erneuten Aufruf der Axis-Seite /axis/servlet/AxisServlet abgefragt werden. Das Servlet verwendet übrigens ein XML-File „server-config.wsdd“ in dem alle „deployten“ Services aufgeführt sind. Wir ein neuer Service in Betrieb genommen, dann passt Axis diese Datei entsprechend an.