web-dev-qa-db-fra.com

Comment fonctionne un client généré par wsimport?

Avant toute chose, je veux que vous sachiez que je peux déjà me connecter au serveur de service Web. Je pose cette question parce que je veux acquérir une connaissance plus approfondie du fonctionnement d'un client généré par wsimport. D'après mes recherches, wsimport utilise JAXWS. Veuillez noter que je n'ai aucune connaissance de JAXWS.

J'ai généré mon client à l'aide de wsimport. Le WSDL que j'ai utilisé provient d'un service Web Axis2 et a été généré automatiquement par Axis2. Les classes ci-dessous sont les résultats de wsimport:

En dessous de com.datamodel.xsd

  • DataBeanRequest.Java
  • DataBeanResponse.Java
  • ObjectFactory.Java
  • package-info.Java

En dessous de com.service

  • MyWebService.Java
  • MyWebServicePortType.Java
  • MyMethod.Java
  • MyMethodResponse.Java
  • ObjectFactory.Java
  • package-info.Java

Avec les classes ci-dessus, je peux dire que com.datamodel.xsd contient les beans utilisés par le serveur de service Web (à l'exclusion de ObjectFactory et package-info). Pendant ce temps, MyMethod et MyMethodResponse sont également des beans utilisés pour définir le paramètre de demande et de réponse de la méthode/opération du service Web.

Voici mes questions: (Vous n'avez pas vraiment besoin de répondre à toutes si vous ne connaissez pas les réponses à certaines de mes questions. :) Et n'hésitez pas à partager toute information que vous pensez que je pourrais trouver utile.)

Suis-je correct avec

  • Suis-je correct avec mes hypothèses ci-dessus?
  • Quelle est la fonction des autres classes?
  • J'ai inspecté MyWebService et il contient une annotation faisant référence à l'emplacement absolu du WSDL que j'ai utilisé pour générer le client. Quelle est la pertinence de spécifier le wsdllocation dans le client? Comment le client utilise-t-il ces informations?
  • J'ai remarqué que l'URL réelle du service Web n'est déclarée dans aucune des classes générées. Comment le client sait-il où il doit se connecter?
  • Le fichier WSDL a-t-il été annoté afin que le client puisse lire l'URL du fichier WSDL lors de la connexion? Si oui, cela signifie-t-il que le fichier WSDL est toujours lu lorsqu'une nouvelle connexion doit être établie?
  • Puisqu'il me faut compiler mon application et l'installer sur un autre serveur, le deviendra invalide. Puis-je le définir sur un chemin relatif au lieu d'un chemin absolu? Comment? (Réponse: Oui, il peut être défini sur un chemin relatif. La commande wsimport a un attribut wsdllocation dans lequel la valeur de wsdllocation peut être spécifiée.)
  • Et si je dois me connecter à un HTTPS. Comment puis-je définir le certificat du serveur?
  • Existe-t-il une différence lorsque je génère mon client à l'aide de wsimport et lorsque je le génère à l'aide d'Axis2 ou d'Apache CXF.
29
Arci

Avant de répondre aux questions, quelques précisions: JAX-WS est une spécification pour implémenter des services Web en Java. Il décrit comment les artefacts WSDL peuvent être mappés à Java et comment ce mappage peut être appliqué à l'aide d'annotations. Vous pouvez télécharger la spécification ici . L'outil wsimport fait partie de l'implémentation de référence de cette spécification et l'implémentation de référence font partie de la bibliothèque de classes Java. Il existe plusieurs implémentations alternatives, telles que Axis2, CXF ou Metro, qui améliorent la prise en charge de base de JAX-WS avec prise en charge de normes supplémentaires telles que WS-ReliableMessaging ou WS-Security.

Passons maintenant à vos questions:

Suis-je correct avec mes hypothèses ci-dessus?

Oui, vous l'êtes.

Quelle est la fonction des autres classes?

Le package-info existe pour mapper l'espace de noms XML utilisé dans le service Web au package dans lequel résident vos classes d'implémentation. L'espace de noms est normalement différent d'un Java (normalement, il s'agit d'une URL), ce qui rend le mappage nécessaire.

Le ObjectFactory vous permet de créer n'importe quel message envoyé et reçu par le service. Vous en avez besoin si vous voulez accrocher du code devant votre classe de stub, fournir des messages modifiés ou des choses similaires.

Je ne vois pas le contenu de vos classes, mais si je le comprends bien, MyWebServicePortType est une interface qui ressemble à portType dans votre WSDL. Autrement dit, il mappe les opérations et leurs signatures dans le WSDL à Java. Si vous voulez fournir le service (ce que vous ne faites pas, vous posez des questions sur le client), vous le feriez besoin d'implémenter cette interface. Lorsque vous implémentez le client, vous l'utilisez simplement.

Enfin, la classe MyWebService contient le stub client dont vous avez besoin si vous souhaitez appeler le service Web.

J'ai inspecté MyWebService et il contient une annotation faisant référence à l'emplacement absolu du WSDL que j'ai utilisé pour générer le client. Quelle est la pertinence de spécifier le wsdllocation dans le client? Comment le client utilise-t-il ces informations?

L'interface que vous avez générée contient la signature du portType du service, mais elle n'explique pas comment vous pouvez parler au service. Cela fait partie de la liaison dans le WSDL. Le paramètre le plus basique est un style document/littéral pour les messages utilisant SOAP sur HTTP. D'autres configurations, telles que SOAP sur JMS, sont possibles et votre client doit savoir quel protocole utiliser. Par conséquent, il a besoin de la liaison WSDL. De plus, comme vous le déclarerez plus tard, il n'y a pas d'adresse de point de terminaison dans vos fichiers Java. Cette adresse est également lue à partir du WSDL.

J'ai remarqué que l'URL réelle du service Web n'est déclarée dans aucune des classes générées. Comment le client sait-il où il doit se connecter?

Il lit le address du port du service dans le WSDL. Il se trouve à la fin du WSDL.

Le fichier WSDL a-t-il été annoté afin que le client puisse lire l'URL du fichier WSDL lors de la connexion?

Non, le port est un élément typique d'un point de terminaison de service Web concret. Il n'y a rien de spécial nécessaire ici.

Si oui, cela signifie-t-il que le fichier WSDL est toujours lu lorsqu'une nouvelle connexion doit être établie?

Eh bien, il pourrait y avoir une mise en cache côté client (je ne connais pas les détails de l'implémentation de référence sur celui-ci). D'un point de vue conceptuel: oui, ça l'est.

Et si je dois me connecter à un HTTPS. Comment puis-je définir le certificat du serveur

Cela peut être délicat, je ne peux pas vous donner une réponse prête à l'emploi. Je suggère de lire les questions sur ce sujet, comme celle-ci .

Existe-t-il une différence lorsque je génère mon client à l'aide de wsimport et lorsque je le génère à l'aide d'Axis2 ou d'Apache CXF

Oui il y a. wsimport est mieux, n'utilisez pas wsdl2Java. Voici une description, pourquoi .

45
joergl

Vous avez demandé: j'ai remarqué que l'URL réelle du service Web n'est déclarée dans aucune des classes générées. Comment le client sait-il où il doit se connecter?

Si le WSDL a été téléchargé à l'aide d'un navigateur et passé en entrée à wsimport , l'emplacement du fichier wsdl local est intégré dans le code généré. C'est pourquoi vous ne voyez pas l'emplacement de service réel dans le code généré. Cela signifie également que si vous avez supprimé la copie locale du fichier wsdl, le code généré ne fonctionnera pas (lorsqu'il est inovké à l'aide d'une méthode principale).

Si l'URL du wsdl a été passée en entrée à wsimport alors cette URL est incorporée dans le code généré, qui est en outre utilisé pour obtenir l'emplacement de service réel. L'idée est que les emplacements WSDL sont fixes. Ils devraient être dans un UDDI ou dans un fichier local. Cela permet aux services réels de se déplacer et s'ils bougent, il vous suffit de modifier la copie locale du fichier wsdl seul ou de mettre à jour le wsdl dans l'UDDI. [la plupart du temps, cela ne se produit pas car les emplacements de service ne sont jamais IP mais des noms DNS]

C'est pourquoi ce n'est jamais une bonne idée de publier le wsdl sur le même serveur où votre webservice fonctionne

3
krish