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

3

8

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.

Aponeurosis answered 28/4, 2011 at 15:19 Comment(1)
Is the class implementing any interface? In that case it may have something to do with the problem explained in this question: https://mcmap.net/q/560502/-autowire-strange-problemMural
A
5

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;
    }
    ...
}
Aponeurosis answered 28/4, 2011 at 20:37 Comment(0)
B
3

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.

Blimey answered 28/4, 2011 at 15:35 Comment(0)
F
2

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();
Figurant answered 15/7, 2014 at 10:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.