it-swarm.com.de

JAX-WS-Client: Wie lautet der richtige Pfad für den Zugriff auf die lokale WSDL?

Das Problem ist, dass ich einen Webdienst-Client aus einer Datei erstellen muss, die mir zur Verfügung gestellt wurde. Ich habe diese Datei im lokalen Dateisystem gespeichert, und obwohl ich die WSDL-Datei im richtigen Dateisystemordner belasse, ist alles in Ordnung. Wenn ich es auf einem Server bereitstelle oder die WSDL aus dem Dateisystemordner entferne, kann der Proxy die WSDL nicht finden und gibt einen Fehler aus. Ich habe das Web durchsucht und die folgenden Beiträge gefunden, aber ich konnte es nicht zum Laufen bringen:
JAX-WS lädt WSDL aus jar
http://www.Java.net/forum/topic/glassfish/metro-and-jaxb/client-jar-cant-find-local-wsdl-
http://blog.vinodsingh.com/2008/12/locally-packaged-wsdl.html

Ich verwende NetBeans 6.1 (dies ist eine ältere Anwendung, die ich mit diesem neuen Webdienst-Client aktualisieren muss). Nachfolgend finden Sie die JAX-WS-Proxyklasse:

    @WebServiceClient(name = "SOAService", targetNamespace = "http://soaservice.eci.ibm.com/", wsdlLocation = "file:/C:/local/path/to/wsdl/SOAService.wsdl")
public class SOAService
    extends Service
{

    private final static URL SOASERVICE_WSDL_LOCATION;
    private final static Logger logger = Logger.getLogger(com.ibm.eci.soaservice.SOAService.class.getName());

    static {
        URL url = null;
        try {
            URL baseUrl;
            baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");
            url = new URL(baseUrl, "file:/C:/local/path/to/wsdl/SOAService.wsdl");
        } catch (MalformedURLException e) {
            logger.warning("Failed to create URL for the wsdl Location: 'file:/C:/local/path/to/wsdl/SOAService.wsdl', retrying as a local file");
            logger.warning(e.getMessage());
        }
        SOASERVICE_WSDL_LOCATION = url;
    }

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

    public SOAService() {
        super(SOASERVICE_WSDL_LOCATION, new QName("http://soaservice.eci.ibm.com/", "SOAService"));
    }

    /**
     * @return
     *     returns SOAServiceSoap
     */
    @WebEndpoint(name = "SOAServiceSOAP")
    public SOAServiceSoap getSOAServiceSOAP() {
        return super.getPort(new QName("http://soaservice.eci.ibm.com/", "SOAServiceSOAP"), SOAServiceSoap.class);
    }

    /**
     * @param features
     *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
     * @return
     *     returns SOAServiceSoap
     */
    @WebEndpoint(name = "SOAServiceSOAP")
    public SOAServiceSoap getSOAServiceSOAP(WebServiceFeature... features) {
        return super.getPort(new QName("http://soaservice.eci.ibm.com/", "SOAServiceSOAP"), SOAServiceSoap.class, features);
    }

}


Dies ist mein Code zur Verwendung des Proxys:

   WebServiceClient annotation = SOAService.class.getAnnotation(WebServiceClient.class);
   // trying to replicate proxy settings
   URL baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource("");//note : proxy uses "."
   URL url = new URL(baseUrl, "/WEB-INF/wsdl/client/SOAService.wsdl");
   //URL wsdlUrl = this.getClass().getResource("/META-INF/wsdl/SOAService.wsdl"); 
   SOAService serviceObj = new SOAService(url, new QName(annotation.targetNamespace(), annotation.name()));
   proxy = serviceObj.getSOAServiceSOAP();
   /* baseUrl;

   //classes\com\ibm\eci\soaservice
   //URL url = new URL(baseUrl, "../../../../wsdl/SOAService.wsdl");

   proxy = new SOAService().getSOAServiceSOAP();*/
   //updating service endpoint 
   Map<String, Object> ctxt = ((BindingProvider)proxy ).getRequestContext();
   ctxt.put(JAXWSProperties.HTTP_CLIENT_STREAMING_CHUNK_SIZE, 8192);
   ctxt.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, WebServiceUrl);

