# Struktur  einer SOAP-Anwendung



## pkm (7. Mrz 2020)

Ich mache gerade ein SOAP-Tutorium: https://www.baeldung.com/jax-ws

Mein Plan ist dieser. Ich habe ein dynamisches Webprojekt erstellt mit folgender Struktur.



Nun meine Frage. Es gibt eine wsdl-Datei in dem Tutorium -> In welchen Ordner kommt die WSDL-Datei rein? 

In welchen Ordner gehört das Endpointinterface und dessen Implementierung? 

Zudem gibt es die Modelklasse -> Wo gehört diese rein?


----------



## mihe7 (8. Mrz 2020)

pkm hat gesagt.:


> Ich mache gerade ein SOAP-Tutorium: https://www.baeldung.com/jax-ws


Freiwillig?!?


----------



## pkm (8. Mrz 2020)

Ja, freiwillig, wieso? Allerdings habe ich jetzt die Struktur bereits hinbekommen, und mich plagt nun en anderes Problem. wsimport wird von eclipse nicht mehr unterstützt 

Ich habe mir jax-ws von github gerippt, ich will einfach nur in den Folder meines Webservice wechseln und diesen Befehl ausführen: wsimport -Xnocompile -s src xml/meinewsdl.wsdl

Keine Ahnung, wie ich da jetz vorgehen soll.

Hier der git-hub-Link, allerdings weiß ich nicht, wie ich jetzt mit wsimport weiter verfahre.








						GitHub - javaee/metro-jax-ws
					

Contribute to javaee/metro-jax-ws development by creating an account on GitHub.




					github.com


----------



## mihe7 (8. Mrz 2020)

pkm hat gesagt.:


> Ja, freiwillig, wieso?


Weil ohne Not kein Mensch mehr SOAP nutzt  



pkm hat gesagt.:


> und mich plagt nun en anderes Problem. wsimport wird von eclipse nicht mehr unterstützt


Wundert mich nicht, s. o.  Allerdings vermute ich eher, dass es daran liegt, dass das Zeug aus dem JDK entfernt wurde.



pkm hat gesagt.:


> allerdings weiß ich nicht, wie ich jetzt mit wsimport weiter verfahre.


Unter dem Link findest Du ganz unten eine Distribution. Versuch die mal.


----------



## Ullenboom (8. Mrz 2020)

Als Tipp würde ich empfehlen langfristig das Ganze zu automatisieren, etwa über Maven und https://github.com/davidmoten/jax-maven-plugin.


----------



## mihe7 (8. Mrz 2020)

Ullenboom hat gesagt.:


> Als Tipp würde ich empfehlen langfristig das Ganze zu automatisieren, etwa über Maven und https://github.com/davidmoten/jax-maven-plugin.


Wobei das "offizielle" Maven-Plugin jetzt auch funktionieren soll: kaum wartet man zwei Jahre drauf, schon ist es soweit... Allerdings hat sich das Problem bei uns mittlerweile erledigt -> kein SOAP mehr.


----------



## pkm (1. Apr 2020)

Ich bin weitergekommen bei diesem Tutorium: https://www.baeldung.com/jax-ws

Dennoch gibt es da etwa,s das ich nicht verstehe. Unter Kapitel 8. (Remote Web Service Client) gibt es einen wsimport-Befehl 
wsimport -keep -p com.baeldung.jaxws.client http://localhost:8080/employeeservice?wsdl

Dieser Befel produziert einen Fehler: "Schemadokument http://localhost:8080/employeeservice?wsdl konnte nicht gelesen werden, da 1) das Dokument nicht gefunden werden konnte [daran wird es wohl liegen], 2) das Dokument nicht gelesen werden konnte [m. E. auch nicht der Fall] 3) das rootElement des Dokuments nicht <wsdl:definitions> ist. [stimmt nicht]

In dem ganzen oben verlinkten Tutorium ist nirgends von einer Datei http://localhost:8080/employeeservice?wsdl die Rede. Worauf bezieht sich der in dem Totorium erwähnte Befehl?


----------



## mihe7 (1. Apr 2020)

Die SOAP-Dienste werden mittels WSDL sprachunabhängig beschrieben. Mit Hilfe von wsimport werden dieser Beschreibung entsprechende Java-Klassen erzeugt.


----------



## kneitzel (1. Apr 2020)

