Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use @Resource WebServiceContext injection with Spring's @Transactional

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.

like image 500
adrianboimvaser Avatar asked Apr 28 '11 15:04

adrianboimvaser


3 Answers

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;
    }
    ...
}
like image 85
adrianboimvaser Avatar answered Nov 05 '22 05:11

adrianboimvaser


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.

like image 3
Augusto Avatar answered Nov 05 '22 05:11

Augusto


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();
like image 2
ian visser Avatar answered Nov 05 '22 04:11

ian visser