2009-08-06 21 views
1

Lors du développement d'une application qui consomme un webservice externe j'ai généré les sources de la wsdl-url puis créé un client:Le thread de proxy client xfire est-il sécurisé?

GeoIPServiceClient service = new GeoIPServiceClient(); 
GeoIPServiceSoap geoIPClient = service.getGeoIPServiceSoap(); 

Depuis la création de cette procuration prend un certain temps, je mis le client comme un attribut dans ma classe de service.

Mais je suis inquiet que le client ne soit pas thread-safe et ce webservice est fortement utilisé dans l'application par des threads concurrents (webapp). Je ne trouve aucune documentation à ce sujet. Par mesure de précaution, j'ai commencé à utiliser un pool d'objets de clients soap au lieu d'un pool partagé.

Est-ce une précaution inutile? Quelle est la meilleure pratique lors de l'écriture des clients xfire?

Je soupçonne une sorte de problème de simultanéité avec xfire puisque je reçois régulièrement, sous forte charge, des threads bloqués et à la suite de cela l'application se bloque. Voici une décharge de filetage partiel:

"http-xx.xx.xx.xx-80-17" daemon prio=10 tid=0x00007f560d437000 nid=0x66cb waiting for monitor entry [0x00000000412b8000] 
    java.lang.Thread.State: BLOCKED (on object monitor) 
    at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Injector.java:174) 
    - waiting to lock <0x00007f561d44e1c0> (a com.sun.xml.bind.v2.runtime.reflect.opt.Injector) 
    at com.sun.xml.bind.v2.runtime.reflect.opt.Injector.inject(Injector.java:85) 
    at com.sun.xml.bind.v2.runtime.reflect.opt.AccessorInjector.prepare(AccessorInjector.java:87) 
    at com.sun.xml.bind.v2.runtime.reflect.opt.OptimizedAccessorFactory.get(OptimizedAccessorFactory.java:165) 
    at com.sun.xml.bind.v2.runtime.reflect.Accessor$FieldReflection.optimize(Accessor.java:253) 
    at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.<init>(TransducedAccessor.java:231) 
    at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor.get(TransducedAccessor.java:173) 
    at com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.<init>(SingleElementLeafProperty.java:83) 
    at sun.reflect.GeneratedConstructorAccessor165.newInstance(Unknown Source) 
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513) 
    at com.sun.xml.bind.v2.runtime.property.PropertyFactory.create(PropertyFactory.java:124) 
    at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.<init>(ClassBeanInfoImpl.java:171) 
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.getOrCreate(JAXBContextImpl.java:481) 
    at com.sun.xml.bind.v2.runtime.JAXBContextImpl.<init>(JAXBContextImpl.java:315) 
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:139) 
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:117) 
    at com.sun.xml.bind.v2.ContextFactory.createContext(ContextFactory.java:188) 
    at sun.reflect.GeneratedMethodAccessor176.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at java.lang.reflect.Method.invoke(Method.java:597) 
    at javax.xml.bind.ContextFinder.newInstance(ContextFinder.java:128) 
    at javax.xml.bind.ContextFinder.find(ContextFinder.java:277) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:372) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:337) 
    at javax.xml.bind.JAXBContext.newInstance(JAXBContext.java:244) 
    at org.codehaus.xfire.jaxb2.JaxbType.getJAXBContext(JaxbType.java:306) 
    - locked <0x00007f565b3aee60> (a org.codehaus.xfire.jaxb2.JaxbType) 
    at org.codehaus.xfire.jaxb2.JaxbType.writeObject(JaxbType.java:230) 
    at org.codehaus.xfire.aegis.AegisBindingProvider.writeParameter(AegisBindingProvider.java:229) 
    at org.codehaus.xfire.service.binding.AbstractBinding.writeParameter(AbstractBinding.java:273) 
    at org.codehaus.xfire.service.binding.WrappedBinding.writeMessage(WrappedBinding.java:90) 
    at org.codehaus.xfire.soap.SoapSerializer.writeMessage(SoapSerializer.java:80) 
    at org.codehaus.xfire.transport.http.HttpChannel.writeWithoutAttachments(HttpChannel.java:56) 
    at org.codehaus.xfire.transport.http.OutMessageRequestEntity.writeRequest(OutMessageRequestEntity.java:51) 
    at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:499) 
    at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:2114) 
    at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:1096) 
    at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:398) 
    at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171) 
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397) 
    at org.codehaus.xfire.transport.http.CommonsHttpMessageSender.send(CommonsHttpMessageSender.java:369) 
    at org.codehaus.xfire.transport.http.HttpChannel.sendViaClient(HttpChannel.java:123) 
    at org.codehaus.xfire.transport.http.HttpChannel.send(HttpChannel.java:48) 
    at org.codehaus.xfire.handler.OutMessageSender.invoke(OutMessageSender.java:26) 
    at org.codehaus.xfire.handler.HandlerPipeline.invoke(HandlerPipeline.java:131) 
    at org.codehaus.xfire.client.Invocation.invoke(Invocation.java:79) 
    at org.codehaus.xfire.client.Invocation.invoke(Invocation.java:114) 
    at org.codehaus.xfire.client.Client.invoke(Client.java:336) 
    at org.codehaus.xfire.client.XFireProxy.handleRequest(XFireProxy.java:77) 
    at org.codehaus.xfire.client.XFireProxy.invoke(XFireProxy.java:57) 
    at $Proxy143.getMyMethod(Unknown Source) 

Le vidage de fil contient un grand nombre de threads bloqués qui ressemblent à ceci.

Répondre

1

Je suppose que vous obtenez beaucoup de bloqué threads, le client est réellement thread-safe que les données de l'objet ne sont pas corrompues :). Mais je suis d'accord qu'il ne gère pas la concurrence dans le bon sens.

1) Une observation est que le verrou final semble être dans l'implémentation de JAXB et non dans XFire. Que faire si vous essayez d'utiliser une implémentation JAXB différente comme JaxMe?

2) La méthode getJAXBContext dans JaxbType est également synchronisée. Et probablement parce que vos threads accèdent à la même instance JaxbType, ils peuvent être bloqués.

En regardant cette méthode que je fait déplacé la synchronisation dans la méthode après contexte presense est vérifié:

if (context == null) { 
    synchronized (this) { 
     ... 

Cela permettra aux clients qui ont déjà JAXBContext initialisés sauter la synchronisation coûteuse.

Ma suggestion est soit essayer de réparer le code vous-même et faire un test ou soumettre un bug à XFire ou faire les deux :).

1

Dépend de la version de Xfire que vous utilisez, car ils ont corrigé quelques problèmes de sécurité des threads dans la version 1.2.5. Vous pouvez vérifier le bug soulevé à http://jira.codehaus.org/browse/XFIRE-886, et voir plus de détails sur les notes de version à hxxp: //xfire.codehaus.org/XFire+1.2.5+Release+Notes