In dem Tutorial hast Du zwei Teile:
a) Top-Down 
Hier wird erst der Vertrag geschrieben, d.h. Du erstellst die wsdl und daraus wird dann viel Code generiert. Wenn Du das in dem Tutorial anschaust (Kapitel 5), dann siehst du den wsimport Aufruf direkt auf der wsdl Datei, die geschrieben wurde.
b) Bottom-Up
Hier schreibst Du den Server direkt. Deinen Code versiehst Du mit Annotations, so dass beim publishen des Service die WSDL erstellt werden kann.
(Direkt zweiter Satz in Kapitel 6: "The WSDL is generated from the classes when the web service is published.")

Wenn Du dem Beispiel folgst, den Service dann startest, dann kannst Du mit dem wsimport-Aufruf so wie in Kapitel 6 angegeben, die Dateien generieren lassen für den Zugriff auf den Webservice.

Wie @mihe7 das schon richtig ausgedrückt hat: Das ist ein Weg, mit dem man einen Service Sprachunabhängig definieren kann. So einen Service kann man also auch ganz einfach in .Net nutzen (Windows Communication Foundation wird da genutzt, Visual Studio bietet z.B. direkt das Einbinden von einem Service in ein Projekt.)


----------



## pkm (1. Apr 2020)

Ok, vielen Danke für dne Tipp. Nun, den Top-Down-Approach habe ich schon, leider kann ich den Publisher nicht ohne Fehlermeldung ausführen. Hier der Publisher:



```
package core;

import javax.xml.ws.Endpoint;

public class EmployeeServicePublisher {

    public static void main(String[] args) {

        Endpoint.publish("http://localhost:8080/employeeservicetopdown", new EmployeeServiceTopDownImpl());

    }

}
```

Wenn ich diesen ausführe, kommt eine Fehlermeldung:



> Caused by: java.lang.ClassNotFoundException: com.sun.istack.localization.LocalizableMessageFactory$ResourceBundleSupplier
> at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:583)
> at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
> at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)



Dennoch habe ich ja die jar "jaxb-impl-2.2.6.jar" dem Buildpath inzugefügt, und die jar enthält die Klasse "LocalizableMessageFactory.class". Leider weiß ich nicht, was dieses $-Zeichen in "com.sun.istack.localization.LocalizableMessageFactory$ResourceBundleSupplier"bedeutet.


----------



## kneitzel (1. Apr 2020)

Kannst Du die genauen Abhängigkeiten einmal zeigen?

Also es scheint ein kleines Problem zu geben das wohl mit der verwendeten Version zusammen hängt. In https://stackoverflow.com/questions...error-com-sun-istack-localization-localizable wird vorgeschlagen, da ein Exclude mit rein zu nehmen...

Evtl. löst sich dieses Problem, wenn Du eine aktuelle Version der Library verwendest. Also z.B. die 2.3.2 hat diese Abhängigkeit nicht mehr drin so wie es aussieht: https://mvnrepository.com/artifact/com.sun.xml.bind/jaxb-impl


----------



## pkm (1. Apr 2020)

Also ich poste, wenn es ok so ist, die Abhängigkeiten einmal per Screenshot:



