jax-rshttp-status-code-406media-typehttp-accept-header

NotAcceptableException (HTTP 406 Not Acceptable) but no apparent error from MessageBodyWriter


In a webapp implemented as a Jetty container, we have a custom javax.ws.rs.ext.MessageBodyWriter<T> annotated with

@Singleton
@Provider
@Produces( "application/rss+xml" )

We also have a resource which works just fine. The get() method is annotated with

@Produces( "application/vnd.api+json" )

Visiting that endpoint returns the expected json response.

Adding .rss to the endpoint causes a 406 response to be returned.

What could be the reason it is not finding the MessageBodyWriter for returning the RSS response?

The full stacktrace is:

javax.ws.rs.NotAcceptableException: HTTP 406 Not Acceptable
    at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter.getMethodRouter(MethodSelectingRouter.java:472)
    at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter.access$000(MethodSelectingRouter.java:73)
    at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter$4.apply(MethodSelectingRouter.java:674)
    at org.glassfish.jersey.server.internal.routing.MethodSelectingRouter.apply(MethodSelectingRouter.java:305)
    at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:86)
    at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:89)
    at org.glassfish.jersey.server.internal.routing.RoutingStage._apply(RoutingStage.java:89)
    at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:69)
    at org.glassfish.jersey.server.internal.routing.RoutingStage.apply(RoutingStage.java:38)
    at org.glassfish.jersey.process.internal.Stages.process(Stages.java:173)
    at org.glassfish.jersey.server.ServerRuntime$1.run(ServerRuntime.java:247)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:248)
    at org.glassfish.jersey.internal.Errors$1.call(Errors.java:244)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:292)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:274)
    at org.glassfish.jersey.internal.Errors.process(Errors.java:244)
    at org.glassfish.jersey.process.internal.RequestScope.runInScope(RequestScope.java:265)
    at org.glassfish.jersey.server.ServerRuntime.process(ServerRuntime.java:234)
    at org.glassfish.jersey.server.ApplicationHandler.handle(ApplicationHandler.java:684)
    at <our package>.Jetty94HttpContainer.handle(Jetty94HttpContainer.java:167) // Jetty94HttpContainer extends AbstractHandler implements Container
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at com.codahale.metrics.jetty9.InstrumentedHandler.handle(InstrumentedHandler.java:284)
    at org.eclipse.jetty.server.handler.HandlerWrapper.handle(HandlerWrapper.java:127)
    at org.eclipse.jetty.server.Server.handle(Server.java:516)
    at org.eclipse.jetty.server.HttpChannel.lambda$handle$1(HttpChannel.java:487)
    at org.eclipse.jetty.server.HttpChannel.dispatch(HttpChannel.java:732)
    at org.eclipse.jetty.server.HttpChannel.handle(HttpChannel.java:479)
    at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:277)
    at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:311)
    at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:105)
    at org.eclipse.jetty.io.ChannelEndPoint$1.run(ChannelEndPoint.java:104)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.runTask(EatWhatYouKill.java:338)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.doProduce(EatWhatYouKill.java:315)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.tryProduce(EatWhatYouKill.java:173)
    at org.eclipse.jetty.util.thread.strategy.EatWhatYouKill.run(EatWhatYouKill.java:131)
    at org.eclipse.jetty.util.thread.ReservedThreadExecutor$ReservedThread.run(ReservedThreadExecutor.java:409)
    at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:883)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$Runner.run(QueuedThreadPool.java:1034)
    at java.base/java.lang.Thread.run(Thread.java:829)

Solution

  • The resource methods annotated with a request method should declare the supported request media types equals to the entity providers that supply mapping services between representations and their associated Java types.

    Adding:

    @Produces( "application/vnd.api+json", "application/rss+xml" )
    

    to the get() method should do the trick.