I've tried deploying my app to both Tomcat 6 with Metro/Jersey and Glassfish 3.1.2, but accessing the WebServiceContext resource always causes a null pointer exception, except when I test the app using the autogenerated Glassfish testing portal.
Here is a simple test method I wrote to verify this:
import javax.annotation.Resource;
import javax.jws.WebService;
import javax.xml.ws.WebServiceContext;
import javax.xml.ws.handler.MessageContext;
import javax.servlet.ServletContext;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
@WebService
@Path("/test")
public class Test {
@Resource
WebServiceContext wsContext;
@GET
@Produces("text/plain")
@Path("/hello")
public String hello() {
MessageContext mc = wsContext.getMessageContext(); // NULL POINT HAPPENS HERE!
ServletContext servletContext = (ServletContext)
mc.get(
MessageContext.SERVLET_CONTEXT);
String s = servletContext.getRealPath("/WEB-INF");
return "Real Path: " + s;
}
}
and here is the corresponding web-xml (largely auto-generated by Eclipse):
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
<display-name>WebApp</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
<welcome-file>index.htm</welcome-file>
<welcome-file>index.jsp</welcome-file>
<welcome-file>default.html</welcome-file>
<welcome-file>default.htm</welcome-file>
<welcome-file>default.jsp</welcome-file>
</welcome-file-list>
<servlet>
<description>JAX-RS Tools Generated - Do not modify</description>
<servlet-name>JAX-RS Servlet</servlet-name>
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>JAX-RS Servlet</servlet-name>
<url-pattern>/jaxrs/*</url-pattern>
</servlet-mapping>
</web-app>
What's most interesting is that when I test the TestService by going to the Glassfish generated URL:
http://localhost:8080/WebApp/TestService?Tester
I can test/invoke the "hello" method by submitting the form and get a valid WebServiceContext object that generates the appropriate filepath. Unfortunately, actually performing an HTTP GET Request like
$curl -H "Accept: text/plain" http://localhost:8080/WebApp/jaxrs/test/hello
results in a null pointer stack trace that points to line 22 (the WebServiceContext) in the Test class.
Why does the web service work in the Glassfish test harness, but not from actual HTTP requests?
UPDATE:
I was able to confirm that the Web Service works perfectly (WebServiceContext is properly injected) if you utilize the GlassFish default XML SOAP request to the GlassFish default URL like this:
$curl -X POST -d @req.xml http://localhost:8080/ZlotyGlassfish/TestService --header "Content-Type:text/xml"
where the contents of the file "req.xml" are a request matching the WSDL definition:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:impl="http://impl.rest.webservice.webapp.com/">
<soapenv:Header/>
<soapenv:Body>
<impl:hello/>
</soapenv:Body>
</soapenv:Envelope>
My primary question remains why does this work perfectly through the default GlassFish implementation, but the Endpoints generated by the @GET and @Path notations fail to get injected with the the appropriate WebServiceContext object?
The difference is that the default GlassFish implementation is a JAX-WS SOAP-based web service. For a JAX-RS web service, you should use the following annotation to inject the context.
There are other types that you can use @Context annotation to inject, such as
UriInfo
,HttpHeaders
. Please see Jersey documentation for details.WebServiceContext
andMessageContext
are JAX-WS objects that have no meaning in the JAX-RS context.