Skip to main content

Need authoritative answer on whether JAX-WS client objects are thread-safe

18 replies [Last post]
kzho
Offline
Joined: 2008-04-17

We need to know whether the service objects generated by wsimport (JAX-WS RI 2.0.1 and later versions), as well as the port objects returned by the getPort() methods of those service objects are thread-safe.

The spec appears to be ambiguous on this and forum posts for other JAX-WS implementations appear to indicate that these objects are not thread-safe for some implementations (e.g. Axis 2, CXF).

In our performance tests with JAX-WS RI 2.0.1 and 2.1.3, the overhead of the Service.getPort() method is very heavy with average response times of 400-1000 ms.

In order to achieve acceptable performance, we would need to cache and share port objects across threads. In order to do this, we need to know whether these objects are thread-safe. If we cannot do this, we may be forced to look at using an alternative web service stack.

The documentation for wsimport does not indicate whether these objects are thread-safe.

We were able to find two older forum posts where two posters indicate that service and port objects are thread-safe, however it is unclear whether these posters are actual developers on the JAX-WS RI codebase, whether they simply verified that a particular set of classes for a particular version were thread-safe, or whether this is being enforced from a project design perspective for past, present, and future versions of the JAX-WS RI implementation.

http://forum.java.sun.com/thread.jspa?threadID=705659&messageID=4089586
http://forums.java.net/jive/thread.jspa?threadID=18756

Relying on these few forum posts doesn't give us a good level of comfort in making the broad architectural decision to cache port objects for multi-threaded use and applying this to a mission-critical production application.

Can the JAX-WS RI documentation be updated to clearly indicate whether the user should expect wsimport-generated service and port objects to be thread-safe, and provide some basic guidelines on multi-threaded usage?

Without this, it is very difficult for developers to make informed architectural decisions that can impact the performance as well as the integrity of applications using JAX-WS RI.

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
fthurber
Offline
Joined: 2010-04-16

I ran into a similar problem using Java 1.6 JAX-WS when doing some prototyping.

I "solved" the problem by adding the Metro 2.0 webservices-rt.jar to my classpath. Presumably this overrides the default metro in Java 1.6 (1.1 I think).

Interestingly enough, I was naively using a thread pool and Future variables to do the threading. After the fact, I discovered the handy WSFuture and the WS AsyncHandler. When I get a chance I will re-tool my prototype code to use WSFuture and see if this solves the thread safety problem without using the Metro trick.

BTW, I used ThreadLocal for handling the thread issues with getPort. Not yet sure if this is the best approach but it seemed to work.

m_jenkins
Offline
Joined: 2009-09-25

Hi,

We are hitting exactly the same problem (I think).

com.gui.ws.TariffService service = new com.gui.ws.TariffService();
com.gui.ws.Tariff port = service.getTariffPort();

...the call to getTariffPort() takes 2 - 4 seconds.

We have tried defining the web service as a file (which means that the wsdl file must be available at runtime) and leaving it defined as a reference to the remote service (in which case we see a ?wsdl request head over to the remote service).

We are using Glassfish 2.1.

I want to prototype holding a cache of the services, as suggested here; has anybody got any more experiences that may help?

Thanks very much,

Martin

chris2
Offline
Joined: 2009-01-27

I have the same problem and would also like to know the answer to this question.
Due to performace reasons I would like to create a service object once in a constructor of a class and use it later by each call to "service.getPort()".

chris2
Offline
Joined: 2009-01-27
guinyardlives
Offline
Joined: 2009-05-22

BUMP!

I still haven't found any authoritative answer for this, and I find it quite disturbing that there's no standard pattern to follow for consuming web services in a multi-threaded environment.

gmolik
Offline
Joined: 2008-05-08

UPDATE:

I added the following jars to my classpath. All threading issues have disappeared and the client is running about 40% faster.

xml-resolver-1.2, wstx-asl-3.2.4, jaxb-impl-2.1.6, wsdl4j-1.6.1, XmlSchema-1.4.2

huima
Offline
Joined: 2006-05-05

> UPDATE:
>
> I added the following jars to my classpath. All
> threading issues have disappeared and the client is
> running about 40% faster.
>
> xml-resolver-1.2, wstx-asl-3.2.4, jaxb-impl-2.1.6,
> wsdl4j-1.6.1, XmlSchema-1.4.2

