How to change Spring Boot health actuator result for testing? - java

When using Spring Boot health actuator
http://localhost:8080/health
{"status":"UP","diskSpace":{"status":"UP","total":122588196864,"free":59227926528,"threshold":10485760},"mongo":{"status":"UP","version":"3.2.6"}}
Now I want to check for other condition, so as to check dependent action are triggered when status is down. I want something like
{"status":"Down"}

You can write your custom 'Health Indicator' which would override the default Health Indicator and write your implementation (e.g. Always return status as down).
Now, as this is only needed to test the app, I would recommend annotating this with #Profile so that it only gets activated when the app is started with let's say test profile, e.g.:
#Component
#Profile("test")
public class MyHealthIndicator implements HealthIndicator {
By this way, if you start the app with any profile other than test, default HealthIndicator will be used.

First disable the default /health endpoint or customize it to some different endpoint. You can disable it follow
endpoints.health.disabled=true
Once this is disabled, implement your own custom endpoints at /health and define your custom conditions with whatever you like to check.
You can take a look here for creating custom endpoints
Don't forget to use test profile while creating custom endpoint

Related

Is there a possibility to add custom spring boot metrics tags at runtime?

I'm using Spring Boot with micrometer-registry-prometheus, trying to store custom tags from http headers, security context, etc.
So I found MeterFilter iterface and tried to use it to store the data I need.
But MeterFilter method works after request is completed, so at that point I don't have any information about request.
Seems like the case is pretty common, is there any possibility to achieve it?
If you're using Spring MVC you can define a bean that implements WebMvcTagsProvider to take complete control over the tags that are added to metrics for request-response exchanges. Alternatively, you can define a bean that implements WebMvcTagsContributor to add to the default tags. Similarly, if you're using Spring WebFlux you can define beans that implements WebFluxTagsProvider and WebFluxTagsContributor to take complete control over the tags and contribute additional tags respectively.

Set default response content type in Spring Boot REST API

Response content type on REST API endpoints (controller classes or methods) in Spring Boot can be set using the #Produces annotation. Is there a way to set this application wide as a default for every endpoint in the REST API? For example, instead of writing #Produces("application/json") on every controller class or endpoint, can this be set on the entry application class? Or is there any other way to configure a default used until explicitely overwritten?
If you want to set the default Accept header, not of default "Content-Type" header, so this solution will only impact responses, not requests.
As of Spring Boot 2.x, you need to create a class that extends the WebMvcConfigurer interface, e.g.:
#Configuration
class WebMvcConfiguration implements WebMvcConfigurer {
#Override
public void configureContentNegotiation( ContentNegotiationConfigurer configurer){
configurer.defaultContentType( MediaType.APPLICATION_JSON );
}
}
Let me know the result. Good luck.
Another option is to specify this default-media-type property in your application.properties:
spring.data.rest.default-media-type=application/json
Interestingly, it's also shown here as defaultMediaType. I believe you can use either the above or:
spring.data.rest.defaultMediaType=application/json
I'm not sure actually why there appear to be 2 ways to specify this same property.

CAS redirect to URL on succesfull login

Here a solution is described to handle redirects to a custom URL based on a condition via use of AccessStrategy.
This however is part of the unauthorized login logical flow therefore results into a still not-logged in user arriving at the end url we redirect to. (via getUnauthorizedUrl)
If we want to redirect the user based on a condition, say via injecting an action to the webflow, how can we manipulate the return URL to be changed into a custom one?
WebUtils.getService(requestContext) include getters of the source/originalUrl but no obvious way to set/manipulate said value through an action bean.
p.s. Currently using CAS version 5.3.x
Responses for normal web applications from CAS are built using WebApplicationServiceResponseBuilder.
If you examine this block you will find that the final response is built using WebApplicationServiceResponseBuilder bean. It is only created conditionally, if an existing bean is not already found in the context by the same name. So to provide your own, you just need to register a bean with the same name using your own #Configuration class.
#Bean
public ResponseBuilder<WebApplicationService> webApplicationServiceResponseBuilder() {
return new MyOwnWebApplicationServiceResponseBuilder(...);
}
...and then proceed to design your own MyOwnWebApplicationServiceResponseBuilder, perhaps even by extending WebApplicationServiceResponseBuilder and overriding what you need where necessary to build the final redirect logic conditionally.
To learn about how #Configuration classes work in general, you can:
Review this post
or this post
or consult the documentation for Spring and/or Spring Boot.

Spring Boot Actuator - enable single endpoint

There's a difference in implementation between two versions of Spring Boot Actuator (1.2.5 and 1.3.0) in HealthMvcEndpoint, isUnrestricted() method ( && and || ). I understand that this is to preserve these restrictions
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#production-ready-health-access-restrictions
But is there any solution now to enable only one endpoint (e.g. Health) unrestricted with full content, without exposing all the others?
Disabling management.security.enabled is just making all the endpoints accessible without authentication (?) - it doesn't look like it's taking endpoint sensitivity with it.
I managed to partially solve this by making all the endpoints disabled in the first place by endpoints.enabled = false with disabling their security management.security.enabled = false
and enabled the ones I wanted without security - like the Health endpoint
endpoints.health.enabled = true and endpoints.health.sensitive = false.
With actuator 2 these properties have been changed
To disable all the actuator endpoints use
management.endpoints.enabled-by-default=false
To enable specific endpoint use management.endpoint.<id>.enabled property. The following example enables the shutdown endpoint:
management.endpoint.shutdown.enabled=true
Official Documentation
https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html

Spring MVC: Log Controller paths without params

I am trying to add some metric gathering to a Spring MVC app. Lets say I have a controller whose mapping is:
/User/{username}/Foobar
I want to gather metrics on all controller mapping invocations with the path. Right now I can create a handler/interceptor and look at the requests but that will give me:
/User/Charlie/Foobar
Which is not what I want. I want the controller mapping itself to log. and I don't want to have to add something to every controller. I'd also rather not use AOP if I can help it.
It turns out that Spring hangs the best matching controller pattern on the request itself. You can get this from within a handlerinterceptor like this:
(String)request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE)
I can think of two choices:
It seems to me the results of the matching are obtained in the class org.springframework.web.servlet.handler.AbstractUrlHandlerMapping, which logs the patterns obtained (see line 266). I'd try enabling logging for that class and see if the output is helpful for your purposes.
(Complicated)
Extending org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping to override the lookupHandler method inherited from AbstractUrlHandlerMapping and logging/registering what you need. Accoding to this class documentation, you can register a different one so that the DispatcherServlet uses your version.
In Spring 3.2.x DefaultAnnotationHandlerMapping is deprecated so, a different class would have to be used.

Categories