views:

6164

answers:

4

I'm using Java 6, Tomcat 6, and Metro. I use WebService and WebMethod annotations to expose my web service. I would like to obtain information about the request. I tried the following code, but wsCtxt is always null. What step must I take to not get null for the WebServiceContext.

In other words: how can I execute the following line to get a non-null value for wsCtxt?

MessageContext msgCtxt = wsCtxt.getMessageContext();

@WebService
public class MyService{

  @Resource
  WebServiceContext wsCtxt;

  @WebMethod
  public void myWebMethod(){
    MessageContext msgCtxt = wsCtxt.getMessageContext();
    HttpServletRequest req = (HttpServletRequest)msgCtxt.get(MessageContext.SERVLET_REQUEST);
    String clientIP = req.getRemoteAddr();
  }
A: 

Maybe the javax.ws.rs.core.Context annotation is for what you are looking for, instead of Resource?

asterite
+4  A: 

I recommend you either rename your variable from wsCtxt to wsContext or assign the name attribute to the @Resource annotation. The J2ee tutorial on @Resource indicates that the name of the variable is used as part of the lookup. I've encountered this same problem using resource injection in Glassfish injecting a different type of resource.

Though your correct name may not be wsContext. I'm following this java tip. If you like the variable name wsCtxt, then use the name attribute in the variable declaration:

@Resource(name="wsContext") WebServiceContext wsCtxt;

James A Wilson
A: 

I still have this problem. Here is my work-around was to write a ServletRequestListener that puts the request into a ThreadLocal var. Then the WebService can obtain the request from the ThreadLocal. In other words, I'm reimplementing something that just doesn't work for me.

Here's the Listener:

import javax.servlet.ServletRequest;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;

public class SDMXRequestListener implements ServletRequestListener {

    public SDMXRequestListener() {
    }

    public void requestDestroyed(ServletRequestEvent event) {
    }

    public void requestInitialized(ServletRequestEvent event) {
        final ServletRequest request = event.getServletRequest();
        ServletRequestStore.setServletRequest(request);
    }

}

Here's the ThreadLocal wrapper:

import javax.servlet.ServletRequest;

public class ServletRequestStore {

    private final static ThreadLocal<ServletRequest> servletRequests = new ThreadLocal<ServletRequest>();

    public static void setServletRequest(ServletRequest request) {
        servletRequests.set(request);
    }

    public static ServletRequest getServletRequest() {
        return servletRequests.get();
    }

}

And the web.xml wiring:

  <listener>
        <listener-class>ecb.sdw.webservices.SDMXRequestListener</listener-class>
    </listener>

The Web service uses the following code to obtain the request:

final HttpServletRequest request = (HttpServletRequest) ServletRequestStore.getServletRequest();

Steve McLeod
+1  A: 

The following code works for me using Java 5, Tomcat 6 and Metro

Could it possibly be that there is a conflict between the WS support in Java 6 and the version of Metro you are using. Have you tried it on a Java 5 build?

@WebService
public class Sample {
    @WebMethod
    public void sample() {
        HttpSession session = findSession();
        //Stuff

    }
    private HttpSession findSession() {
        MessageContext mc = wsContext.getMessageContext();
        HttpServletRequest request = (HttpServletRequest)mc.get(MessageContext.SERVLET_REQUEST);
        return request.getSession();
    }
    @Resource
    private WebServiceContext wsContext;
}
Garth Gilmour