I've noticed the actuator endpoints throwing a 404 error. The following are the Spring Framework versions used:

Spring Boot Starter 3.2.5 Spring Boot Jersey Starter 3.2.5 Tomcat embedded container

The actuator endpoints worked with Spring boot 2.7.* and Jersey was configured as "Filter".

Additional info: (In the working code)

ServletContainer.class throws Status.NOT_FOUND The call reaches the Tomcat Embedded core (ApplicationFilterChain, WSFilter) The call hits the Spring boot actuator

In the not-working code, the flow never reaches the spring boot actuator.

Please share your thoughts.

Comment From: philwebb

Please share a sample project that replicates the issue.

Comment From: RameshVE123

ActuatorIssue.zip

Attached is the demo code.

Comment From: nosan

Thank you for your demo, @RameshVE123

I checked it, and indeed, it does not work. I also downgraded the Spring Boot version to 2.7.18, and it does not work either.

Three things should be changed in your demo code to make it work:

  • In your demo, you have added dependency on org.springframework.boot:spring-boot-starter-web that back-offs JerseyWebEndpointManagementContextConfiguration as DispatcherServlet was registered.
JerseyWebEndpointManagementContextConfiguration:
  Did not match:
     - @ConditionalOnMissingBean (types: org.springframework.web.servlet.DispatcherServlet; SearchStrategy: all) found beans of type 'org.springframework.web.servlet.DispatcherServlet' dispatcherServlet (OnBeanCondition)
  Matched:
     - @ConditionalOnClass found required class 'org.glassfish.jersey.server.ResourceConfig' (OnClassCondition)
     - found 'session' scope (OnWebApplicationCondition)

You need to either comment out this dependency or remove it entirely from your pom.xml


  • A property server.servlet.context.path=/msapi is incorrect and should be changed to server.servlet.context-path=/msapi

  • Since, you set spring.jersey.type=filter, the Jersey ServletContainer will be registered as Filter and filters are invoked on either the request to a resource (a servlet or static content), or on the response from a resource, or both, and in your application, there are no such resources. You can modify your configuration with the following changes:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

    @Bean
    ServletRegistrationBean<NoOpServlet> noOpServlet() {
        return new ServletRegistrationBean<>(new NoOpServlet(), "/*");
    }

    public static class NoOpServlet extends GenericServlet {

        @Override
        public void service(ServletRequest servletRequest, ServletResponse servletResponse) {
            throw new UnsupportedOperationException("Not supported yet.");
        }

    }

}

Once you have made all these changes, the actuator endpoint will be available on:

```http request GET http://localhost:8080/msapi/actuator/health



Could you please provide more information about your application, which uses Jersey as a `Filter`, as the provided demo does not show that it worked in `2.7.x`. 


**Comment From: nosan**

> The actuator endpoints worked with Spring boot 2.7.* and Jersey was configured as "Filter".
> Additional info: (In the working code)
> ServletContainer.class throws Status.NOT_FOUND
> The call reaches the Tomcat Embedded core (ApplicationFilterChain, WSFilter)
> The call hits the Spring boot actuator
> In the not-working code, the flow never reaches the spring boot actuator.

The actuator endpoints are not accessible because the `ServletContainer` (Jersey Filter) is not configured with the actuator resources. This occurs because a `DispatcherServlet` bean was registered, which back-off `JerseyWebEndpointManagementContextConfiguration` and the latter one is responsible for configuring `ServletContainer`. 

You can adjust `JerseyConfiguration` with the following changes: 

```java
@Component
@ApplicationPath("/jersey") //change path from '/' to something else 
public class JerseyConfiguration extends ResourceConfig {

    // Demo code, no resources are registered

}

The actuator endpoint will also be accessible (handled by the MVC infrastructure) since the Jersey filter will use the /jersey/ URL pattern and will not interfere with /actuator/health but in that case, you need to have org.springframework.boot:spring-boot-starter-web dependency in your pom.xml*

Comment From: philwebb

Thanks for the detailed analysis @nosan. It doesn't look like this is a bug so I'm going to close the issue.

Comment From: RameshVE123

Thank you for your suggestion.

Comment From: rdlf0

  • Since, you set spring.jersey.type=filter, the Jersey ServletContainer will be registered as Filter and filters are invoked on either the request to a resource (a servlet or static content), or on the response from a resource, or both, and in your application, there are no such resources. You can modify your configuration with the following changes:

```java @SpringBootApplication public class DemoApplication {

public static void main(String[] args) { SpringApplication.run(DemoApplication.class, args); }

@Bean ServletRegistrationBean noOpServlet() { return new ServletRegistrationBean<>(new NoOpServlet(), "/*"); }

public static class NoOpServlet extends GenericServlet {

  @Override
  public void service(ServletRequest servletRequest, ServletResponse servletResponse) {
      throw new UnsupportedOperationException("Not supported yet.");
  }

}

} ```

Once you have made all these changes, the actuator endpoint will be available on:

httpspec GET http://localhost:8080/msapi/actuator/health

A simpler way to achieve this is to just set server.servlet.register-default-servlet=true. This way you won't need to register a NoOpServlet.

Comment From: RameshVE123

Thank you for the response.

I have a follow up question on the @ApplicationPath annotation,

Does it support regex pattern like the below to register multiple url mappings or any alternate ways to do this.

@ApplicationPath(“/jersey/{ver: v[0-9]+}”)

Comment From: wilkinsona

@ApplicationPath is part of JAX-RS. As such, questions about what it supports don't belong in Spring Boot's issue tracker. I'd recommend checking the Javadoc for the annotation's value attribute and the JAX-RS spec. If that doesn't help, Stack Overflow may be a good place to ask.