Reputation: 629
I have a project setup with spring boot 1.4.2 and CXF JAXRS. I want to add spring boot actuator to the project. This is the configuration which I added to the project.
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
I create a WAR file after this and then deploy it in external tomcat server. But when I access the health URL localhost:8080/management/health it is giving 404 HTTP code. The server starts properly and I can see the logs with following details:
Health configuration log
[localhost-startStop-1] INFO org.springframework.boot.actuate.endpoint.mvc.EndpointHandlerMapping - Mapped "{[/management/health || /management/health.json],produces=[application/json]}" onto public java.lang.Object
Servlet(s) configuration log
[localhost-startStop-1] INFO org.springframework.boot.web.servlet.DelegatingFilterProxyRegistrationBean - Mapping filter: 'springSecurityFilterChain' to: [/*]
[localhost-startStop-1] INFO org.springframework.boot.web.servlet.FilterRegistrationBean - Mapping filter: 'webRequestLoggingFilter' to: [/*]
[localhost-startStop-1] INFO org.springframework.boot.web.servlet.FilterRegistrationBean - Mapping filter: 'applicationContextIdFilter' to: [/*]
[localhost-startStop-1] INFO org.springframework.boot.web.servlet.ServletRegistrationBean - Mapping servlet: 'dispatcherServletRegistration' to []
[localhost-startStop-1] INFO org.springframework.boot.web.servlet.ServletRegistrationBean - Mapping servlet: 'dispatcherServlet' to [/]
[localhost-startStop-1] INFO org.springframework.boot.web.servlet.ServletRegistrationBean - Mapping servlet: 'CXFServlet' to [/services/*]
Upvotes: 3
Views: 2476
Reputation: 2241
In my case i have Spring 1.5.X , i cannot use two different base paths for CXF and Spring Actuator. I need to keep "/" for root application path and add a RestEnpoint for returning actuator Health result.
So i use another approach when CXF returns a string result from Health Info generated on Service layer using @Autowired + ObjectMapper.
Note: you should enable the annotation context support for apply this solutions.
These following workaround works for me :
keep your CXF Servlet on "/"
In my case i'm using Camel + CXF, however all you need to do is creating the following component for build the Health object:
@Component
public class InfoHealthEndpoint extends HealthEndpoint {
@Autowired
private InfoEndpoint infoEndpoint;
public InfoHealthEndpoint(HealthAggregator healthAggregator, Map<String, HealthIndicator> healthIndicators) {
super(healthAggregator, healthIndicators);
}
@Override
public Health invoke() {
Health health = super.invoke();
return new Health.Builder(health.getStatus(), health.getDetails())
.withDetail("info", infoEndpoint.invoke())
.build();
}
}
And create a service that returns the String result for CXF response controller.
@Service public class HealthService {
@Autowired
private InfoHealthEndpoint infoHealthEndpoint;
@Autowired
private ObjectMapper mapper;
private static final String HEALTH_UP = "UP";
public void health(Exchange exchange) throws JsonProcessingException {
Health health = infoHealthEndpoint.invoke();
String healthReponse = mapper.writeValueAsString(infoHealthEndpoint.invoke());
if(!HEALTH_UP.equals(health.getStatus().getCode())){
Response response = Response.status(503).entity(healthReponse).build();
exchange.getOut().setBody(response);
exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
}else{
exchange.getIn().setBody(healthReponse);
}
}
}
NOTE: in my case, im using Apache Camel (Exchange) for set response on route, however this solution could applyable for another situation by using a simple String return.
Credits for @Danny on this answer: Combine Spring Boot Actuator /health and /info into one
Upvotes: 1
Reputation: 629
Issue is solved and here is the details. Since CXF and spring boot together were together cofigured, both CXF REST API and actuator end point were configured for '/'. The name of servlet bean configured for CXF RESt end point is dispatcherServletRegistration. An auto configuration for CXF servlet was also happening since boot starter for CXf was there in the POM. Hence you can find CXFServlet also configured for /services/*.
Mapping servlet: 'dispatcherServletRegistration' to []
Mapping servlet: 'dispatcherServlet' to [/]
Mapping servlet: 'CXFServlet' to [/services/*]
I removed auto configuration option (CXFServlet) since I have some customization required for the CXF JAXRS implementation and mapped dispatcherServletRegistration to /services/* and now everything is working fine. Now actuator works under '/' and CXF REST APIs under /services.
Upvotes: 1