2010-11-12 3 views
66

Le problème est que je dois créer un client de service Web à partir d'un fichier qui m'a été fourni. J'ai stocké ce fichier sur le système de fichiers local et, tandis que je garde le fichier WSDL dans le bon dossier du système de fichiers, tout va bien. Lorsque je le déploie sur un serveur ou supprime le fichier WSDL du dossier du système de fichiers, le proxy ne trouve pas le fichier WSDL et génère une erreur. Je l'ai cherché sur le web et je l'ai trouvé les postes suivants mais je ne suis pas été en mesure de le faire fonctionner:
JAX-WS Loading WSDL from jar
http://www.java.net/forum/topic/glassfish/metro-and-jaxb/client-jar-cant-find-local-wsdl-0
http://blog.vinodsingh.com/2008/12/locally-packaged-wsdl.htmlClient JAX-WS: quel est le bon chemin pour accéder au WSDL local?

J'utilise NetBeans 6.1 (ce qui est un héritage application que je dois mettre à jour avec ce nouveau client de service Web). Ci-dessous la classe proxy JAX-WS:

@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); 
    } 

} 


Ceci est mon code pour utiliser le proxy:

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 mettre une copie du WSDL dans web-inf/wsdl/client/SOAService, donc je ne veux pas l'ajouter à META-INF aussi. Les classes de service sont dans WEB-INF/classes/com/ibm/eci/soaservice/ et la variable baseurl contient le chemin complet du système de fichiers (c: \ chemin \ vers \ le \ projet ... \ soaservice). Le code ci-dessus soulève l'erreur:

javax.xml.ws.WebServiceException: Failed to access the WSDL at: file:/WEB-INF/wsdl/client/SOAService.wsdl. It failed with: \WEB-INF\wsdl\client\SOAService.wsdl (cannot find the path)

Alors, tout d'abord, puis-je mettre à jour le WSDLLocation de la classe proxy? Alors comment puis-je dire à la classe SOAService dans WEB-INF/classes/com/ibm/eci/soaservice de rechercher le WSDL dans \ WEB-INF \ wsdl \ client \ SOAService.wsdl?

EDITED: J'ai trouvé cet autre lien - http://jianmingli.com/wp/?cat=41, qui dit de mettre le WSDL dans le classpath. J'ai honte de demander: comment puis-je le mettre dans le classpath de l'application web?

+0

Question similaire: [JAX-WS Chargement du fichier WSDL depuis le fichier jar] (http://stackoverflow.com/questions/764772/jax-ws-loading-wsdl-from-jar/15913322#15913322) – sleske

Répondre

97

La meilleure option est d'utiliser JAX-WS-catalog.xml

Lorsque vous compilez le fichier WSDL local, remplacer l'emplacement WSDL et le mettre à quelque chose comme

 
http://localhost/wsdl/SOAService.wsdl 

Ne vous inquiétez pas il s'agit uniquement d'un URI et non d'une URL, ce qui signifie que vous ne devez pas avoir le WSDL disponible à cette adresse.
Vous pouvez le faire en transmettant l'option wsdllocation au compilateur wsdl to java.

Ce faisant, vous changer votre code proxy de

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; 
} 

à

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; 
} 

fichier avis: // changé à l'adresse http: // dans le constructeur d'URL.

Maintenant disponible dans jax-ws-catalog.xml. Sans jax-ws-catalog.xml jax-ws va en effet essayer de charger le WSDL depuis l'emplacement

http://localhost/wsdl/SOAService.wsdl 
et échouer, car aucun WSDL de ce type ne sera disponible.

Mais avec jax-ws-catalogue.xml vous pouvez rediriger jax-ws à un WSDL localement empaqueté chaque fois qu'il essaye d'accéder au WSDL @

http://localhost/wsdl/SOAService.wsdl 
.

Voici 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> 

Ce que vous faites est de dire JAX-ws que si jamais il a besoin de charger WSDL à partir

http://localhost/wsdl/SOAService.wsdl 
, il faut le charger de chemin local wsdl/SOAService. wsdl.

Maintenant, où devriez-vous mettre wsdl/SOAService.wsdl et jax-ws-catalog.xml? C'est la question à un million de dollars, n'est-ce pas?
Il devrait être dans le répertoire META-INF de votre application Jar.

