web-dev-qa-db-fra.com

Comment définir le délai d'expiration pour un client de service Web JAX-WS?

J'ai utilisé JAXWS-RI 2.1 pour créer une interface pour mon service Web, basée sur un WSDL. Je ne peux pas interagir avec le service Web, mais je n'ai pas été en mesure de spécifier de délai d'expiration pour l'envoi de demandes au service Web. Si, pour une raison quelconque, il ne répond pas, le client semble faire tourner ses roues pour toujours.

La chasse autour a révélé que je devrais probablement essayer de faire quelque chose comme ceci:

((BindingProvider)myInterface).getRequestContext().put("com.Sun.xml.ws.request.timeout", 10000);
((BindingProvider)myInterface).getRequestContext().put("com.Sun.xml.ws.connect.timeout", 10000);

J'ai également découvert que, selon la version de JAXWS-RI dont vous disposez, vous devrez peut-être définir ces propriétés à la place:

((BindingProvider)myInterface).getRequestContext().put("com.Sun.xml.internal.ws.request.timeout", 10000);
((BindingProvider)myInterface).getRequestContext().put("com.Sun.xml.internal.ws.connect.timeout", 10000);

Le problème que j'ai est que, peu importe ce qui précède est correct, je ne sais pas je peux le faire. Tout ce que j'ai est une sous-classe Service qui implémente l'interface auto-générée vers le service Web et au moment où cela s'installe, si le WSDL est non réactif, alors c'est déjà trop tard pour définir les propriétés:

MyWebServiceSoap soap;
MyWebService service = new MyWebService("http://www.google.com");
soap = service.getMyWebServiceSoap();
soap.sendRequestToMyWebService();

Est-ce que quelqu'un peut-il me montrer la bonne direction?!

86
ninesided

Je sais que cela est vieux et a répondu ailleurs, mais j'espère que cela ferme ce processus. Je ne sais pas pourquoi vous voudriez télécharger le WSDL de manière dynamique, mais les propriétés du système:

Sun.net.client.defaultConnectTimeout (default: -1 (forever))
Sun.net.client.defaultReadTimeout (default: -1 (forever))

devrait s'appliquer à toutes les lectures et les connexions à l'aide de HttpURLConnection utilisée par JAX-WS. Cela devrait résoudre votre problème si vous obtenez le WSDL depuis un emplacement distant - mais un fichier sur votre disque local est probablement meilleur!

Ensuite, si vous souhaitez définir des délais d'attente pour des services spécifiques, une fois que vous avez créé votre proxy, vous devez le transtyper vers un BindingProvider (que vous connaissez déjà), obtenez le contexte de la demande et définissez vos propriétés. La documentation en ligne de JAX-WS est fausse, ce sont les noms de propriété corrects (enfin, ils fonctionnent pour moi).

MyInterface myInterface = new MyInterfaceService().getMyInterfaceSOAP();
Map<String, Object> requestContext = ((BindingProvider)myInterface).getRequestContext();
requestContext.put(BindingProviderProperties.REQUEST_TIMEOUT, 3000); // Timeout in millis
requestContext.put(BindingProviderProperties.CONNECT_TIMEOUT, 1000); // Timeout in millis
myInterface.callMyRemoteMethodWith(myParameter);

Bien sûr, c’est une façon horrible de faire les choses, je créerais une usine de Nice pour produire ces fournisseurs de reliure qui peuvent être injectés avec les délais d’expiration que vous souhaitez.

83
alpian

Les propriétés de la réponse acceptée ne fonctionnent pas pour moi, probablement parce que j'utilise l'implémentation JBoss de JAX-WS?

