93 votes

Client JAX-WS: quel est le chemin correct pour accéder au WSDL local?

Je suppose que c'est une question banale, mais après avoir passé beaucoup de temps à essayer tous les chemins, j'ai renoncé.
Le problème est que j'ai besoin de construire un client de service web à partir d'un fichier je suis été fournis. J'ai enregistré le fichier sur le système de fichiers local et, bien que je garde le fichier WSDL dans le bon dossier du système de fichiers, tout va bien. Quand je le déployer sur un serveur ou supprimer le fichier WSDL à partir du dossier système de fichiers le proxy ne peut pas trouver le fichier WSDL, et se lève une erreur. J'ai cherché sur le web et j'ai trouvé les postes suivants pourtant je ne suis pas été capable 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

Je suis à l'aide de NetBeans 6.1 (c'est un héritage de l'application que j'ai mise à jour avec ce nouveau client de service web). Ci-dessous est le JAX-WS classe de proxy :

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

               //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 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/ice/soaservice/ et baseurl variable contient le système de fichiers chemin d'accès complet (c:\path\to\the\project...\soaservice ). Le code ci-dessus génère 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, doit-je mettre à jour le wsdllocation de la classe de proxy? Alors comment dois-je dire à la SOAService classe dans WEB-INF/classes/com/ibm/ice/soaservice à la recherche pour le WSDL dans \WEB-INF\wsdl\client\SOAService.wsdl?

Je vous remercie à l'avance.

ÉDITÉ: j'ai trouvé cet autre lien - http://jianmingli.com/wp/?cat=41qui dire de mettre le WSDL dans le classpath. J'ai honte de poser la question: comment dois-je les mettre dans le classpath de l'application web?

120voto

Bhaskar Karambelkar Points 1571

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

Lorsque vous compilez le local fichier WSDL , remplacer l'emplacement WSDL et le régler pour quelque chose comme

http://localhost/wsdl/SOAService.wsdl

Ne vous inquiétez pas ce n'est qu'une URI et pas un URL , ce qui signifie que vous n'avez pas à avoir le WSDL disponible à cette adresse.
Vous pouvez le faire en passant par le wsdllocation option pour le wsdl compilateur java.

Cela permettra de changer votre code proxy à partir 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;
}

pour

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 file:// changé http:// dans l'URL constructeur.

Vient maintenant dans jax-ws-catalog.xml. Sans jax-ws-catalog.xml jax-ws, en effet, essayez de charger le fichier WSDL à partir de l'emplacement

http://localhost/wsdl/SOAService.wsdl

et l'échec, car aucun de ces WSDL seront disponibles.

Mais avec jax-ws-catalog.xml vous pouvez rediriger jax-ws locale emballés WSDL chaque fois qu'il tente d'accéder au fichier 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 quand jamais il a besoin pour charger des fichiers WSDL

http://localhost/wsdl/SOAService.wsdl

il doit charger à partir du chemin d'accès local wsdl/SOAService.wsdl.

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

donc quelque chose comme ceci

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

De cette façon, vous n'avez même pas à remplacer l'URL dans votre client que l'accès au proxy. Le WSDL est ramassé à l'intérieur de votre POT, et vous éviter d'avoir à le faire codée en dur système de fichiers chemins d'accès dans votre code.

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

Espère que ça aide

19voto

mark Points 51

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

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

Depuis que nous avons exécuter ce pour un projet avec plusieurs fichiers wsdl, le script résout le $(wsdl.fichier} valeur de manière dynamique ce qui est mis en place pour être /META-INF/wsdl/YourWebServiceName.wsdl par rapport à la JavaSource emplacement (ou /src, selon la configuration de votre projet). Lors de la compilation proess, le WSDL et XSDs les fichiers sont copiés à cet emplacement et emballé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 sont aide par rapport refrerences à tout importés XSDs et pas les Url 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 l' généré code, 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 cela peut vous aider trop. C'est juste une approche différente, à ne pas utiliser le "catalogue" de la démarche.

0voto

Piko Points 3470

A l' exact même problème qui est décrit ci-après. Peu importe ce 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 était encore le référencement de l'emplacement d'origine intégré au sein de l'arborescence des sources du processus du serveur.

Après de NOMBREUSES heures à essayer de débogage, j'ai remarqué que l'Exception était toujours levée à partir de la même ligne (dans mon cas, 41). Enfin ce matin, j'ai décidé de tout envoyer ma source code client pour nos partenaires commerciaux afin qu'ils puissent au moins de comprendre la façon dont le code ressemble, mais peut-être construire leur propre. À mon choc et horreur , j'ai trouvé un tas de fichiers de classe mixte avec mon .fichiers java dans mon client de l'arbre source. Comme c'est bizarre!! Je soupçonne que c'était un sous-produit de l'JAX-WS client builder outil.

Une fois que j'ai zappé ces stupides .les fichiers de classe et effectué un nettoyage complet et de reconstruire le code du client, tout fonctionne parfaitement!! Redonculous!!

YMMV, Andrew

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X