JAX-WS client: Quel est le chemin correct pour accéder à la WSDL locale?

le problème est que j'ai besoin de construire 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, pendant 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 que je supprime la WSDL du dossier du système de fichiers, le mandataire ne peut pas trouver la WSDL et génère une erreur. J'ai cherché sur le web et j'ai trouvé les messages suivants mais je ne suis pas en mesure de le faire fonctionner:

JAX-WS Chargement WSDL à partir de 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.html

J'utilise NetBeans 6.1 (il s'agit d'une application héritée que je dois mettre à jour avec ce nouveau client du service web). Ci-dessous figure la classe de 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);
    }

}



C'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;

   //classescomibmecisoaservice
   //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 placer une copie du fichier WSDL dans web-inf/wsdl/client/SOAService , donc je ne veux pas à l'ajouter à META-INF . 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 vers elle (c:pathtotheproject...soaservice). Le code ci-dessus génère l'erreur:

javax.xml.ws.WebServiceException: échec de l'accès à la WSDL à: fichier: / WEB-INF/wsdl/client / SOAService.wsdl. Il a échoué avec: WEB-INFwsdlclientSOAService.wsdl (ne trouve pas le chemin)

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

Edité : j'ai trouvé cet autre lien - http://jianmingli.com/wp/?cat=41 , qui disent de mettre le WSDL dans le chemin de classe. J'ai honte de demander: Comment puis-je le mettre dans le web application classpath?

75
demandé sur ROMANIA_engineer 2010-11-12 13:14:56

5 réponses

La meilleure option est d'utiliser jax-ws-catalogue.xml

lorsque vous compilez le fichier WSDL local, outrepassez l'emplacement WSDL et mettez-le à quelque chose comme

http://localhost/wsdl/SOAService.wsdl

ne vous inquiétez pas , il ne s'agit que d'une URI et non D'une URL, ce qui signifie que vous n'avez pas à avoir la WSDL disponible à cette adresse.

Vous pouvez le faire en passant l'option wsdllocation au compilateur java de la wsdl.

cela changera votre code de procuration 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;
}

Avis " fichier:// changé http:// dans l'URL constructeur.

est maintenant disponible en JAX-ws-catalog.XML. Sans jax-ws-catalogue.xml jax-ws va en effet essayer de charger la WSDL à partir de l'emplacement

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

Mais avec jax-ws-catalogue.vous pouvez rediriger jax-ws vers un paquet WSDL local à chaque fois qu'il essaie d'accéder à la 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 lorsque jamais il doit charger WSDL à partir de

http://localhost/wsdl/SOAService.wsdl
, il doit le charger à partir du chemin local wsdl/SOAService.wsdl.

maintenant où mettre wsdl / SOAService.wsdl et jax-ws-catalogue.xml ? C'est la question à un million de dollars, n'est-ce pas ?

Il devrait être dans le META-INF répertoire 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 n'avez même pas à outrepasser L'URL de votre client qui accède au proxy. La WSDL est récupérée à l'intérieur de votre JAR, et vous éviterez d'avoir à 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

L'espoir qui aide

106
répondu 2010-11-14 17:52:48

une autre approche que nous avons adoptée avec succès est de générer le code WS client proxy en utilisant wsimport (de Ant, comme tâche Ant) et de spécifier 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 exécutons ceci pour un projet w/ multiple WSDLs, le script résout le $(wsdl.fichier} valeur dynamiquement qui est configurée pour être / META-INF/wsdl / YourWebServiceName.wsdl relative à L'emplacement JavaSource (ou / src, selon la façon dont vous avez mis en place votre projet). Lors le processus de construction, les fichiers WSDL et XSDs sont copiés à cet endroit 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

Note: assurez-vous que les fichiers WSDL utilisent des références relatives à des URLs xsds importées et non à des URLs http:

  <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 un approche différente qui n'utilise pas l'approche" catalogue".

17
répondu mark 2010-11-29 11:26:46

remercie une tonne pour la réponse de Bhaskar Karambelkar qui explique en détail et a réglé mon problème. Mais aussi je voudrais reformuler la réponse en trois étapes simples pour quelqu'un qui est pressé de réparer

  1. Faites votre référence locale wsdl comme wsdlLocation= "http://localhost/wsdl/yourwsdlname.wsdl"
  2. crée un dossier META-INF directement sous le src. Mettez votre/Vos fichier (s) wsdl dans un dossier sous META-INF, say META-INF /wsdl
  3. créer un fichier xml jax-ws-catalogue.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>

emballez votre pot. Plus de référence à l'annuaire local, tout est emballé et référencé dans

2
répondu Hemus7 2015-12-31 14:04:53

pour ceux d'entre vous qui utilisent Spring, vous pouvez simplement référencer n'importe quelle ressource classpath en utilisant le protocole classpath. Ainsi dans le cas de la wsdlLocation, cela devient:

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

Remarque qui n'est pas standard Java comportement. Voir aussi: http://docs.spring.io/spring/docs/current/spring-framework-reference/html/resources.html

2
répondu Martin Devillers 2016-12-07 10:17:55

avait le exact même problème qui est décrit ici. Peu importe ce que j'ai fait, en suivant les exemples ci-dessus, pour changer l'emplacement de mon fichier WSDL (dans notre cas d'un serveur web), il faisait toujours référence à l'emplacement original intégré dans l'arborescence des sources du processus du serveur.

après beaucoup heures en essayant de corriger cela, j'ai remarqué que L'Exception a toujours été jeté de la même ligne exacte (dans mon décision 41). Enfin ce matin, j'ai décidé d'envoyer mon code client source à notre partenaire commercial pour qu'ils puissent au moins comprendre à quoi ressemble le code, mais peut-être construire le leur. À mon choc et horreur j'ai trouvé un tas de fichiers de classe mixte avec mon .les fichiers java dans l'arborescence des sources de mon client. Comme c'est bizarre!! Je pense que c'était un sous-produit de l'outil client builder de JAX-WS.

une fois j'ai zappé ces idiotes .les fichiers de classe et effectué un nettoyage complet et la reconstruction du code client, tout fonctionne parfaitement!! Redonculous!!

YMMV, Andrew

0
répondu Piko 2012-02-08 18:02:41