Interesting. Where did you get the idea to add those jars and have you any thoughs on what happens in your system because of it.

gmolik
Offline
Joined: 2008-05-08

I narrowed it down even more. It seems to be just an issue with the StAX parser in the JDK. When I use Woodstox StAX (wstx-asl), everything is fine.

I was adding/removing jars my classpath and found that I got different behaviors when I would run the client. So, I just started tinkering.

Adding that jar replaces the default implementation. The jar contains the services configuration for the XMLEventFactory, XMLInputFactory, and XMLOutputFactory to use Woodstox.

kzho
Offline
Joined: 2008-04-17

gmolik, the issue you described is with Apache CXF versus the GlassFish JAX-WS RI, correct?

I expect different behavior with different JAX-WS implementations, since the spec is ambiguous.

We have tested caching service objects (calling getPort() on the cached service object for each request) with GlassFish JAX-WS RI 2.0.1 and have not encountered any issues under load with up to 40 threads.

Still hoping for an official answer or updated documentation from the GlassFish JAX-WS RI team.

gmolik
Offline
Joined: 2008-05-08

Yes, Apache CXF, but the CXF generated classes only have dependencies on JAX-WS within the JDK release. I tested using the CXF generated classes and a custom solution with the same results. I had no luck caching the Service or the interface (getPort()). When I dropped in the Woodstox StAX parser, the problem disappeared. I'm able to cache the interface with no issues.

gmolik
Offline
Joined: 2008-05-08

I'm not on the development team, but I'm fairly certain that they're not thread-safe.

I fired off the client with 36 concurrent threads and no explicit synchronization. When watching the communication, some requests end up empty and some end up looking like this:

ssoS:Body>...
[i]or[/i]
?><><>...

Interestingly, the corruption only seems to occur before the body content. I'd hate to think that there's some shared buffer being used. I've had this occur with just two concurrent threads. Even if I create a new instance of the Service and retrieve the endpoint interface in each thread, the issue still exists. Synchronizing on a shared endpoint interface is the only way I've found to "fix" it.

I'm using Mule/CXF with the CXF generated client. Another option that works is to use the Axis generated client.

acruise
Offline
Joined: 2005-04-22

I've seen this exact symptom with CXF, which we've worked around by making all our stubs single-threaded (ouch!).

Maybe someone can comment whether this fix is related?

kzho
Offline
Joined: 2008-04-17

Can a developer from the JAX-WS RI development team please confirm whether service objects generated by wsimport are thread-safe?

gekis
Offline
Joined: 2008-09-18

Hello.
I'd like to know if the question has been resolved?
Is it the best way to do:

Cash Service service = Service.create(new URL(wsdlLocation), new QName(targetNamspace, servicename));

And with every call make synchronized
service.getPort(new QName(targetNamspace, portName), clazz);

Thaks in advance.

kzho
Offline
Joined: 2008-04-17

Bump

kzho
Offline
Joined: 2008-04-17

Update:

I've run several tests with various combinations of caching service as well as port objects.

It is the initial invocation of getPort() on any given service object instance that incurs the most overhead. So if you do not cache the service object, but create a new one for each request, you will incur this overhead every time you call getPort() on a new service object instance.

If the service object is cached but not the port, subsequent calls to getPort() on the same service object instance are near instantaneous (so it looks like service objects internally cache data for constructing ports of the same type).

So we just need confirmation that the service objects are thread-safe and can be cached and we are good to go.

jamesw
Offline
Joined: 2005-05-19

I asked the same question on this thread http://forums.java.net/jive/thread.jspa?messageID=204991&#204991. My experimental results are identical and looking the access logs you can see creating a service object causes a fetch of the WSDL, presumably to parse it and configure the client. My understanding was that it was OK to cache the service object and to serialize calls to getPort and this is what I'm doing in my code. However this is not an authoritative answer.

kzho
Offline
Joined: 2008-04-17

The thread below suggests that JAX-WS RI port/proxy objects are NOT thread-safe.

An official answer on this from the JAX-WS RI development team would be greatly appreciated.

http://www.jboss.com/index.html?module=bb&op=viewtopic&p=4110102#4110102