Hello,
Voici mon problème. J'ai deux applications web, l'une fournissant un web-service (appellons-la ws-provider), l'autre consommant ce web-service (on va l'appeller ws-client).
La communication entre ces deux systèmes est sécurisée par une connection SSL bidirectionnelle (2-ways SSL). La configuration des deux serveurs est normalement correctement réalisée (installation des certificats, configuration des propriétés système, paramétrage des Tomcat, etc.)
Les deux serveurs tournent sur du Tomcat (5.5 pour ws-provider, 6 pour l'autre), Java 6 et du Jax-WS comme librairie de web-service.
Quand l'utilisateur se connecte à l'application ws-client et réalise les opérations lançant l'appel au web-service, cet appel va généralement échouer avec l'erreur suivante :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| com.sun.xml.ws.client.ClientTransportException: The server sent HTTP status code 400: No client certificate chain in this request
at com.sun.xml.ws.transport.http.client.HttpClientTransport.checkResponseCode(HttpClientTransport.java:218)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.process(HttpTransportPipe.java:137)
at com.sun.xml.ws.transport.http.client.HttpTransportPipe.processRequest(HttpTransportPipe.java:74)
at com.sun.xml.ws.api.pipe.Fiber.__doRun(Fiber.java:559)
at com.sun.xml.ws.api.pipe.Fiber._doRun(Fiber.java:518)
at com.sun.xml.ws.api.pipe.Fiber.doRun(Fiber.java:503)
at com.sun.xml.ws.api.pipe.Fiber.runSync(Fiber.java:400)
at com.sun.xml.ws.client.Stub.process(Stub.java:234)
at com.sun.xml.ws.client.sei.SEIStub.doProcess(SEIStub.java:120)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:230)
at com.sun.xml.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:210)
at com.sun.xml.ws.client.sei.SEIStub.invoke(SEIStub.java:103)
at $Proxy33.createOrRenewRequest(Unknown Source)
at my.app.MyPushRequest.sendXMLRequest(MyPushRequest.java:29)
at my.app.MyRequestCreation.sendRequestForDraftApproval(MyRequestCreation.java:284) |
Du côté du ws-provider j'ai cette erreur :
1 2 3 4 5 6 7 8
| WARNING: Exception getting SSL attributes
java.net.SocketException: SSL Cert handshake timeout
at org.apache.tomcat.util.net.jsse.JSSE14Support.synchronousHandshake(JSSE14Support.java:101)
at org.apache.tomcat.util.net.jsse.JSSE14Support.handShake(JSSE14Support.java:67)
at org.apache.tomcat.util.net.jsse.JSSESupport.getPeerCertificateChain(JSSESupport.java:121)
at org.apache.coyote.http11.Http11Processor.action(Http11Processor.java:1127)
at org.apache.coyote.Request.action(Request.java:349)
... |
Ce qui est très étrange également, comme je viens de le dire, c'est que cet appel web-service va généralement échouer, mais il arrive dans certains cas que tout se passe bien ! J'ai du mal à bien comprendre pourquoi des fois ça passe, des fois non. Visiblement, quand l'utilisateur met moins d'une minute après son login pour exécuter l'appel web-service, alors il va s'exécuter correctement (!)
Le web-service que j'utilise dispose d'un attachement. Il s'agit d'un fichier PDF qui n'est généralement pas très volumineux (environ 10Ko).
En testant mon web-service sans attacher de fichier PDF, je ne réussis pas à reproduire l'erreur précédente, et cela fonctionne !
De même, si je désactive les contraintes de sécurité (donc que je me passe du 2-ways SSL), là aussi, je n'ai pas de soucis...
Donc j'imagine que quelque chose doit encore être configuré, au niveau du WS, du Tomcat ou ailleurs. Mais quoi ??
Code Java
Voici l'interface Java qui fournit la méthode d'appel, côté ws-client (comme on peut le voir, ce sont des classes générées par JAX-WS.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| /**
* This class was generated by the JAX-WS RI.
* JAX-WS RI 2.1.3-b02-
* Generated source version: 2.1
*
*/
@WebService(name = "PushServicePortType", targetNamespace = "http://my.app.ws/PushService")
@XmlSeeAlso({
ObjectFactory.class
})
public interface PushServicePortType {
@WebMethod
@WebResult(name = "response", targetNamespace = "")
@RequestWrapper(localName = "createOrRenewRequest", targetNamespace = "http://my.app.ws/PushService", className = "my.app.CreateOrRenewRequest")
@ResponseWrapper(localName = "createOrRenewRequestResponse", targetNamespace = "http://my.app.ws/PushService", className = "my.app.CreateOrRenewRequestResponse")
public String createOrRenewRequest(
@WebParam(name = "xmlMessageContent", targetNamespace = "")
String xmlMessageContent,
@WebParam(name = "version", targetNamespace = "")
String version,
@WebParam(name = "attachments", targetNamespace = "")
List<DataHandler> attachments);
} |
L'appel se réalise de cette façon (xmlFile contient le XML de la requête, datahandler est du type javax.activation.DataHandler qui contient le fichier PDF).
1 2 3
| PushServicePortType pushServicePort = new PushService(new URL("url/to/wsdl"), new QName("http://my.app.ws/PushService", "PushService")).getPushServiceSOAP(new MTOMFeature());
PushRequest push = new PushRequest();
responseXML = push.sendXMLRequest(pushServicePort, xmlFile, datahandler); |
Il y a beaucoup de configuration, de logs ou de classes Java, donc n'hésitez pas à demander plus d'infos...
ps : J'ai essayé de forcer l'intégration du fichier PDF au sein du message SOAP directement, en définissant le seuil (threshold du MTOM) à 2 Mo (voir ici) :
Côté ws-client:
PushServicePortType pushServicePort = new PushService(new URL("url/to/wsdl"), new QName("http://my.app.ws/PushService", "PushService")).getPushServiceSOAP(new MTOMFeature(2097152));
Côté ws-provider, j'ai défini l'annotation MTOM avec @MTOM(threshold=2097152)
Cette modification n'a malheureusement rien résolu...
Partager