Aber (da ich das Ganze ja nie studiert hab'): Was bedeutet eigentlich das $ in .LocalizableMessageFactory$ResourceBundleSupplier  ?


----------



## mihe7 (1. Apr 2020)

pkm hat gesagt.:


> Was bedeutet eigentlich das $ in .LocalizableMessageFactory$ResourceBundleSupplier ?


Darüber werden innere Klassen (bzw. Typen) adressiert. D. h. ResourceBundleSupplier ist ein innerhalb von LocalizableMessageFactory deklarierter Typ.


----------



## kneitzel (1. Apr 2020)

Du nutzt also kein maven sondern machst die Abhängigkeiten selbst? Laut dem Bild hast Du die jaxb-impl-2.3.2 gerunter geladen, aber referenziert ist immer noch die 2.2.6. Du musst natürlich die alte Referenz raus und die neue rein nehmen.


----------



## pkm (1. Apr 2020)

Danke für den Tipp, geht aber leider beides nicht, denn wenn ich die andere, also 2.3.2 referenziere, dann findet er sie Klasse nicht:

Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/istack/localization/Localizable


----------



## mrBrown (1. Apr 2020)

vermutlich fehlt noch ne Abhängigkeit, jaxb-core?

(warum nutzt du nicht Maven oder gradle?)


----------



## mihe7 (1. Apr 2020)

mrBrown hat gesagt.:


> (warum nutzt du nicht Maven oder gradle?)


Das wäre zu einfach.


----------



## pkm (1. Apr 2020)

Ihr habt mich überzeugt, und ich habe auf mvn umgestellt. Nun habe ich noch folgenden Fehler (einen sehr interessanten):



> Exception in thread "main" javax.xml.ws.WebServiceException: Error while searching for service [javax.xml.ws.spi.Provider]
> at javax.xml.ws.spi.FactoryFinder$1.createException(FactoryFinder.java:61)
> at javax.xml.ws.spi.FactoryFinder$1.createException(FactoryFinder.java:58)
> at javax.xml.ws.spi.ServiceLoaderUtil.firstByServiceLoader(ServiceLoaderUtil.java:70)
> ...



.... ich habe hierzu etwas auf stackOverflow gefunden:









						Eclipse 4.12 - java.lang.ClassNotFoundException: com.sun.xml.internal.bind.v2.ContextFactory
					

I am getting below error while running my eclipse plugin. Eclipse used 4.12 with java11. It used to work fine in eclipse 4.6.3 + java8.  javax.xml.bind.JAXBException: Provider com.sun.xml.internal....




					stackoverflow.com
				




Da heißt es: 



> And well, one of the ways to set that is via the jaxb.properties file, which must be visible to the classpath (so, in Maven, it's usually somewhere like src/main/resources/*). As it is explained here, this file has to contain:
> 
> javax.xml.bind.context.factory=com.sun.xml.bind.v2.JAXBContextFactory



Das Problem ist, dass ich im core-Package eine Datei jaxb.properties mit dem oben genannten Eintrag eingefügt habe, der Fehler ist aber noch da. Hmm, was könnte das nun sein?


----------



## mrBrown (1. Apr 2020)

pkm hat gesagt.:


> Das Problem ist, dass ich im core-Package eine Datei jaxb.properties mit dem oben genannten Eintrag eingefügt habe, der Fehler ist aber noch da. Hmm, was könnte das nun sein?


Die Datei sollte direkt in src/main/resources liegen


----------



## pkm (1. Apr 2020)

Interessant ist Folgendes. Wenn ich die Datei "verlege" wie hier:



... kommt derselbe Fehler :\


----------



## thecain (1. Apr 2020)

Du hätst dich ja auch nicht an die mvn conventions... src/main/java, src/main/resources, src/test/java und src/test/resources


----------



## pkm (2. Apr 2020)

Stimmt, das war verkehrt, aber dieses:



...tut auch nicht, d. h. die Fehlermeldung ist nach wie vor 



> Exception in thread "main" javax.xml.ws.WebServiceException: Error while searching for service [javax.xml.ws.spi.Provider]
> at javax.xml.ws.spi.FactoryFinder$1.createException(FactoryFinder.java:61)
> at javax.xml.ws.spi.FactoryFinder$1.createException(FactoryFinder.java:58)
> at javax.xml.ws.spi.ServiceLoaderUtil.firstByServiceLoader(ServiceLoaderUtil.java:70)
> ...


----------



## mrBrown (2. Apr 2020)

Oh, du solltest auch die JAXB-API als Dependency hinzufügen:

```
Caused by: javax.xml.bind.JAXBException: Implementation of JAXB-API has not been found on module path or classpath.
```


----------



## pkm (2. Apr 2020)

Ok, hab JAXB-API hinzugefügt, aber scheinbar ist das Problem irgendwie unlösbar, vgl. hier:









						Invalid JAXB default factory class on JavaSE 11 · Issue #78 · jakartaee/jaxb-api
					

private static final String PLATFORM_DEFAULT_FACTORY_CLASS = "com.sun.xml.internal.bind.v2.ContextFactory"; Jaxb api uses invalid default factory class which referes to JDK versions, whic...




					github.com
				




Und der Fehler bleibt daher:



> Exception in thread "main" javax.xml.ws.WebServiceException: Error while searching for service [javax.xml.ws.spi.Provider]
> at javax.xml.ws.spi.FactoryFinder$1.createException(FactoryFinder.java:61)
> at javax.xml.ws.spi.FactoryFinder$1.createException(FactoryFinder.java:58)
> at javax.xml.ws.spi.ServiceLoaderUtil.firstByServiceLoader(ServiceLoaderUtil.java:70)
> ...


----------



## mrBrown (2. Apr 2020)

Könntest die  2.4.0 oder die neuste Jakarta-Version mal testen


----------



## pkm (2. Apr 2020)

Danke, habe ich gemacht und auch viele Fehler beheben können. Derzeit bin ich bei:



> Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/org/apache/xml/internal/resolver/CatalogManager
> at com.sun.xml.ws.client.WSServiceDelegate.createCatalogResolver(WSServiceDelegate.java:377)
> at com.sun.xml.ws.client.WSServiceDelegate.parseWSDL(WSServiceDelegate.java:363)
> at com.sun.xml.ws.client.WSServiceDelegate.<init>(WSServiceDelegate.java:321)
> ...



Falls jemand durch einen Hack zum Beispiel eben diesen Fehler mal in einem anderen MVN-Projekt wegbekommen hat, bin ich jederzeit für Tipps dankbar, auch wenn ich langsam befürchte, dass meine Fehlerposts langsam zum Spam werden 

Hier die aktuelle pom.xml:


```
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>

  <groupId>localhost</groupId>
  <artifactId>quickstart</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <name>quickstart</name>
  <url>http://maven.apache.org</url>

  <properties>
    <maven.compiler.source>1.7</maven.compiler.source>
    <maven.compiler.target>1.7</maven.compiler.target>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
  </properties>

  <dependencies>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>3.8.1</version>
      <scope>test</scope>
    </dependency>
    <dependency>
    <groupId>javax.xml.ws</groupId>
    <artifactId>jaxws-api</artifactId>
    <version>2.3.1</version>
</dependency>
<dependency>
    <groupId>javax.jws</groupId>
    <artifactId>javax.jws-api</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>rt</artifactId>
    <version>2.2.10</version>
</dependency>
<dependency>
    <groupId>javax.inject</groupId>
    <artifactId>javax.inject</artifactId>
    <version>1</version>
</dependency>
<dependency>
    <groupId>javax.xml</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.1</version>
</dependency>
<dependency>
    <groupId>javax.xml.bind</groupId>
    <artifactId>jaxb-api</artifactId>
    <version>2.3.0-b170201.1204</version>
</dependency>
<dependency>
    <groupId>javax.activation</groupId>
    <artifactId>activation</artifactId>
    <version>1.1</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.ws</groupId>
    <artifactId>jaxws-ri</artifactId>
    <version>2.2.10</version>
    <type>pom</type>
</dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-impl</artifactId>
    <version>2.2.6</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.stream.buffer</groupId>
    <artifactId>streambuffer</artifactId>
    <version>1.4</version>
</dependency>
<dependency>
    <groupId>com.sun.xml.messaging.saaj</groupId>
    <artifactId>saaj-impl</artifactId>
    <version>1.5.0</version>
</dependency> 
<dependency>
        <groupId>com.sun.xml.ws</groupId>
        <artifactId>jaxws-rt</artifactId>
        <version>2.3.1</version>
        <type>pom</type>
    </dependency>
<dependency>
    <groupId>com.sun.xml.bind</groupId>
    <artifactId>jaxb-xjc</artifactId>
    <version>2.2.11</version>
</dependency>
</dependencies>
</project>
```


----------



## pkm (3. Apr 2020)

Ich habe bin der Dependency-Hell durch Hinzufügen von folgender dependency Herr geworden:


```
<dependency>
<groupId>com.sun.org.apache.xml.internal</groupId>
<artifactId>resolver</artifactId>
<version>20050927</version>
</dependency>
```


----------



## pkm (4. Apr 2020)

Es tut leider immer noch nicht, daher wollte ich einmal in Bezug auf das bereits erwähnte baeldung-Tutorium einmal die grundsätzliche Frage stellen, was das „publishen“ eines Webservice eigentlich tut.

Ich habe auf port 8080 den Tomcat angeworfen und leider funktioniert das publishen aus folgendem Grunde nicht:



> com.sun.xml.ws.wsdl.parser.InaccessibleWSDLException: 2 counts of InaccessibleWSDLException.
> 
> java.net.ConnectException: Connection refused: connect
> 
> ...



Ich verstehe nicht, wieso dieser Fehler kommt, denn ich habe doch den Namespace im Objekt QName des Service deklariert (in der Klasse EmployeeServiceTopDown_Service):


private final static QName _*EMPLOYEESERVICETOPDOWN_QNAME*_ = new QName("http://localhost/employeeservicetopdown/",

            "EmployeeServiceTopDown");

Hier meine wsdl-Datei:

```
<?xml version="1.0" encoding="UTF-8"?>
<definitions
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:tns="http://localhost/employeeservicetopdown/"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns="http://schemas.xmlsoap.org/wsdl/"
  targetNamespace="http://localhost/employeeservicetopdown/"
  qname="EmployeeServiceTopDown">
    <types>
        <xsd:schema
          targetNamespace="http://localhost/employeeservicetopdown/">
            <xsd:element name="countEmployeesResponse" type="xsd:int"/>
        </xsd:schema>
    </types>
 
    <message name="countEmployees">
    </message>
    <message name="countEmployeesResponse">
        <part name="parameters" element="tns:countEmployeesResponse"/>
    </message>
    <portType name="EmployeeServiceTopDown">
        <operation name="countEmployees">
            <input message="tns:countEmployees"/>
            <output message="tns:countEmployeesResponse"/>
        </operation>
    </portType>
    <binding name="EmployeeServiceTopDownSOAP"
      type="tns:EmployeeServiceTopDown">
        <soap:binding transport="http://schemas.xmlsoap.org/soap/http"
          style="document"/>
        <operation name="countEmployees">
            <soap:operation
              soapAction="http://localhost/employeeservicetopdown/
              EmployeeServiceTopDown/countEmployees"/>
            <input>
                <soap:body use="literal"/>
            </input>
            <output>
                <soap:body use="literal"/>
            </output>
        </operation>
    </binding>
    <service name="EmployeeServiceTopDown">
        <port name="EmployeeServiceTopDownSOAP"
          binding="tns:EmployeeServiceTopDownSOAP">
            <soap:address
              location="http://localhost:8080/employeeservicetopdown"/>
        </port>
    </service>
</definitions>
```


Hier der Service-Provider:

```
package maven.localhost.quickstart;

import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.namespace.QName;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.WebServiceFeature;
import javax.xml.ws.WebServiceProvider;

@WebServiceProvider(serviceName = "EmployeeServiceTopDown", targetNamespace = "http://localhost/employeeservicetopdown/", wsdlLocation = "file:/C:/Users/andfe/Documents/eclipse-workspace/quickstart/src/main/java/employeeservicetopdown.wsdl")
public class EmployeeServiceTopDown_Service extends Service {

    private final static URL EMPLOYEESERVICETOPDOWN_WSDL_LOCATION;
    private final static WebServiceException EMPLOYEESERVICETOPDOWN_EXCEPTION;

    // "file://C:/Users/andfe/Documents/eclipse-workspace/quickstart/src/main/java/employeeservicetopdown.wsdl"
    // als QName oder
    // "http://localhost/employeeservicetopdown/"
    // ?

    private final static QName EMPLOYEESERVICETOPDOWN_QNAME = new QName("http://localhost/employeeservicetopdown/",
            "EmployeeServiceTopDown");

    static {
        URL url = null;
        WebServiceException e = null;
        try {
            url = new URL("http://localhost:8080/employeeservicetopdown");
        } catch (MalformedURLException ex) {
            e = new WebServiceException(ex);
        }
        EMPLOYEESERVICETOPDOWN_WSDL_LOCATION = url;
        EMPLOYEESERVICETOPDOWN_EXCEPTION = e;
    }

    public EmployeeServiceTopDown_Service() {
        super(__getWsdlLocation(), EMPLOYEESERVICETOPDOWN_QNAME);
    }

    public EmployeeServiceTopDown_Service(WebServiceFeature... features) {
        super(__getWsdlLocation(), EMPLOYEESERVICETOPDOWN_QNAME, features);
    }

    public EmployeeServiceTopDown_Service(URL wsdlLocation) {
        super(wsdlLocation, EMPLOYEESERVICETOPDOWN_QNAME);
    }

    public EmployeeServiceTopDown_Service(URL wsdlLocation, WebServiceFeature... features) {
        super(wsdlLocation, EMPLOYEESERVICETOPDOWN_QNAME, features);
    }

    public EmployeeServiceTopDown_Service(URL wsdlLocation, QName serviceName) {
        super(wsdlLocation, serviceName);
    }

    public EmployeeServiceTopDown_Service(URL wsdlLocation, QName serviceName, WebServiceFeature... features) {
        super(wsdlLocation, serviceName, features);
    }

    private static URL __getWsdlLocation() {
        if (EMPLOYEESERVICETOPDOWN_EXCEPTION != null) {
            throw EMPLOYEESERVICETOPDOWN_EXCEPTION;
        }
        return EMPLOYEESERVICETOPDOWN_WSDL_LOCATION;
    }

}
```




Und hier die Publisher-Klasse:


```
package maven.localhost.quickstart;

import javax.xml.ws.Endpoint;

public class EmployeeServicePublisher {

    public static void main(String[] args) {

        try {

            Endpoint.publish("http://localhost:8080/employeeservicetopdown", new EmployeeServiceTopDown_Service());

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
```


----------



## pkm (17. Apr 2020)

Ich habe es jetzt hinbekommen. Das Problem war, dass "targetNamespace="http://localhost/employeeservicetopdown/" als Targetnamespace freilich inexistent war.


----------

