Red Hat Training
A Red Hat training course is available for Red Hat JBoss Enterprise Application Platform
15.5.2. Développer une application client JAX-WS
Service
- Aperçu
- Un
Service
est une abstraction qui représente un service WSDL. Un service WSDL est une collection de ports liés les uns aux autres, dont chacun comprend un type de port lié à un protocole particulier et une adresse de point de terminaison particulière.Généralement, le service est créé quand le reste des stubs du composant sont générés à partir d'un contrat WSDL existant. Le contrat WSDL est disponible via l'URL WSDL du point de terminaison déployé, ou peut être créé à partir de la source de point de terminaison à l'aide de la commandewsprovide.sh
dans le répertoire de/bin/ EAP_HOME
.On appelle cela une utilisation statique. Dans un tel cas, vous créez des instances de la classeService
, créée elle-même comme un des composants stubs.Vous pouvez également créer le service manuellement, par la méthodeService.create
. On appelle cela une utilisation dynamic. - Utilisation
- Cas d'utilisation static
- Le cas d'utilisation statique pour un client JAX-WS suppose que vous ayiez déjà un contrat WSDL. Ceci peut être généré par un outil externe ou généré à l'aide des annotations JAX-WS qui conviennent lorsque vous créez votre point de terminaison de JAX-WS.Pour générer vos stubs de composants, vous pouvez utiliser le script
wsconsume.sh
ouwsconsume.bat
inclus dansEAP_HOME/bin/
. Ce script prend le WSDL URL ou fichier en tant que paramètre, et génère de nombreux fichiers structurés dans un arborescence de répertoires. La source et les fichiers de classe représentant votreService
s'appellentCLASSNAME_Service.java
etCLASSNAME_Service.class
, respectivement.La classe d'implémentation générée possède deux constructeurs publics, un sans argument et un avec deux arguments. Les deux arguments représentent respectivement l'emplacement WSDL (unjava.net.URL
) et le nom du service (unjavax.xml.namespace.QName
).Le constructeur sans argument est celui qui est le plus souvent utilisé. Dans ce cas, l'emplacement WSDL et le nom du service sont ceux que l'on trouve dans le fichier WSDL. Ceux-ci sont définis implicitement à partir de l'annotation@WebServiceClient
qui décore la classe générée.Exemple 15.19. Exemple de classe de service générée
@WebServiceClient(name="StockQuoteService", targetNamespace="http://example.com/stocks", wsdlLocation="http://example.com/stocks.wsdl") public class StockQuoteService extends javax.xml.ws.Service { public StockQuoteService() { super(new URL("http://example.com/stocks.wsdl"), new QName("http://example.com/stocks", "StockQuoteService")); } public StockQuoteService(String wsdlLocation, QName serviceName) { super(wsdlLocation, serviceName); } ... }
- Cas d'utilisation dynamic
- Dans un cas d'utilisation dynamic, aucun stub n'est généré automatiquement. Au lieu de cela, le client de service web utilise la méthode
Service.create
pour créer des instances deService
. Le fragment de code suivant illustre ce processus.Exemple 15.20. Création de service manuellement
URL wsdlLocation = new URL("http://example.org/my.wsdl"); QName serviceName = new QName("http://example.org/sample", "MyService"); Service service = Service.create(wsdlLocation, serviceName);
- Handler Resolver
- JAX-WS fournit un framework plug-in flexible pour des modules de traitement des messages, appelés gestionnaires. Ces gestionnaires étendent les fonctionnalités d'un système de runtime JAX-WS. Une instance de
Service
donnera accès à unHandlerResolver
grâce à une paire de méthodesgetHandlerResolver
etsetHandlerResolver
qui peuvent configurer un ensemble de gestionnaires sur la base de service, de port ou de protocole.Lorsqu'une instance deService
crée un proxy ou une instanceDispatch
, le Handler Resolver enregistré dans le service crée la chaîne de gestionnaires requise. Les changements ultérieurs apportés au Handler Resolver qui sont configurés pour une instance deService
n'affectent pas les gestionnaires sur proxies préalablement créés ou les instances deDispatch
. - Exécuteur
- Les instances de
Service
peuvent être configurées par unjava.util.concurrent.Executor
.Executor
invoque les callbacks asynchrones demandés par l'application. Les méthodessetExecutor
etgetExecutor
deService
peuvent modifier et extraire l'Executor
configuré pour un service.
Un dynamic proxy est une instance de proxy de client utilisant une des méthodes getPort
fournie par le Service
. Le portName
indique le nom du port WSDL que le service utilise. La serviceEndpointInterface
indique l'interface du point de terminaison du service prise en charge par l'instance du proxy dynamique créé.
Exemple 15.21. Méthodes getPort
public <T> T getPort(QName portName, Class<T> serviceEndpointInterface) public <T> T getPort(Class<T> serviceEndpointInterface)
wsconsume.sh
qui interprète le WSDL et qui, à partir de cela, crée des classes Java.
Exemple 15.22. Renvoie le Port d'un Service
@WebServiceClient(name = "TestEndpointService", targetNamespace = "http://org.jboss.ws/wsref", wsdlLocation = "http://localhost.localdomain:8080/jaxws-samples-webserviceref?wsdl") public class TestEndpointService extends Service { ... public TestEndpointService(URL wsdlLocation, QName serviceName) { super(wsdlLocation, serviceName); } @WebEndpoint(name = "TestEndpointPort") public TestEndpoint getTestEndpointPort() { return (TestEndpoint)super.getPort(TESTENDPOINTPORT, TestEndpoint.class); } }
@WebServiceRef
L'annotation @WebServiceRef
déclare une référence à un Service Web. Elle suit un modèle de ressource indiqué par l'annotation javax.annotation.Resource
définie dans http://www.jcp.org/en/jsr/summary?id=250.
Cas d'utilisateur @WebServiceRef
- Vous pouvez l'utiliser pour définir une référence dont le type est une classe de
Service
générée. Dans ce cas, l'élément de valeur et le type font tous deux référence au type de classe deService
généré. En outre, si le type de référence peut être déduit grâce au champ ou à la déclaration de méthode à laquelle l'annotation est s'applique, les éléments de type et de valeur peuvent (mais n'y sont pas tenus) avoir la valeur par défaut deObject.class
. Si le type ne peut pas être déduit, alors l'élément au moins doit être présent, avec une valeur par défaut. - Vous pouvez l'utiliser pour définir une référence de type SEI. Dans ce cas, l'élément de type peut (mais pas forcément) se présenter avec sa valeur par défaut si le type de référence peut être déduit de la déclaration de champ ou de méthode annotée. Toutefois, l'élément de valeur doit toujours être présent et faire référence à un type de classe de service généré, qui est un sous-type de
javax.xml.ws.Service
. L'élémentwsdlLocation
, s'il est présent, substitue les informations d'emplacement WSDL spécifiées dans l'annotation@WebService
de la classe de service générée référencée.Exemple 15.23. Exemples de
@WebServiceRef
public class EJB3Client implements EJB3Remote { @WebServiceRef public TestEndpointService service4; @WebServiceRef public TestEndpoint port3;
Les Services Web XML utilisent des messages XML pour la communication entre le point de terminaison, qui est déployé dans le conteneur Java EE, et tous les clients. Les messages XML utilisent un langage XML appelé Simple Object Access Protocol (SOAP). L'API JAX-WS fournit les mécanismes pour que le point de terminaison et les clients puissent chacun être en mesure d'envoyer et de recevoir des messages SOAP. Le Marshalling, ou conversion de paramètres, est l'action de convertir le message XML SOAP en Objet Java.
Dispatch
fournit cette fonctionnalité. Dispatch
opère dans un des deux modes d'utilisation, qui sont identifiés par l'une des constantes suivantes.
javax.xml.ws.Service.Mode.MESSAGE
- ce mode ordonne aux applications clientes de travailler directement avec les structures de message qui sont spécifiques au protocole. Si utilisé avec une liaison de protocole SOAP, une application cliente fonctionne directement avec un message SOAP.javax.xml.ws.Service.Mode.PAYLOAD
- ce mode amène le client à travailler avec la charge elle-même. Par exemple, s'il est utilisé avec une liaison de protocole SOAP, une application cliente travaillera alors avec le contenu SOAP plutôt qu'avec l'intégralité du message SOAP.
Dispatch
est une API de bas niveau qui exige des clients de structurer les messages ou les charges en XML, avec une adhérence stricte aux normes du protocole individuel et une connaissance approfondie de la structure de message ou de la charge. Dispatch
est une classe générique qui prend en charge l'entrée et la sortie des messages ou des charges de message de n'importe quel type.
Exemple 15.24. Utilisation de Dispatch
Service service = Service.create(wsdlURL, serviceName); Dispatch dispatch = service.createDispatch(portName, StreamSource.class, Mode.PAYLOAD); String payload = "<ns1:ping xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>"; dispatch.invokeOneWay(new StreamSource(new StringReader(payload))); payload = "<ns1:feedback xmlns:ns1='http://oneway.samples.jaxws.ws.test.jboss.org/'/>"; Source retObj = (Source)dispatch.invoke(new StreamSource(new StringReader(payload)));
L'interface BindingProvider
représente un composant qui fournit une liaison de protocole que les clients peuvent utiliser. Elle est implémentée et étendue par l'interface Dispatch
.
BindingProvider
peuvent fournir des possibilités d'opérations asynchrones. Comme les opérations asynchrones, les invocations sont découplées de l'instance BindingProvider
au moment de l'invocation. Le contexte de réponse n'est pas mis à jour lorsque l'opération est terminée. Au lieu de cela, un contexte de réponse distinct est fourni à l'aide de l'interface de réponse
.
Exemple 15.25. Invocation asynchrone
public void testInvokeAsync() throws Exception { URL wsdlURL = new URL("http://" + getServerHost() + ":8080/jaxws-samples-asynchronous?wsdl"); QName serviceName = new QName(targetNS, "TestEndpointService"); Service service = Service.create(wsdlURL, serviceName); TestEndpoint port = service.getPort(TestEndpoint.class); Response response = port.echoAsync("Async"); // access future String retStr = (String) response.get(); assertEquals("Async", retStr); }
@Oneway
L'annotation @Oneway
indique que la méthode web donnée ne prend un message d'entrée mais ne renvoie aucun message de sortie. Habituellement, une méthode @Oneway
renvoie le thread de contrôle à l'application appelante avant l'exécution de la méthode commerciale.
Exemple 15.26. Exemple d'invocation @Oneway
@WebService (name="PingEndpoint") @SOAPBinding(style = SOAPBinding.Style.RPC) public class PingEndpointImpl { private static String feedback; @WebMethod @Oneway public void ping() { log.info("ping"); feedback = "ok"; } @WebMethod public String feedback() { log.info("feedback"); return feedback; } }
Il y a deux propriétés qui contrôlent le comportement du délai d'expiration de la connexion HTTP et le délai d'attente d'un client qui attend de recevoir un message. Le premier est javax.xml.ws.client.connectionTimeout
et le second est javax.xml.ws.client.receiveTimeout
. Chacun est exprimé en millisecondes, et la syntaxe correcte est indiquée ci-dessous.
Exemple 15.27. Configuration de timeout JAX-WS
public void testConfigureTimeout() throws Exception { //Set timeout until a connection is established ((BindingProvider)port).getRequestContext().put("javax.xml.ws.client.connectionTimeout", "6000"); //Set timeout until the response is received ((BindingProvider) port).getRequestContext().put("javax.xml.ws.client.receiveTimeout", "1000"); port.echo("testTimeout"); }