donc quelque chose comme ça

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

De cette façon, vous ne devez pas même remplacer l'URL dans votre client que l'accès au proxy. Le fichier WSDL est extrait de votre fichier JAR et vous évitez d'avoir des chemins de système de fichiers codés en dur dans votre code.

Plus d'informations sur JAX-WS-catalog.xml http://jax-ws.java.net/nonav/2.1.2m1/docs/catalog-support.html

espoir qui aide

+0

ok , je ne suis pas capable de résoudre le problème de cette façon dans l'application web: j'ai essayé de mettre wsdl dans web-inf sans succès, probablement pour mon manque de connaissances. Quoi qu'il en soit, cela fonctionne avec un pot, donc je vais faire une bibliothèque d'emballage, comme cela aurait dû être fait depuis le début. Merci pour votre soutien –

+9

Pour l'application Web l'emplacement correct est WEB-INF/classes/META-INF –

14

Une autre approche que nous avons adoptée est avec succès pour générer le code proxy client WS à l'aide wsimport (Ant, comme une tâche Ant) et spécifiez l'attribut wsdlLocation.

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

Puisque nous courons cela pour un projet w/plusieurs fichiers WSDL, le script résout la valeur de $ (de wsdl.file} dynamique qui est configuré pour être /META-INF/wsdl/YourWebServiceName.wsdl par rapport à la Emplacement JavaSource (ou/src, en fonction de la configuration de votre projet) Pendant la construction, les fichiers WSDL et XSD sont copiés à cet emplacement et empaquetés dans le fichier JAR (similaire à la solution décrite par Bhasakar ci-dessus)

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

Remarque: assurez-vous que les fichiers WSDL utilisent refrerences par rapport à tous les XSD importés et non http URL:

<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> 

Dans le code généré , nous trouvons ceci:

/** 
* 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; 
    } 

} 

Peut-être que cela pourrait aider aussi. C'est juste une approche différente qui n'utilise pas l'approche "catalogue".

+0

J'aime cette approche ... mais pourquoi le répertoire META-INF? – IcedDante

+1

S'il vous plaît noter que cela nécessite l'utilisation de JAX-WS RI 2.2, pas 2.1 qui vient avec JDK 6 par défaut – fnt

+0

Cela fonctionne 100% et magnifiquement. – Abs

0

Avait le exact même problème qui est décrit ici. Quoi que j'ai fait, en suivant les exemples ci-dessus, pour changer l'emplacement de mon fichier WSDL (dans notre cas à partir d'un serveur web), il faisait toujours référence à l'emplacement d'origine incorporé dans l'arborescence source du processus serveur.

Après BEAUCOUP heures en essayant de déboguer cela, j'ai remarqué que l'exception était toujours lancée de la même ligne (dans mon cas 41). Finalement, ce matin, j'ai décidé d'envoyer mon code client source à notre partenaire commercial pour qu'ils puissent au moins comprendre l'apparence du code, mais peut-être construire le leur. À mon choc et horreur J'ai trouvé un tas de fichiers de classe mélangés avec mes fichiers .java dans mon arbre source de client.C'est bizarre !! Je soupçonne que ceux-ci étaient un sous-produit de l'outil de création de client JAX-WS. Une fois que j'ai zappé ces fichiers .class stupides et effectué un nettoyage complet et la reconstruction du code client, tout fonctionne parfaitement !! Redonculous !!

YMMV, Andrew

1

Merci une tonne pour la réponse de Bhaskar Karambelkar ce qui explique en détail et fixe mon problème. Mais aussi je voudrais re phrase la réponse en trois étapes simples pour quelqu'un qui est pressé de fixer

  1. Faites votre wsdl emplacement local référence wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
  2. Créez un dossier META-INF juste sous la src . Mettez votre fichier wsdl/s dans un dossier sous META-INF, par exemple META-INF/wsdl
  3. Créer un fichier xml JAX-WS-catalog.xml sous META-INF comme ci-dessous

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

Maintenant emballez votre pot. Plus de référence au répertoire local, tout est empaqueté et référencé dans

Questions connexes