20
votes

Although this is one ancient question, I still can not find the answer to make this work. Please correct if you find any of my statement is not correct.

I have a Java Face app and use REST for the Web Services. I don't think Face has anything to do with my problem at all. The web.xml is:

<servlet>
    <servlet-name>NDREST</servlet-name>
    <servlet-class>
        com.sun.jersey.spi.container.servlet.ServletContainer
    </servlet-class>
    <init-param>
        <param-name>com.sun.jersey.config.property.packages</param-name>
        <param-value>com.bi.nd.webservice</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>NDREST</servlet-name>
    <url-pattern>/nd/*</url-pattern>
</servlet-mapping>

I have quite a few more servlets in the web.xml since is is a Face app with Trinidad, etc.

In the package com.bi.nd.webservice, my resource class is:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

@Produces(MediaType.APPLICATION_XML)
@Path("/hello")
public class TransactionResource 
{
public TransactionResource() 
{
}

@GET
@Produces(MediaType.TEXT_PLAIN)
public String itWorks()
{
    return "Get is OK";
}
}

The fact that my class has a @GET is enough to identify itself a resource class.
Let alone all other complexities, I compiled my source code with Ant in Eclipse and I got this error in the catalina.out file:

May 24, 2011 8:48:46 AM com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
     com.bi.nd.webservice
May 24, 2011 8:48:46 AM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.7 05/20/2011 11:04 AM'
May 24, 2011 8:48:46 AM com.sun.jersey.server.impl.application.RootResourceUriRules <init>
SEVERE: The ResourceConfig instance does not contain any root resource classes.

Some suggested that copy the asm.jar, jsr-api.jar, jersey-server.jar and jersey-core.jar into the app WEB-INF/lib. I did that and it still did not work. I found the suggestion was a bit odd since WEB-INF/lib is a place where Eclipse will install all dependency libraries from the build path. It is not a place where we manually put libraries.

Some explained that this error had something to do with Java plug-in and the way Jersey was written. But that was years ago.

Can some one explains to me why I keep having this problem?

Followup: Although from REST web site, resource class defined as Root resource classes are POJOs (Plain Old Java Objects) that are either annotated with@Path or have at least one method annotated with @Path or a request method designator such as @GET, @PUT, @POST, or @DELETE. Resource methods are methods of a resource class annotated with a request method designator. This section describes how to use Jersey to annotate Java objects to create RESTful web services.

I have to add @Path("/hello") to my class, and suddenly Jersey can find my resource class

Now the catalina.out file looks like:

May 24, 2011 3:13:02 PM com.sun.jersey.api.core.PackagesResourceConfig init
INFO: Scanning for root resource and provider classes in the packages:
com.bi.nd.webservice
May 24, 2011 3:13:02 PM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
class com.bi.nd.webservice.TransactionResource
May 24, 2011 3:13:02 PM com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.
May 24, 2011 3:13:02 PM com.sun.jersey.server.impl.application.WebApplicationImpl _initiate
INFO: Initiating Jersey application, version 'Jersey: 1.7 05/20/2011 11:04 AM'

But the problem is far from over. I try to access the URL http://localhost:8080/nd/hello and I still get the 404 NOT FOUND. Is the Provider class NOT FOUND an important message?

9
Can you share what problem you fixed? I am having the same issue! I keep getting a 404 even though I have been over everything with a fine tooth combCollin Peters
@user759646 facing the same problem, i am running it in weblogicDeveloperick

9 Answers

11
votes

I had the same error message and solved it by modifying my web.xml file. Make sure it has this in it:

<init-param>
   <param-name>com.sun.jersey.config.property.packages</param-name>
   <param-value>your.package.name.here</param-value>
</init-param>
7
votes

I found another reason Jersey could fail to find a root resource. The error message is the same, so I thought it'd be a good reason to document the root cause here in case other people stumble on it.

I have a root resource class that has the following annotations on it:

@Singleton
@Path("/helloWorld")
@Service(...) // my own custom annotation
public class MyRootResource {
...
}

This will cause the root resource scanning within Jersey to fail.

The fix is to change the order of the annotations:

@Service(...) // my own custom annotation
@Singleton
@Path("/helloWorld")
public class MyRootResource {
...
}

This works.

5
votes

Firstly, note that having @GET on a class is not enough to identify it as a root resource class; the class must have an @Path on it. Yours does, so that's not the problem.

I was having the same problem as you: it worked in Eclipse, but then didn't work when I built it for external use.

I'm using embedded Jetty, with a main() that looks like this:

public static void main(String argv[])
{
    try
    {
        // from http://wiki.eclipse.org/Jetty/Tutorial/Embedding_Jetty
        Server server = new Server(8080);
        ServletContextHandler contextHandler = new ServletContextHandler(ServletContextHandler.SESSIONS);
        contextHandler.setContextPath("/");
        server.setHandler(contextHandler);

        // http://stackoverflow.com/questions/9670363/how-do-i-programmatically-configure-jersey-to-use-jackson-for-json-deserializa
        final PackagesResourceConfig prc = new PackagesResourceConfig("com.ultimatefoodfight.server.api");
        final Map<String, Object> prcProperties = prc.getProperties();
        prcProperties.put(JSONConfiguration.FEATURE_POJO_MAPPING, true);

        // from http://stackoverflow.com/questions/7421574/embedded-jetty-with-jersey-or-resteasy
        contextHandler.addServlet(new ServletHolder(new ServletContainer(prc)), "/*");

        server.start();
        server.join();
    }
    catch(Exception e)
    {
        System.out.println(e);
    }
}

(When embedding Jetty, this takes the place of a web.xml.) com.sun.jersey.api.core.PackagesResourceConfig scans the named classes for root resource provider classes -- I'm sure the web.xml is just pointing at the same. This worked fine in Eclipse. Server startup correctly reports this in the console:

INFO: Scanning for root resource and provider classes in the packages:
  com.ultimatefoodfight.server.api
Jul 29, 2012 7:31:28 AM com.sun.jersey.api.core.ScanningResourceConfig logClasses
INFO: Root resource classes found:
  class com.ultimatefoodfight.server.api.Users
  class com.ultimatefoodfight.server.api.Contests

However, when I start the application on a server, I only get the first two lines of that, and no Root resource classes are found.

It turns out that when you make a jar, there are different options for how it is constructed; in particular, if you just make it by listing the paths to the classes, you get just those entries. But if you point jar at the directory with a wild card, you also get all the intermediate paths. See this message for the example that tipped me off: https://groups.google.com/d/msg/neo4j/0dNqGXvEbNg/xaNlRiU1cHMJ .

The PackagesResourceConfig class depends on having a directory with the name of the package in order to find the classes within it. I went back to Eclipse, and found an option at the bottom of the "Export ... > Jar" dialog for "Add directory entries." I turned that on, exported the jar again, and then the scanning found my resource classes. You'll need to find some comparable option in your build environment.

3
votes

I've just spent a good 5 or 6 hours wrestling with this too and have finally fixed the problem. This may work for you too perhaps.

The source code I've been using is available at Lars Vogel's tutorial page. Using Apache Tomcat 6.0.20, asm-all-3.3.1.jar, jersey-bundle-1.17.1.jar and jsr311-api-1.1.1.jar I was getting the same results as the OP, i.e.

INFO: Root resource classes found:
  class com.mypackage.MyClass
13/03/2013 4:32:30 PM com.sun.jersey.api.core.ScanningResourceConfig init
INFO: No provider classes found.

I had the following settings across the various deployment files:

context root = rivets
<url-pattern>/rest</url-pattern>
@Path("/hello")

Trying to access the resource using the following URL gave a 404 error

 http://localhost:8080/rivets/rest/hello

I was eventually able to fix it by changing the url-pattern to :

<url-pattern>/rest/*</url-pattern>

Though I'm not sure how this will hold up when I start to introduce more complex resources. Anyway, hopefully this may help someone.

2
votes

I found that the "no provider classes found" message is scary but not important.

"The ResourceConfig instance does not contain any root resource classes" is a much bigger problem.

I found that the resource class needs to be annotated with @Path, and the provider class (if you have one -- we use one for mapping exceptions to HTTP response codes) needs to be annotated with @Provider, and both need to be in the right package, and then Jersey will find them.

1
votes

you might need to use a url like this

http://localhost:8080/<web_context_root>/nd/hello
1
votes

So I read trough the answers and still had the same problem. I resolved it as follows.

Added "jetty-web.xml" to the "WEB-INF" folder. Thus: src/main/webapp/WEB-INF/jetty-web.xml

The content of the jetty-web.xml is:

<?xml version="1.0"  encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-" "http://www.eclipse.org/jetty/configure.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
    <Set name="contextPath">/YourEndpoint</Set>
</Configure>

My rest is now available at:

http://localhost:8080/YourEndpoint/webresources/someMethod

Hope this helps someone out there.

0
votes

I had the same problem. Solved it by fixing in the web.xml the param-value under init-param tag. By default, Eclipse had set in the web.xml the name of the project into display-name. That shall not be copied to the param-value, but the Java package.

  <init-param>
    <param-name>com.sun.jersey.config.property.packages</param-name>
    <param-value>com.test.demo</param-value>
    </init-param> 

Hope this helps.

0
votes

To resolve this problem, please verify your class MapperIn, there is required to specify Path:

import javax.ws.rs.GET;
import javax.ws.rs.OPTIONS;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import com.lot.account.api.doc.GetMemberAccountsIn;
import com.lot.common.doc.CommonApi;
import com.lot.common.doc.FlowData;
import com.lot.security.authorization.RequestData;


@Path("/account/member/")
public class MapperIn {

    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @Path("/{memberId}")
    public GetAccountIn prepareGetAccount(@PathParam("memberId") String memberId) {

        // create apiInput
        GetAccountIn apiInput = new GetAccountIn ();

        // map values from url
            apiInput.setMemberId(memberId);


        return apiInput;
    }
//...
}