NetBeans hat eine Kopie der WSDL in web-inf/wsdl/client/SOAService abgelegt, daher möchte ich sie nicht zu META-INF hinzufügen auch. Serviceklassen befinden sich in WEB-INF/classes/com/ibm/eci/soaservice/ und die Variable baseurl enthält den vollständigen Pfad zum Dateisystem (c:\path\to\the\Projekt ...\soaservice). Der obige Code löst den Fehler aus:

javax.xml.ws.WebServiceException: Fehler beim Zugriff auf die WSDL unter: file: /WEB-INF/wsdl/client/SOAService.wsdl. Es ist fehlgeschlagen mit:\WEB-INF\wsdl\client\SOAService.wsdl (kann den Pfad nicht finden)

Soll ich also zuerst die wsdllocation der Proxy-Klasse aktualisieren? Wie kann ich dann die SOAService-Klasse in WEB-INF/classes/com/ibm/eci/soaservice anweisen, nach der WSDL in\WEB-INF\wsdl\client\SOAService.wsdl zu suchen?

[~ # ~] bearbeitet [~ # ~] : Ich habe diesen anderen Link gefunden - http://jianmingli.com/ wp /? cat = 41 , die sagen, dass die WSDL in den Klassenpfad eingefügt werden soll. Ich schäme mich zu fragen: Wie füge ich es in den Klassenpfad der Webanwendung ein?

81
user260192

Die beste Option ist die Verwendung von jax-ws-catalog.xml

Überschreiben Sie beim Kompilieren der lokalen WSDL-Datei den WSDL-Speicherort und setzen Sie ihn auf einen Wert wie

 http: //localhost/wsdl/SOAService.wsdl 

Keine Sorge, dies ist nur eine URI und keine URL. Das bedeutet, dass Sie die WSDL nicht an dieser Adresse verfügbar haben müssen.
Sie können dies tun, indem Sie die Option wsdllocation an den Compiler Java) übergeben.

Dadurch wird Ihr Proxy-Code von geändert

static {
    URL url = null;
    try {
        URL baseUrl;
        baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");
        url = new URL(baseUrl, "file:/C:/local/path/to/wsdl/SOAService.wsdl");
    } catch (MalformedURLException e) {
        logger.warning("Failed to create URL for the wsdl Location: 'file:/C:/local/path/to/wsdl/SOAService.wsdl', retrying as a local file");
        logger.warning(e.getMessage());
    }
    SOASERVICE_WSDL_LOCATION = url;
}

zu

static {
    URL url = null;
    try {
        URL baseUrl;
        baseUrl = com.ibm.eci.soaservice.SOAService.class.getResource(".");
        url = new URL(baseUrl, "http://localhost/wsdl/SOAService.wsdl");
    } catch (MalformedURLException e) {
        logger.warning("Failed to create URL for the wsdl Location: 'http://localhost/wsdl/SOAService.wsdl', retrying as a local file");
        logger.warning(e.getMessage());
    }
    SOASERVICE_WSDL_LOCATION = url;
}

Hinweisdatei: // im URL-Konstruktor in http: // geändert.

Kommt jetzt in jax-ws-catalog.xml. Ohne jax-ws-catalog.xml versucht jax-ws in der Tat, die WSDL vom Speicherort zu laden

http: //localhost/wsdl/SOAService.wsdl

Mit jax-ws-catalog.xml können Sie jax-ws jedoch zu einer lokal gepackten WSDL umleiten, wenn versucht wird, auf die WSDL @ zuzugreifen.

http: //localhost/wsdl/SOAService.wsdl

Hier ist jax-ws-catalog.xml

<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system">
        <system systemId="http://localhost/wsdl/SOAService.wsdl"
                uri="wsdl/SOAService.wsdl"/>
    </catalog>

