Ramazan Ramazan - 2 months ago 14
reST (reStructuredText) Question

Grizzly REST - POSTs are always 404

In my endpoint, I have some methods with

@GET
and some methods with
@POST
.
@GET
s are working fine, but
@POST
s 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.

Answer

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 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.

Comments