Search code examples
jerseyjax-rs

JAX-RS Resource Not Automatically Collected Despite @Path Annotation


I'm encountering an issue with my JAX-RS application where a resource class annotated with @Path is not automatically collected by the server, resulting in a 404 error when attempting to access the endpoint.

Project Structure:

com.example
│   Main.java
│
└───hello
        Hello.java

Main.java:

package com.example;

import org.glassfish.grizzly.http.server.HttpServer;
import org.glassfish.jersey.grizzly2.httpserver.GrizzlyHttpServerFactory;

import java.io.IOException;
import java.net.URI;

public class Main {
    public static final String BASE_URI = "http://localhost:8080/";

    public static HttpServer startServer() {
        return GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URI));
    }

    public static void main(String[] args) throws IOException {
        final HttpServer server = startServer();
        System.out.println(String.format("Jersey app started with endpoints available at %s%nHit Ctrl-C to stop it...", BASE_URI));
        System.in.read();
        server.stop();
    }
}

Hello.java:

package com.example.hello;

import javax.ws.rs.GET;
import javax.ws.rs.Path;

@Path("hello")
public class Hello {

    @GET
    public String sayHello() {
        return "Hello World";
    }
}

Whenever I explicitly register the package using ResourceConfig constructor like this:

final ResourceConfig rc = new ResourceConfig().packages("com.example.hello");

it works, but otherwise, it doesn't.

I've read this Stack Overflow answer which suggests that using the default application class without registering anything should automatically include all resources, but that doesn't seem to be happening in my case.

What could be causing this issue? How can I ensure that my resource class is properly collected and accessible through the defined URI path without explicit registration?


Solution

  • The answer says you need to use @ApplicationPath annotation on an Application subclass (ResourceConfig).

    This "autodiscovery" mechanism is implemented by using Servlet 3 capabilities. It is implemented by org.glassfish.jersey.containers:jersey-container-servlet module which delegates to Servlet 3 container.

    However, Grizzly is not a servlet container, Grizzly is an NIO server with a few servlet functions. The autodiscovery mechanism would work fine in an application server such as Payara, Glassfish, or WebLogic. It also should work fine with Servlet containers such as Tomcat or Jetty. You can also use Helidon MP, which implements the autodiscovery mechanism on its own. In Helidon, you would not need the Application subclass at all.