Advanced   Java   Services Web Services 3 Back Next Up Home


Ein Beispiel mit selbstenworfenen Datentypen (Style.DOCUMENT)

Will man selbstenworfene Datentypen verwenden, so muß im SEI die Annotation @SOAPBinding(style = Style.DOCUMENT) verwendet werden. Da dies die Defaulteinstellung ist, kann man diese Annotation auch weglassen, was hier absichtlich nicht geschieht. @SOAPBinding(style = Style.DOCUMENT) wird gebraucht, weil die selbstentworfenen Datentypen in der WSDL-Datei beschrieben werden müssen. In welcher Form diese geschieht legt JSR-101 in der Spezifikation "Java™ API for XML-based RPC JAX-RPC 1.1" fest. Diese Spezifikation (jax_rpc-1_1-mrel-spec.pdf) kann hier angesehen oder/und heruntergeladen werden.


Auszüge aus der Spezifikation JSR 101

Diese Spezifikation legt u.a. fest, welche primitive Datentypen und welche Klassen aus der API verwendet werden dürfen.

Für selbstentworfenen Klassen gelten folgende Beschränkungen (Spec. 5.4)


Die Klasse Director

Instanzen der Klasse Director sollen den Namen eines (Film-) Regisseurs beinhalten.

package nimdb;

import javax.xml.bind.annotation.XmlType;

@XmlType
public class Director
{
   private String name = "";


   public Director()
   {
   }

   /**
    */
   public Director(String name)
   {
      this.name = name;
   }

   /**
    */
   public String getName()
   {
      return name;
   }

   /**
    */
   public void setName(String name)
   {
      this.name = name;
   }
}

Die Klasse Movie

Instanzen der Klasse Movie sollen den Titel eines Films beinhalten.

package nimdb;

import javax.xml.bind.annotation.XmlType;

@XmlType
public class Movie
{
   private String title="";

   public Movie()
   {
   }

   /**
    */
   public Movie(String title )
   {
      this.title = title;
   }
   /**
    */
   public String getTitle()
   {
      return title;
   }
   /**
    */
   public void setTitle(String title)
   {
      this.title = title;
   }
}

Das Service Endpoint Interface

Das Service Endpoint Interface vereinbart zwei Methoden. Die Methode getDirector(Movie movie) soll zu einem Film den Namen des Regisseurs liefern, die Methode getMovies(Director dir) soll eine Liste "aller" Filme liefern, bei denen der übergebene Regisseur Regie geführt hat.

package nimdb;

import java.util.List;
import javax.jws.WebService;
import javax.jws.WebMethod;
import javax.jws.soap.SOAPBinding;
import javax.jws.soap.SOAPBinding.Style;

@WebService
@SOAPBinding(style = Style.DOCUMENT)  // default
public interface NimdbService
{
   @WebMethod
   public Director getDirector(Movie movie);
   @WebMethod
   public List<Movie> getMovies(Director dir);
}

Die Service Implementation Bean

Die Implementierung des Interfaces erzeugt on the fly zu zwei Regisseuren eine kleine Liste mit zwei Filmen. Falls ein ungültiger Regisseur oder Film eingegeben wird, geben beide Methoden null zurück.

import java.util.ArrayList;
import java.util.List;
import javax.jws.WebService;

@WebService(endpointInterface = "nimdb.NimdbService", serviceName = "TheNimdbService")
public class NimdbServiceImpl implements NimdbService
{
   private static final long serialVersionUID = 1L;

   public NimdbServiceImpl()
   {
   }

   @Override
   public List<Movie> getMovies(Director dir)
   {
      if (dir==null) return null;
      if (dir.getName().toLowerCase().equals("fellini"))
      {
         List<Movie>  list = new ArrayList<>();
         list.add(new Movie("schiff der träume"));
         list.add(new Movie("la strada"));
         return list;
      }
      else if (dir.getName().toLowerCase().equals("bergman"))
      {
         List<Movie>  list = new ArrayList<>();
         list.add(new Movie("sommer mit monika"));
         list.add(new Movie("wilde erdbeeren"));
         return list;
      }
      return null;
   }

   @Override
   public Director getDirector(Movie movie)
   {
      if (movie==null) return null;
      if (movie.getTitle().toLowerCase().equals("schiff der träume"))
         return new Director("fellini");
      else if (movie.getTitle().toLowerCase().equals("la strada"))
         return new Director("fellini");
      else if (movie.getTitle().toLowerCase().equals("sommer mit monika"))
         return new Director("bergman");
      else if (movie.getTitle().toLowerCase().equals("wilde erdbeeren"))
         return new Director("bergman");

      return null;
   }
}

Der Serviceendpoint

package nimdb;

