Bug Report:

Spring Boot Version: 3.2.5

When using Spring Jersey with Spring Boot (spring.jersey.type is set to filter), and in JerseyConfig we have:

@Configuration
public class JerseyConfig extends ResourceConfig {
    public JerseyConfig() {
        packages("my.service.package");
        property(ServerProperties.RESPONSE_SET_STATUS_OVER_SEND_ERROR, true);
        property(ServletProperties.FILTER_FORWARD_ON_404, true);
    }
}

We have found if we have a controller that legitimately returns Response.status(404).build() or Response.status(404).entity(null).build (I presume these are equivalent anyway) a 404 response is not returned to the client, but instead a 500 with No static resource /my/endpoint found

It seems like Spring Jersey thinks a 404 without any entity indicates the controller itself was not found, rather than us legitimately returning a 404 because the underlying domain resource (such as a Customer or a Account or any kind of domain object) was found.

We can work around this by providing some blank object as an entity, but this behaviour seems odd as a default. Surely we shouldn't have to provide a response body if we just want the client's status code to be 404.

However, this is not the end of the issue. Even more strangely, if the controller takes a long period of time to respond (we tested this by adding a Thread.sleep(1000L)), it does correctly return the 404 to the client even if the entity is null. ie:

Bodies of controller methods that work correctly, returning a 404 to client:

1) return Response.status(404).entity(someObject).build(); 2) Thread.sleep(1000L); return Response.status(404).build(); 2) Thread.sleep(1000L); return Response.status(404).entity(null).build();

Bodies of controller methods that do not work incorrectly, and return a 500 with No static resource /my/endpoint found to client: 1) return Response.status(404).build(); 2) return Response.status(404).entity(null).build();

Comment From: wilkinsona

Thanks for the report, but Spring Boot can't do much about this as the behavior of Jersey's filter when the response is a 404 is out of our control. When forwardOn404 is enabled, Jersey's filter will forward the request for further handling unless it has been committed or, as you've described, it has an entity.

Perhaps there's a way using the JAX-RS API or Jersey's API to commit the response? If that's not possible, the request is going to reach Spring MVC as that's what you've configured Jersey to do. You could update your Spring MVC exception handling so that the NoResourceFoundException that's thrown by ResourceHttpRequestHandler is mapped to a 404. It appears that it's being mapped to a 500 at the moment.

Comment From: jamfor352

Thanks for the report, but Spring Boot can't do much about this as the behavior of Jersey's filter when the response is a 404 is out of our control. When forwardOn404 is enabled, Jersey's filter will forward the request for further handling unless it has been committed or, as you've described, it has an entity.

Perhaps there's a way using the JAX-RS API or Jersey's API to commit the response? If that's not possible, the request is going to reach Spring MVC as that's what you've configured Jersey to do. You could update your Spring MVC exception handling so that the NoResourceFoundException that's thrown by ResourceHttpRequestHandler is mapped to a 404. It appears that it's being mapped to a 500 at the moment.

Thanks. So this is a bug I should be raising with Jersey?

Looks like this comment does explain the issue:

// We could add an optional flag to disable this step if anyone can ever find a case where
                // this causes a problem, though I suspect any problems will really be with downstream
                // servlets not correctly setting an error status if they cannot find something to return

That said, I'm not sure why I'm getting 500 No static resource. Is this another Spring filter? If so, could I disable it and always return a 404 somehow, from Spring's end?

Jersey's code also doesn't explain the timing issue.

Comment From: wilkinsona

So this is a bug I should be raising with Jersey?

I'm not sure that they'd consider it to be a bug, but you could ask, particularly if there's no easy way to stop Jersey from performing the forward when you really want a 404 to be returned.

That said, I'm not sure why I'm getting 500 No static resource

I believe that's due to the ResourceHttpRequestHandler that will be thrown by Spring MVC's static resource support. You should handle the exception in a Spring MVC exception handler and map it to a 404. Alternatively, if you not using Spring MVC alongside Jersey, you could configure Jersey as a servlet and avoid this situation entirely.

Jersey's code also doesn't explain the timing issue.

Indeed, but it will all happen in Jersey before the request reaches Spring MVC so it's out of our control.

If you have any further questions, please follow up on Stack Overflow. As mentioned in the guidelines for contributing, we prefer to use GitHub issues only for bugs and enhancements.