I hava a Metro jax-ws webservice that looks more or less like this:
@WebService
@Transactional
public class UserManagementServiceImpl {
@Resource
private WebServiceContext context;
...
}
The WebServiceContext
is allways null. However, if I remove @Transactional
the WebServiceContext is injected.
Anybody knows a workaround?
Thanks.
I've found a workaround. Use setter injection instead of field injection:
@WebService
@Transactional
public class UserManagementServiceImpl {
private WebServiceContext context;
@Resource
public void setContext(WebServiceContext context) {
this.context = context;
}
...
}
The problem with webservices and the transaction management is that each creates a proxy of the class, and the 2nd one to create a proxy doesn't get the real implementation but the proxy (and things go south).
The way to avoid this is to delegate all the calls from the webservice endpoint implementation to the service. So you'll need two concrete classes :S.
I don't know if this is the best way to do it, but it's the best I've found.
And it might clean up the code a bit, as it looks like the User Manager cares about webservices, which doesn't look right.
I suspect this may cause problems when handling simultaneous calls to the web service since the Servlet is a singleton, all instance data is "shared" by all threads - so your "private context" will keep being overridden by the next call even while you are still busy with a previous call. Maybe something like
ThreadLocal<WebServiceContext> WSS = new ThreadLocal<WebServiceContext>();
@Resource
public void setContext(WebServiceContext context) {
WSS.set(context);
}
// then where you need the context use WSS.get();