Sie sagen jax-ws, dass WSDL immer dann geladen werden muss, wenn dies erforderlich ist

http: //localhost/wsdl/SOAService.wsdl

Wo sollten Sie nun wsdl/SOAService.wsdl und jax-ws-catalog.xml platzieren? Das ist die Millionen-Dollar-Frage, nicht wahr?
Es sollte sich im META-INF-Verzeichnis Ihrer Anwendungsdatei befinden.

also so etwas

 ABCD.jar 
 | __ META-INF 
 | __ jax-ws-catalog.xml 
 | __ wsdl 
 | __ SOAService.wsdl 

Auf diese Weise müssen Sie nicht einmal die URL in Ihrem Client überschreiben, die auf den Proxy zugreift. Die WSDL wird in Ihrer JAR-Datei abgerufen, und Sie müssen in Ihrem Code keine fest codierten Dateisystempfade verwenden.

Weitere Informationen zu jax-ws-catalog.xml http://jax-ws.Java.net/nonav/2.1.2m1/docs/catalog-support.html

Hoffentlich hilft das

111
user507484

Ein anderer Ansatz, den wir erfolgreich gewählt haben, besteht darin, den WS-Client-Proxy-Code mit wsimport (von Ant als Ant-Task) zu generieren und das Attribut wsdlLocation anzugeben.

<wsimport debug="true" keep="true" verbose="false" target="2.1" sourcedestdir="${generated.client}" wsdl="${src}${wsdl.file}" wsdlLocation="${wsdl.file}">
</wsimport>

