Ramazan
Ramazan

Reputation: 999

Grizzly REST - POSTs are always 404

In my endpoint, I have some methods with @GET and some methods with @POST. @GETs are working fine, but @POSTs always return 404.

Here is some part from the endpoint's interface:

public interface TestEndpoint {

    @GET
    @Path("/ping")
    Response ping();

    @POST
    @Path("/weather/{iata}/{pointType}")
    Response updateWeather(@PathParam("iata") String iataCode,
                           @PathParam("pointType") String pointType,
                           String datapointJson);

    @POST
    @Path("/airport/{iata}/{lat}/{long}")
    Response addAirport(@PathParam("iata") String iata,
                        @PathParam("lat") String latString,
                        @PathParam("long") String longString);

    @GET
    @Path("/exit")
    Response exit();
}

Here is the server initialization part:

public class TestServer {

    private static final String BASE_URL = "http://localhost:9090/";

    public static void main(String[] args) {
        try {
            final ResourceConfig resourceConfig = new ResourceConfig();
            resourceConfig.register(TestEndpointImpl.class);

            HttpServer server = GrizzlyHttpServerFactory.createHttpServer(URI.create(BASE_URL), resourceConfig, false);
            Runtime.getRuntime().addShutdownHook(new Thread(() -> {
                server.shutdownNow();
            }));

            HttpServerProbe probe = new HttpServerProbe.Adapter() {
                public void onRequestReceiveEvent(HttpServerFilter filter, Connection connection, Request request) {
                    System.out.println(request.getRequestURI());
                }
            };
            server.getServerConfiguration().getMonitoringConfig().getWebServerConfig().addProbes(probe);

            server.start();
            Thread.currentThread().join();
            server.shutdown();
        } catch (IOException | InterruptedException ex) {
            Logger.getLogger(TestServer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
}

where, TestEndpointImpl is an implementation of TestEndpoint (as the name implies) with class-level annotation @Path("/collect").

When I perform GET requests, it works fine. But POSTs are problematic. Corresponding methods are not called.

As a side note, probe prints both GET and POST requests as expected, so I am sure that requests reach the server and paths are ok.

Is there any suggestion?

EDIT: Some snippet from the implementation:

@Path("/collect")
public class TestEndpointImpl implements TestEndpoint {

    ...

    @Override
    public Response updateWeather(@PathParam("iata") String iataCode, @PathParam("pointType") String pointType,
            String datapointJson) {
        System.out.println("TRACE: " + datapointJson);
        // do something and return a Response
    }

    ...

}

The registered probe prints /collect/weather/BOS/wind, but updateWeather is not called.

Upvotes: 2

Views: 1046

Answers (2)

cassiomolin
cassiomolin

Reputation: 131167

Short answer

Copy the @POST and the @Path annotations to the method implementation. It will do the trick.

Long answer

The section regarding annotation inheritance of the JAX-RS 2.0 specification (the specification which Jersey is the reference implementation) is pretty clear. See the quote below:

3.6 Annotation Inheritance

JAX-RS annotations may be used on the methods and method parameters of a super-class or an implemented interface. Such annotations are inherited by a corresponding sub-class or implementation class method provided that the method and its parameters do not have any JAX-RS annotations of their own. Annotations on a super-class take precedence over those on an implemented interface. The precedence over conflicting annotations defined in multiple implemented interfaces is implementation specific. Note that inheritance of class or interface annotations is not supported.

If a subclass or implementation method has any JAX-RS annotations then all of the annotations on the superclass or interface method are ignored. E.g.:

public interface ReadOnlyAtomFeed {

    @GET 
    @Produces("application/atom+xml")
    Feed getFeed();
}
@Path("feed")
public class ActivityLog implements ReadOnlyAtomFeed {

    public Feed getFeed() {...}
}

In the above, ActivityLog.getFeed inherits the @GET and @Produces annotations from the interface. Conversely:

@Path("feed")
public class ActivityLog implements ReadOnlyAtomFeed {

    @Produces("application/atom+xml")
    public Feed getFeed() {...}
}

In the above, the @GET annotation on ReadOnlyAtomFeed.getFeed is not inherited by ActivityLog.getFeed and it would require its own request method designator since it redefines the @Produces annotation.

For consistency with other Java EE specifications, it is recommended to always repeat annotations instead of relying on annotation inheritance.

Upvotes: 2

Riccardo Cossu
Riccardo Cossu

Reputation: 2739

That can also happen if the url is not in the correct format; for example you could have sent a request without the correct path parameters.

Upvotes: 0

Related Questions