L'utilisation d'un ensemble de propriétés différent (trouvé dans le Guide de l'utilisateur de JBoss JAX-WS ) l'a fait fonctionner:

//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");
34
jwaddell

Voici ma solution de travail:

// --------------------------
// SOAP Message creation
// --------------------------
SOAPMessage sm = MessageFactory.newInstance().createMessage();
sm.setProperty(SOAPMessage.WRITE_XML_DECLARATION, "true");
sm.setProperty(SOAPMessage.CHARACTER_SET_ENCODING, "UTF-8");

SOAPPart sp = sm.getSOAPPart();
SOAPEnvelope se = sp.getEnvelope();
se.setEncodingStyle("http://schemas.xmlsoap.org/soap/encoding/");
se.setAttribute("xmlns:SOAP-ENC", "http://schemas.xmlsoap.org/soap/encoding/");
se.setAttribute("xmlns:xsd", "http://www.w3.org/2001/XMLSchema");
se.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");

SOAPBody sb = sm.getSOAPBody();
// 
// Add all input fields here ...
// 

SOAPConnection connection = SOAPConnectionFactory.newInstance().createConnection();
// -----------------------------------
// URL creation with TimeOut connexion
// -----------------------------------
URL endpoint = new URL(null,
                      "http://myDomain/myWebService.php",
                    new URLStreamHandler() { // Anonymous (inline) class
                    @Override
                    protected URLConnection openConnection(URL url) throws IOException {
                    URL clone_url = new URL(url.toString());
                    HttpURLConnection clone_urlconnection = (HttpURLConnection) clone_url.openConnection();
                    // TimeOut settings
                    clone_urlconnection.setConnectTimeout(10000);
                    clone_urlconnection.setReadTimeout(10000);
                    return(clone_urlconnection);
                    }
                });


try {
    // -----------------
    // Send SOAP message
    // -----------------
    SOAPMessage retour = connection.call(sm, endpoint);
}
catch(Exception e) {
    if ((e instanceof com.Sun.xml.internal.messaging.saaj.SOAPExceptionImpl) && (e.getCause()!=null) && (e.getCause().getCause()!=null) && (e.getCause().getCause().getCause()!=null)) {
        System.err.println("[" + e + "] Error sending SOAP message. Initial error cause = " + e.getCause().getCause().getCause());
    }
    else {
        System.err.println("[" + e + "] Error sending SOAP message.");

    }
}
12
vnoel
ProxyWs proxy = (ProxyWs) factory.create();
Client client = ClientProxy.getClient(proxy);
HTTPConduit http = (HTTPConduit) client.getConduit();
HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
httpClientPolicy.setConnectionTimeout(0);
httpClientPolicy.setReceiveTimeout(0);
http.setClient(httpClientPolicy);

Cela a fonctionné pour moi.

9
Daniel Kaplan

Si vous utilisez JAX-WS sur JDK6, utilisez les propriétés suivantes:

com.Sun.xml.internal.ws.connect.timeout  
com.Sun.xml.internal.ws.request.timeout
7
Domenico Briganti

Dans le cas où votre serveur d'applications est WebLogic (pour moi, il s'agissait de 10.3.6), les propriétés responsables des délais d'expiration sont les suivantes:

com.Sun.xml.ws.connect.timeout 
com.Sun.xml.ws.request.timeout
4
E.Egiazarov

Je ne sais pas si cela vous aidera dans votre contexte ...

L'objet soap peut-il être transformé en BindingProvider?

MyWebServiceSoap soap;
MyWebService service = new MyWebService("http://www.google.com");
soap = service.getMyWebServiceSoap();
// set timeouts here
((BindingProvider)soap).getRequestContext().put("com.Sun.xml.internal.ws.request.timeout", 10000);
    soap.sendRequestToMyWebService();

Par ailleurs, si vous souhaitez définir le délai d’initialisation de l’objet MyWebService, cela ne vous aidera pas.

Cela a fonctionné pour moi lorsque je voulais expirer les appels individuels du WebService.

3
Ron Tuffin

le moyen le plus simple d'éviter une extraction lente du WSDL distant lorsque vous instanciez votre SEI consiste à ne pas extraire le WSDL du point de terminaison du service distant au moment de l'exécution.

cela signifie que vous devez mettre à jour votre copie WSDL locale chaque fois que le fournisseur de service apporte un changement impactant, mais cela signifie également que vous devez mettre à jour votre copie locale chaque fois que le fournisseur de service effectue un changement impactant.

Lorsque je génère mes stubs client, je demande au moteur d'exécution JAX-WS d'annoter le SEI de manière à ce qu'il lise le WSDL à partir d'un emplacement prédéterminé sur le chemin d'accès aux classes. Par défaut, l'emplacement est relatif à l'emplacement du package SEI du service.


<wsimport
    sourcedestdir="${dao.helter.dir}/build/generated"
    destdir="${dao.helter.dir}/build/bin/generated"
    wsdl="${dao.helter.dir}/src/resources/schema/helter/helterHttpServices.wsdl"
    wsdlLocation="./wsdl/helterHttpServices.wsdl"
    package="com.helter.esp.dao.helter.jaxws"
    >
    <binding dir="${dao.helter.dir}/src/resources/schema/helter" includes="*.xsd"/>
</wsimport>
<copy todir="${dao.helter.dir}/build/bin/generated/com/helter/esp/dao/helter/jaxws/wsdl">
    <fileset dir="${dao.helter.dir}/src/resources/schema/helter" includes="*" />
</copy>

l'attribut wsldLocation indique au SEI où il peut trouver le WSDL et la copie s'assure que le wsdl (et le support de xsd .. etc.) se trouve au bon emplacement.

étant donné que l'emplacement est relatif à l'emplacement du paquet SEI, nous créons un nouveau sous-paquet (répertoire) appelé wsdl et copions tous les artefacts wsdl qui s'y trouvent.

à ce stade, tout ce que vous avez à faire est de vous assurer d'inclure tous les fichiers * .wsdl, * .xsd en plus de tous les fichiers * .class lorsque vous créez votre fichier jar d'artefact de stub client.

(au cas où vous seriez curieux, l'annotation @webserviceClient est l'emplacement où cet emplacement wsdl est défini dans le Java

@WebServiceClient(name = "httpServices", targetNamespace = "http://www.helter.com/schema/helter/httpServices", wsdlLocation = "./wsdl/helterHttpServices.wsdl")
2
Helter Scelter