Da dies für ein Projekt mit mehreren WSDLs ausgeführt wird, löst das Skript den Wert $ (wsdl.file} dynamisch auf, der relativ zum JavaSource-Speicherort (oder/src, Während des Erstellungsprozesses werden die WSDL- und XSDs-Dateien an diesen Speicherort kopiert und in die JAR-Datei gepackt (ähnlich der von Bhasakar oben beschriebenen Lösung).

MyApp.jar
|__META-INF
   |__wsdl
      |__YourWebServiceName.wsdl
      |__YourWebServiceName_schema1.xsd
      |__YourWebServiceName_schmea2.xsd

Hinweis: Stellen Sie sicher, dass die WSDL-Dateien relative Verweise auf alle importierten XSDs und nicht auf http-URLs verwenden:

  <types>
    <xsd:schema>
      <xsd:import namespace="http://valueobject.common.services.xyz.com/" schemaLocation="YourWebService_schema1.xsd"/>
    </xsd:schema>
    <xsd:schema>
      <xsd:import namespace="http://exceptions.util.xyz.com/" schemaLocation="YourWebService_schema2.xsd"/>
    </xsd:schema>
  </types>

Im generierten Code finden wir Folgendes:

/**
 * This class was generated by the JAX-WS RI.
 * JAX-WS RI 2.2-b05-
 * Generated source version: 2.1
 * 
 */
@WebServiceClient(name = "YourService", targetNamespace = "http://test.webservice.services.xyz.com/", wsdlLocation = "/META-INF/wsdl/YourService.wsdl")
public class YourService_Service
    extends Service
{

    private final static URL YOURWEBSERVICE_WSDL_LOCATION;
    private final static WebServiceException YOURWEBSERVICE_EXCEPTION;
    private final static QName YOURWEBSERVICE_QNAME = new QName("http://test.webservice.services.xyz.com/", "YourService");

    static {
        YOURWEBSERVICE_WSDL_LOCATION = com.xyz.services.webservice.test.YourService_Service.class.getResource("/META-INF/wsdl/YourService.wsdl");
        WebServiceException e = null;
        if (YOURWEBSERVICE_WSDL_LOCATION == null) {
            e = new WebServiceException("Cannot find '/META-INF/wsdl/YourService.wsdl' wsdl. Place the resource correctly in the classpath.");
        }
        YOURWEBSERVICE_EXCEPTION = e;
    }

    public YourService_Service() {
        super(__getWsdlLocation(), YOURWEBSERVICE_QNAME);
    }

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

    /**
     * 
     * @return
     *     returns YourService
     */
    @WebEndpoint(name = "YourServicePort")
    public YourService getYourServicePort() {
        return super.getPort(new QName("http://test.webservice.services.xyz.com/", "YourServicePort"), YourService.class);
    }

    /**
     * 
     * @param features
     *     A list of {@link javax.xml.ws.WebServiceFeature} to configure on the proxy.  Supported features not in the <code>features</code> parameter will have their default values.
     * @return
     *     returns YourService
     */
    @WebEndpoint(name = "YourServicePort")
    public YourService getYourServicePort(WebServiceFeature... features) {
        return super.getPort(new QName("http://test.webservice.services.xyz.com/", "YourServicePort"), YourService.class, features);
    }

    private static URL __getWsdlLocation() {
        if (YOURWEBSERVICE_EXCEPTION!= null) {
            throw YOURWEBSERVICE_EXCEPTION;
        }
        return YOURWEBSERVICE_WSDL_LOCATION;
    }

}

Vielleicht hilft das auch. Es ist nur ein anderer Ansatz, der nicht den "Katalog" -Ansatz verwendet.

17
mark

Vielen Dank für die Antwort von Bhaskar Karambelkar, die ausführlich erklärt und mein Problem behoben hat. Aber auch ich möchte die Antwort für jemanden, der es eilig hat, in drei einfachen Schritten umformulieren

  1. Machen Sie Ihren lokalen wsdl-Standort als wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
  2. Erstellen Sie einen META-INF-Ordner direkt unter dem Quellcode. Legen Sie Ihre WSDL-Datei/en in einem Ordner unter META-INF ab, sagen Sie META-INF/wsdl
  3. Erstellen Sie eine XML-Datei jax-ws-catalog.xml unter META-INF (siehe unten)

    <catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" prefer="system"> <system systemId="http://localhost/wsdl/yourwsdlname.wsdl" uri="wsdl/yourwsdlname.wsdl" /> </catalog>

Verpacken Sie jetzt Ihr Glas. Kein Verweis mehr auf das lokale Verzeichnis, alles ist gepackt und referenziert

4
Hemus7

Für diejenigen unter Ihnen, die Spring verwenden, können Sie einfach mit dem classpath-Protokoll auf eine Klassenpfad-Ressource verweisen. Im Fall von wsdlLocation wird dies zu:

<wsdlLocation>classpath:META-INF/webservice.wsdl</wsdlLocation>

Beachten Sie, dass dies kein Standardverhalten Java ist. Siehe auch: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html

1

Hatte das genaue gleiche Problem, das hier beschrieben wird. Unabhängig davon, was ich gemäß den obigen Beispielen getan habe, um den Speicherort meiner WSDL-Datei (in unserem Fall von einem Webserver) zu ändern, wurde immer noch auf den ursprünglichen Speicherort verwiesen, der in der Quellstruktur des Serverprozesses eingebettet ist.

Nach [~ # ~] vielen [~ # ~] Stunden bemerkte ich, dass die Exception immer aus genau derselben Zeile geworfen wurde (in meinem Fall 41). Schließlich habe ich heute Morgen beschlossen, meinen Quell-Client-Code einfach an unseren Handelspartner zu senden, damit dieser zumindest verstehen kann, wie der Code aussieht, aber vielleicht seinen eigenen Code erstellt. Zu meinem Schock und Entsetzen fand ich eine Reihe von Klassen-Dateien gemischt mit meinen .Java-Dateien in meinem Client-Quelltextbaum. Wie bizarr !! Ich vermute, dass dies ein Nebenprodukt des JAX-WS Client Builder-Tools war.

Sobald ich diese dummen .class-Dateien gezappt und eine vollständige Bereinigung und Neuerstellung des Client-Codes durchgeführt habe, funktioniert alles perfekt !! Redonculous !!

YMMV, Andrew

0
Piko