Pergunta

Ao desenvolver um aplicativo que consome um webservice externo I geraram as fontes a partir do WSDL-url e depois criado um cliente:

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

Desde a criação desta procuração leva algum tempo eu definir o cliente como um atributo na minha classe de serviço.

Mas estou preocupado que o cliente não é thread-safe e este webservice é muito utilizada na aplicação de threads simultâneos (webapp). Não consigo encontrar qualquer documentação sobre isso.

Como precaução eu comecei a usar um pool de objeto de clientes de sabão em vez de uma responsabilidade partilhada.

Esta é uma precaução desnecessária? Qual é a melhor prática ao escrever clientes Xfire?

Eu suspeito que algum tipo de problema de simultaneidade com xfire desde que eu regularmente, sob carga alta, ficar bloqueado tópicos e, como resultado disto, o aplicativo falha. Aqui está um despejo rosca parcial:

"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)

O despejo segmento contém um monte de tópicos bloqueados que se parecem com isso.

Foi útil?

Solução

Eu acho que você começa um monte de tópicos bloqueados, o cliente está realmente thread-safe como dados objeto não está corrompido :). Mas eu concordo que não é lidar com a concorrência em um bom caminho.

1) Uma observação é que o bloqueio final parece estar em execução JAXB e não no XFire. E se você tentar usar a implementação JAXB diferente, como JaxMe ?

2) Além disso, o método getJAXBContext em JaxbType é sincronizado. E o mais provável, porque seus segmentos estão acessando a mesma instância JaxbType eles podem ser bloqueados.

Olhando para esse método eu realmente mudou a sincronização para o método depois presense contexto está marcada:

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

Isto irá permitir a clientes que já têm JAXBContext inicializado para pular a sincronização caro.

A minha sugestão é ou tentar resolver o código de si mesmo e fazer um teste ou submeter um erro ao XFire ou fazer as duas coisas:.)

Outras dicas

Depende da versão do Xfire você está usando, como eles fixaram algumas questões de segurança Rosca na versão 1.2.5. Você pode verificar o bug levantada em http://jira.codehaus.org/browse/XFIRE-886 , e veja mais detalhes sobre as notas de lançamento em hxxp: //xfire.codehaus.org/XFire+1.2.5+Release+Notes

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top