Monday, June 06, 2011

Seemingly common RESTEasy error and a solution

So I was playing with RESTeasy a bit and using the standalone servlet method of exposing REST services was very easy and straightforward.

And then I thought, ok, let me now do the EJB integration on a JBoss AS 4.2.3 - and ran into the following error:

java.lang.RuntimeException: Class is not a root resource.  It, or one of its interfaces must be annotated with @Path: $Proxy862 implements: org.rhq.enterprise.server.rest.ResourceHandlerLocal org.jboss.ejb3.JBossProxy

Which was strange as I did have the @Path annotation present:

@Local
@Produces({"application/json","application/xml","text/plain"})
@Path("/resource")
public interface ResourceHandlerLocal {

Googling around showed, others have/had the same issue; but as so often, no solution was given. After some digging around I found the issue: the error message is a bit misleading, and I was actually missing a @ApplicationPath("/rest") annotation, which defines the "root context" and which is not needed in the simple standalone war case.

So I implemented a subclass of javax.ws.rs.core.Application which is marked with this ApplicationPath annotation and registered it in web.xml:

<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >

<web-app>
<display-name>RHQ Rest interface</display-name>

<context-param>
<param-name>resteasy.jndi.resources</param-name>
<param-value>rhq/ResourceHandlerBean/local</param-value>
<description>List of jndi names of EJBs local interfaces that define REST stuff</description>
</context-param>


<servlet>
<servlet-name>Resteasy</servlet-name>
<servlet-class>
org.jboss.resteasy.plugins.server.servlet.HttpServletDispatcher
</servlet-class>

<init-param>
<param-name>resteasy.scan</param-name>
<param-value>false</param-value>
</init-param> <init-param>
<param-name>javax.ws.rs.Application</param-name>
<param-value>org.rhq.enterprise.server.rest.RHQApplication</param-value>
</init-param>

</servlet>

<servlet-mapping>
<servlet-name>Resteasy</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>
</web-app>

And now the REST provider is starting nicely :)

Of course, if you are using JBoss AS 6 or the upcoming AS7, you do not need to go through all this, as they have RESTeasy already integrated and ready to go.

1 comment:

Gimby said...

Nice post; misleading error messages are only too common in the Java world unfortunately :/ Decent error reporting should be even more important than proper API design IMO. Design flaws you can work around; getting wrong information is just too costly!

But Servlet spec 2.3? You take backwards compatibility seriously!