After moving from spring-boot v1.3 to the newest spring-boot v2.2.4 we've lost the ability to have custom endpoints under management port.
Before we had our custom endpoints declared as:
#Component
public class CacheEndpoint implements MvcEndpoint {
...
#Override
public String getPath() {
return "/v1/cache";
}
...
// mappings goes here
Since MvcEndpoint has been removed from spring-boot actuator now we need to do next:
#Component
#RestControllerEndpoint(id = "cache")
public class CacheEndpoint {
...
// mappings goes here
Unfortunately, we've lost an option to have a custom root path for our custom management endpoints (before it was /v1/)
For back-compatibility, we still want to have default actuator endpoints such as health, metrics, env.. to be under / base path. e.g. host:<management_port>/health, but at the same time we still want to support our custom endpoints under /v1/ path, e.g. host:<management_port>/v1/cache
I tried a lot of things, googled even more, but no success yet.
Is there a way to achieve this?
This is what I use for spring boot 2:
application.yml:
management:
endpoints:
enabled-by-default: true
web:
exposure:
include: "*"
base-path: "/management" # <-- note, here is the context path
All-in-all consider reading a migration guide for actuator from spring boot 1.x to 2.x
Related
Setup
I use a Spring Boot app from the Initializr with Jersey dependency included and add io.swagger.core.v3:swagger-jaxrs2:2.1.13 as an additional dependency. Then I create the following ResourceConfig (registering other resource classes omitted for brevity):
#Component
public class JerseyConfig extends ResourceConfig {
public JerseyConfig() {
this.registerClasses(
OpenApiResource.class
);
}
}
When I start the application and have a look at the generated API spec at http://localhost:8080/openapi.json, I find two paths:
GET /application.wadl/{path} and
GET /application.wadl
In Swagger UI, it looks like this:
When I send a request to the WADL endpoint, I get a 404 response in this setup. I already tried to disable the WADL feature with this line, but the spec still contains the two paths:
this.property(ServerProperties.WADL_FEATURE_DISABLE, true);
Question
How do I disable or hide these two paths in the OpenAPI spec properly?
May be you can try packages-to-scan property
springdoc:
packages-to-scan:
- com.myapp.appName.controller
The OpenApi documentation says that it supports micrometer. How does the integration works? I could not find anything except this little documentation.
I have a FeignClient in a spring boot application
#FeignClient(name = "SomeService", url = "xxx", configuration = FeignConfiguration.class)
public interface SomeService {
#GET
#Path("/something")
Something getSomething();
}
with the configuration
public class FeignConfiguration {
#Bean
public Capability capability() {
return new MicrometerCapability();
}
}
and the micrometer integration as a dependency
<dependency>
<groupId>io.github.openfeign</groupId>
<artifactId>feign-micrometer</artifactId>
<version>10.12</version>
</dependency>
The code makes a call but I could not find any new metrics via the actuator overview, expecting some general information about my HTTP requests. What part is missing?
Update
I added the support for this to spring-cloud-openfeign. After the next release (2020.0.2), if micrometer is set-up, the only thing you need to do is putting feign-micrometer onto your classpath.
Old answer
I'm not sure if you do but I recommend to use spring-cloud-openfeign which autoconfigures Feign components for you. Unfortunately, it seems it does not autoconfigure Capability (that's one reason why your solution does not work) so you need to do it manually, please see the docs how to do it.
I was able to make this work combining the examples in the OpenFeign and Spring Cloud OpenFeign docs:
#Import(FeignClientsConfiguration.class)
class FooController {
private final FooClient fooClient;
public FooController(Decoder decoder, Encoder encoder, Contract contract, MeterRegistry meterRegistry) {
this.fooClient = Feign.builder()
.encoder(encoder)
.decoder(decoder)
.contract(contract)
.addCapability(new MicrometerCapability(meterRegistry))
.target(FooClient.class, "https://PROD-SVC");
}
}
What I did:
Used spring-cloud-openfeign
Added feign-micrometer (see feign-bom)
Created the client in the way you can see above
Importing FeignClientsConfiguration and passing MeterRegistry to MicrometerCapability are vital
After these, and calling the client, I had new metrics:
feign.Client
feign.Feign
feign.codec.Decoder
feign.codec.Decoder.response_size
When we use 'KeycloakSpringBootConfigResolver' for reading the keycloak configuration from Spring Boot properties file instead of keycloak.json.
Now there are guidelines to implement a multi-tenant application using keycloak by overriding 'KeycloakConfigResolver' as specified in http://www.keycloak.org/docs/2.3/securing_apps_guide/topics/oidc/java/multi-tenancy.html.
The steps defined here can only be used with keycloak.json.
How can we adapt this to a Spring Boot application such that keycloak properties are read from the Spring Boot properties file and multi-tenancy is achieved.
You can access the keycloak config you secified in your application.yaml (or application.properties) if you inject org.keycloak.representations.adapters.config.AdapterConfig into your component.
#Component
public class MyKeycloakConfigResolver implements KeycloakConfigResolver {
private final AdapterConfig keycloakConfig;
public MyKeycloakConfigResolver(org.keycloak.representations.adapters.config.AdapterConfig keycloakConfig) {
this.keycloakConfig = keycloakConfig;
}
#Override
public KeycloakDeployment resolve(OIDCHttpFacade.Request request) {
// make a defensive copy before changing the config
AdapterConfig currentConfig = new AdapterConfig();
BeanUtils.copyProperties(keycloakConfig, currentConfig);
// changes stuff here for example compute the realm
return KeycloakDeploymentBuilder.build(currentConfig);
}
}
After several trials, the only feasible option for spring boot is to have
Multiple instances of the spring boot application running with different spring 'profiles'.
Each application instance can have its own keycloak properties (as it is under different profiles) including the realm.
The challenge is to have an upgrade path for all instances for version upgrades/bug fixes, but I guess there are multiple strategies already implemented (not part of this discussion)
there is a ticket regarding this problem: https://issues.jboss.org/browse/KEYCLOAK-4139?_sscc=t
Comments for that ticket also talk about possible workarounds intervening in servlet setup of the service used (Tomcat/Undertow/Jetty), which you could try.
Note that the documentation you linked in your first comment is super outdated!
While updating my Spring Boot application to the latest build snapshot and I am seeing that none of the actuator endpoints are enabled by default. If I specify them to be enabled in application.properties, they show up.
1) Is this behavior intended? I tried searching for an issue to explain it but couldn't find one. Could somebody link me to the issue / documentation?
2) Is there a way to enable all the actuator endpoints? I often find myself using them during development and would rather not maintain a list of them inside my properties file.
Two parts to this answer:
"Is there a way to enable all the actuator endpoints?"
Add this property endpoints.enabled=true rather than enabling them individually with endpoints.info.enabled=true, endpoints.beans.enabled=true etc
Update: for Spring Boot 2.x the relevant property is:
endpoints.default.web.enabled=true
"Is this behavior intended?"
Probably not. Sounds like you might have spotted an issue with the latest milestone. If you have a reproducible issue with a Spring Boot milestone then Spring's advice is ...
Reporting Issues
Spring Boot uses GitHub’s integrated issue tracking system to record bugs and feature requests. If you want to raise an issue, please follow the recommendations below:
Before you log a bug, please search the issue tracker to see if someone has already reported the problem.
If the issue doesn’t already exist, create a new issue.
Even if we enable all the actuator endpoints as below
management.endpoints.web.exposure.include=* (In case of YAML the star character should be surrounded by double quotes as "*" because star is one of the special characters in YAML syntax)
The httptrace actuator endpoint will still not be enabled in web by default. HttpTraceRepository interface need to be implemented to enable httptrace (See Actuator default endpoints, Actuator endpoints, Actuator httptrace).
#Component
public class CustomHttpTraceRepository implements HttpTraceRepository {
AtomicReference<HttpTrace> lastTrace = new AtomicReference<>();
#Override
public List<HttpTrace> findAll() {
return Collections.singletonList(lastTrace.get());
}
#Override
public void add(HttpTrace trace) {
if ("GET".equals(trace.getRequest().getMethod())) {
lastTrace.set(trace);
}
}
}
Now the endpoints can be accessed using the url,
http://localhost:port/actuator/respective-actuator-endpoint
(Example http://localhost:8081/actuator/httptrace)
If there is a management.servlet.context-path value present in properties file then the URL will be,
http://localhost:port/<servlet-context-path>/respective-actuator-endpoint
(Example http://localhost:8081/management-servlet-context-path-value/httptrace)
UPDATE: use this only in dev environment, not in production!
Is there a way to enable all the actuator endpoints?
Using Spring Boot 2.2.2 Release, this worked for me:
On the file src/main/resources/application.properties add this:
management.endpoints.web.exposure.include=*
To check enabled endpoints go to http://localhost:8080/actuator
Source: docs.spring.io
What I want to do
Create two (different) endpoints using Spring Boot Actuator
My environment
Spring Boot 1.4.2
spring-boot-starter-actuator embedded in Spring Boot 1.4.2
Detail
I'm creating a Web app using Spring Boot and will need to create two separated endpoints: one for just checking application health including the app's DB connection and so on (This will be realized by the default behavior of "/health") and the other for just checking if the app is ready for accepting HTTP requests (say "/httpcheck").
To implement health check feature, I guess it's the fastest way to use Spring Boot Actuator (by default, /health is mapped to health check endpoint).
I also understand we can configure this endpoint by extending AbstractHealthIndicator (so that it will include DB health check).
But as far as I could see, I could not find a way to create more than one endpoints to do different health checks.
Do you have any ideas?
Thanks in advance.
Thanks for your answer.
Actually, I dealt with this problem by implementing a new endpoint (/httpcheck) to simply check if its HTTP stack works well or not.
HttpCheckEndpoint.java
#Component
#ConfigurationProperties(prefix = "endpoints.httpcheck") // Specifies the prefix on application.yml
public class HttpCheckEndpoint extends AbstractMvcEndpoint {
public HttpCheckEndpoint() {
super("/httpcheck", false);
}
/**
* Check if simply the app can connect to their own HTTP stack and return 200 OK.
* <ul>
* <li>Method: GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS</li>
* <li>Endpoint: "/httpcheck"</li>
* </ul>
*/
#RequestMapping
#ResponseBody
public ResponseEntity<String> checkHttpConnecton() {
if (!isEnabled()) {
return new ResponseEntity<String>("", HttpStatus.NOT_FOUND);
} else {
return new ResponseEntity<String>("{\"status\": \"UP\"}", HttpStatus.OK);
}
}
}
application.yml
endpoints:
enabled: false # Default enabled/disabled on endpoints on Spring Boot Actuator
health: # Health check (already prepared in Spring Boot Actuator)
enabled: true
httpcheck: # Simple HTTP connection check (newly created by myself)
enabled: true
I've confirmed it worked well, although not sure if it's the best solution...
Solution
You can use Jolokia end points in your Spring-boot application and get it registered with o.s.b.a.e.jmx.EndpointMBeanExporter along with your Actuator Plugins.
<dependency>
<groupId>org.jolokia</groupId>
<artifactId>jolokia-core</artifactId>
<version>1.2.2</version>
</dependency>
Jolokia Configurations in application.properties
jolokia.config.debug=true
endpoints.jolokia.enabled=true