import java.util.Scanner;
import javax.xml.ws.Endpoint;

public class NimdbServiceEndpoint
{
   public static void main(String[] args)
   {
      String serviceUrl = "http://127.0.0.1:5003/nimdb";  // packagename wird angegeben
      NimdbService ts = new NimdbServiceImpl();

      Endpoint ep=null;
      try
      {
         ep = Endpoint.publish(serviceUrl, ts);
         //com.sun.xml.internal.ws.transport.http.server.EndpointImpl
         System.out.println("NimdbService started");
         System.out.println("listening on " + serviceUrl);

         System.out.print("Stop server j/n ");
         Scanner sc = new Scanner(System.in);
         String erg = sc.next();
         if (erg.toLowerCase().equals("j"))
         {
            ep.stop();
            System.out.println("server stopped");
         }
      }
      catch(Exception ex)  // BindException
      {
         System.out.println(ex);
      }
   }
}

Die zugehörigen class-Dateien erzeugen

Obwohl das Projekt eine main()-Klasse besitzt ist es nicht startbar. Erst die erzwungene Compilierung der Klassen über clean und build erzeugt alle class-Dateien, die oben aufgeführt sind. Das reicht allerdings nicht um den Endpoint einzurichten. Dazu muß man weitere Hilfsklassen erzeugen.


Erzeugen der Artefakte mit dem Konsoltool wsgen

Die eigenen Klassen müssen in der WSDL beschrieben werden, damit ein Client diese Datentypen erzeugen kann. Dazu werden Hilfsklassen benötigt, die wsgen erzeugt. wsgen legt diese Klassen in einem Packageunterverzeichnis mit dem Namen jaxws an. Da wsgen mit den class-Dateien arbeitet, mußten diese im vorigen Schritt erzeugt werden. Erst dann kann man wsgen einsetzen.


Aufruf von wsgen

wsgen wird am besten im class-Verzeichins aufgerufen. In unserem Fall sieht der Aufruf folgendermaßen aus:

...\classes>wsgen -verbose -keep -cp . nimdb.NimdbServiceImpl

Die folgende Tabelle erklärt die Parameter

ParameterBedeutung
-verboseermöglicht Konsolmeldungen über die Aktivitäten von wsgen
-keepverhindert das Löschen der Quellcodedateien
.bedeutet das aktuelle Verzeichnis (hier also classes)
nimdb.NimdbServiceImplder vollständige Name der SIB Service Implementation Bean

In diesem Beispiel enstehen die Klassen GetDirector, GetDirectorResponse, GetMovie, GetMovieResponse (jeweils .class und .java).

wsgen-1.jpg

wsgen-2.jpg

wsgen-3.jpg

Mit diesen zusätzlichen Dateien ist der oben aufgeführte Serviceendpoint realisierbar.

Der gestartete Endpoint:

wsgen-4.jpg


Der Client

import java.io.IOException;
import java.net.URL;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.namespace.QName;
import java.net.MalformedURLException;
import java.util.List;

import nimdb.NimdbService;
import nimdb.Director;
import nimdb.Movie;

/**
   Falls der Server nicht bereit ist, gibt es die folgende Fehlermeldung
   javax.xml.ws.WebServiceException: Failed to access the WSDL at:
   http://localhost:5003/timeservice?wsdl. It failed with:
   Got Connection refused: connect while opening stream from
   http://localhost:5003/timeservice?wsdl.
*/
public class NimdbServiceClient
{
   public static void main(String[] args) throws IOException
   {
      System.out.println("NimdbServiceClient");

      try
      {
         URL serviceURL = new URL("http://localhost:5003/nimdb?wsdl");
         QName qname = new QName("http://nimdb/", "TheNimdbService");  // slash am ende notwendig
         Service service = Service.create(serviceURL, qname);

         NimdbService ns = service.getPort(NimdbService.class);
         //System.out.println(ns.getClass().getName());
         List list = ns.getMovies(new Director("fellini"));
         if(list!=null)
         {
            System.out.println( ((Movie)list.get(0)).getTitle() );
            System.out.println( ((Movie)list.get(1)).getTitle() );
         }
         else
         {
            System.out.println("unbekannter Regisseur");
         }

         Movie movie = new Movie("wilde erdbeeren");
         Director dir = ns.getDirector(movie);
         if (dir!=null)
         {
            System.out.println(dir.getName());
         }
         else
         {
            System.out.println("unbekannter Film");
         }
      }
      catch(MalformedURLException ex)
      {
         System.out.println(ex);
      }
      catch(WebServiceException ex)
      {
         System.out.println(ex);
      }
   }
}

Die Ausgabe des Clients:

wsgen-5.jpg

Valid XHTML 1.0 Strict top Back Next Up Home