Spring Boot Actuator Trace HTTP POST request parameters is coming empty - spring-boot

I am using Spring Boot 1.5.13 so using Actuator 1.5.13 . When i call with the post request ,request parameters is coming empty.
No other configuration or createing my Actuator repository.
I just using simple actuator trace end point.
Here is my properties:
endpoints.trace.enabled=true
endpoints.trace.sensitive=false
management.trace.include=request-headers,response-headers,cookies,errors,parameters
Here is the dependency :
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.13.RELEASE</version>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
Trace result :
parameters {}
Request Example :
{
"id": 22,
"secondid":350052 ,
"flag":0
}
Do you have any idea why it is happening and how i can fix it?

The parameters that are traced are those that are available from javax.servlet.ServletRequest.getParameterMap(). From its javadoc:
Request parameters are extra information sent with the request. For HTTP servlets, parameters are contained in the query string or posted form data.
Your HTTP request doesn't have a query string and it isn't POSTing form data so there are no parameters to trace.

For example if request is like /api/persons?name=peter, parameters will be available in the trace.
"parameters": {
"name": [
"peter"
]
}

Related

Access token not propagated in Spring Boot 2.7

We use Spring Boot with an OIDC integration to provide authentication and authorization to our users.
Our application acts as Client in the OIDC code flow, calling downstream Resource servers through Http requests to serve user requests.
To have the Client pass the access token of the authenticated user to Resource servers we use the ServletOAuth2AuthorizedClientExchangeFilterFunction and apply that to the org.springframework.web.reactive.function.client.WebClient handling downstream requests.
We recently upgraded from Spring Boot 2.6.7 to 2.7.3 and discovered that the Authentication header containing the access token is no
longer added to outgoing requests, if those requests are scheduled on a thread other than the one serving the original request:
public class MyController {
public Mono<ProductSearchResult> searchByName(SearchProductsQuery query) {
List<String> sortOrder = new ArrayList<>();
System.out.println("--OUTER: " + Thread.currentThread().getName());
return resourceServere.searchByName(query)
.doOnNext(searchResponse -> sortOrder.addAll(searchResponse.getIds()))
.flatMap(searchResponse -> Mono.zip(
getSomething(searchResponse.getIds()),
getSomethingElse(searchResponse.getIds()),
Mono.just(searchResponse.pagination())))
.map(tuple3 -> SearchResultMapper.map(tuple3.getT1(), tuple3.getT2(), tuple3.getT3()));
}
private Mono<List<String>> getSomething(List<String> ids) {
System.out.println("--INNER: " + Thread.currentThread().getName());
if (ids.isEmpty()) {
return Mono.just(new ArrayList<>());
}
return otherResourceServerClient.getStuff(ids);
}
}
Which prints
--OUTER: http-nio-8080-exec-6
--INNER: reactor-http-nio-3
Debugging ServletOAuth2AuthorizedClientExchangeFilterFunction we discovered that the request in the http-nio-thread has the Authentication:
Debugger stopped in ServletOAuth2AuthorizedClientExchangeFilterFunction
whereas the request in the reactor-http thread does not:
Debugger stopped in ServletOAuth2AuthorizedClientExchangeFilterFunction
I can certainly provide more information about our setup, I'm just a bit uncertain what would be relevant.
For starters though, we depend on both spring-starter-webflux and spring-boot-starter-web, as well as on spring-boot-starter-security
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
Curious to hear if anyone has experienced the same issue?

Centralized Swagger/OpenAPI UI for all the different microservices on a single swagger URL i.e accessing all the URLs through one

I have around 16 microservices built in Spring Boot that communicate with each other and each microservice is having multiple APIs in it. I have configured OpenAPI for each of the microservices. So it gives me 16 "swagger-ui" URLs.
I wonder how can I centralize all Swagger URLs on one single page; I want only 1 swagger URL to access all the 16 microservices.
I have gone through the following as well but didn't get any solution
Centralize Swagger at one place for All microservices
Please guide me to the best way to achieve it.
I found a working solution on GitHub. It works with Spring Cloud Discovery but can be easily adapted to other discovery solutions. The basic idea is to generate for Swagger the list of URLs pointing to the OpenAPI JSON files.
The result is similar to one in the #shadyx's answer, but the list is generated dynamically
#RestController
public class SwaggerUiConfig {
#Autowired
private DiscoveryClient discoveryClient;
#GetMapping("/swagger-config.json")
public Map<String, Object> swaggerConfig() {
List<SwaggerUrl> urls = new LinkedList<>();
discoveryClient.getServices().forEach(serviceName ->
discoveryClient.getInstances(serviceName).forEach(serviceInstance ->
urls.add(new SwaggerUrl(serviceName, serviceInstance.getUri() + "/v3/api-docs"))
)
);
return Map.of("urls", urls);
}
}
application.yaml
springdoc:
swagger-ui:
configUrl: "/swagger-config.json"
Sample of the generated swagger-config.json
{
"urls": [
{
"url": "http://localhost:8088/v3/api-docs/users",
"name": "users"
},
{
"url": "http://localhost:8088/v3/api-docs/stores",
"name": "stores"
}
]
}
If all you µservices use the same host, you can create a Spring Boot µservice which acts as a openAPI gateway using spring-doc. (If they are not using the same host, you will have to deal with CORS issues)
First, add the following dependencies to your new gateway µservice
<dependency>
<groupId>org.springdoc</groupId>
<artifactId>springdoc-openapi-ui</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Then, add the below configuration
springdoc:
api-docs:
enabled: true
swagger-ui:
configUrl: ${server.servlet.contextPath}/v3/api-docs/swagger-config
url: ${server.servlet.contextPath}/v3/api-docs
urls:
- name: api-customer
url: /customer/v3/api-docs
- name: api-cart
url: /cart/v3/api-docs
- name: api-product
url: /product/v3/api-docs
For each µservice you have to fill in the url property with is the url to the openAPI definition at json or yaml format.
For springdoc library which uses openAPI 3.0 the default url is /${µServiceContextPath}/v3/api-docs
For springfox library which uses openAPI 2.0 the default url is /${µServiceContextPath}/v2/api-docs
Finally access to /${contextPath}/swagger-ui.html and you will be able to select an openAPI

Configure HTTPS in Spring Boot Apache Camel REST API with keystore having multiple certs using camel-jetty component

I am trying to configure https in my apache camel Spring Boot REST application (using apache-camel v3.11.1, springboot v2.5.3) with keystore having multiple certificates.
Problem:
Application run failed
org.apache.camel.RuntimeCamelException: java.lang.IllegalStateException: KeyStores with multiple certificates are not supported on the base class org.eclipse.jetty.util.ssl.SslContextFactory. (Use org.eclipse.jetty.util.ssl.SslContextFactory$Server or org.eclipse.jetty.util.ssl.SslContextFactory$Client instead)
at org.apache.camel.RuntimeCamelException.wrapRuntimeCamelException(RuntimeCamelException.java:51) ~[camel-api-3.11.1.jar:3.11.1]
Project setup:
pom.xml: (dependencies only, to show that I am not using spring-boot-web-starter)
..
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.camel.springboot</groupId>
<artifactId>camel-jetty-starter</artifactId>
</dependency>
..
..<!-- all other required dependencies are in place-->
..
</dependencies>
..
application.properties
#camel.component.jetty.keystore=keystore-with-one-certificate.jks # WORKS
camel.component.jetty.keystore=keystore-with-multiple-certificates.jks # DOESN'T WORK
camel.component.jetty.ssl-key-password=password
camel.component.jetty.ssl-password=password
Rest Route:
restConfiguration()
.component("jetty")
.scheme("https")
.port("8080");
rest()
.path("/api")
.get("/{name}")
..
..
.to("direct:x");
Looked at answers in the below posts, but still not able to resolve the exception that I get,
https://stackoverflow.com/a/60598953/6363894,
https://stackoverflow.com/a/55499113/6363894
I know that exception clearly states to use org.eclipse.jetty.util.ssl.SslContextFactory$Server, but I don't understand how/where to use SslContextFactory.Server object.
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStoreResource(findKeyStorePath());
sslContextFactory.setKeyStorePassword("password");
sslContextFactory.setKeyManagerPassword("password");
sslContextFactory.setNeedClientAuth(true);
Also I've created a bean for sslContextParameters and added that to restConfiguration as below, this time application runs successfully but then when I test, SSL handshake fails.
restConfiguration()
.component("jetty")
.endpointProperty("sslContextParameters", "#sslContextParameters")
.scheme("https")
.port("8080");
#Bean(name = "sslContextParameters")
public SSLContextParameters setSSLContextParameters() {
KeyStoreParameters ksp = new KeyStoreParameters();
ksp.setResource("keystore-with-multiple-certificates.jks");
ksp.setPassword("password");
KeyManagersParameters kmp = new KeyManagersParameters();
kmp.setKeyStore(ksp);
kmp.setKeyPassword("password");
SSLContextServerParameters scsp = new SSLContextServerParameters();
scsp.setClientAuthentication("REQUIRE");
SSLContextParameters scp = new SSLContextParameters();
scp.setServerParameters(scsp);
scp.setKeyManagers(kmp);
return scp;
}
Any help on how to configure SslContextFactory.Server object with the restConfigurations() or any other way I can achieve this? I'll update the post, if any more details are required.

Avoid sending zero values to InfluxDB

I'm using Spring Boot Actuator + Micrometer to send values to micrometer, so i have the following maven:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>io.micrometer</groupId>
<artifactId>micrometer-registry-influx</artifactId>
</dependency>
So, i have a method that start timer and stop timer sample (micrometer):
public Timer.Sample starTimer() {
return Timer.start(registry);
}
public void stopTimer(Class clazz, Timer.Sample sample) {
sample.stop(registry.timer("timer-dev", Arrays.asList(Tag.of("modulo", modulo), Tag.of("class", clazz.getName()))));
}
So, this works very well. InfluxDB receive value sent from Spring Boot Application and show in Grafana.
The problem: After sending "timer-dev" first time to influx, spring boot keeping sending values "0" continually, i would like avoid spring boot sending zero values, it should send only when timer-dev greater then zero. The "timer-dev" should be sent only when this method is called not everytime.
Any tips ?

Testing with spring-test-mvc jsonpath returns null

I am using Spring's "spring-test-mvc" library to test web controllers. I have a very simple controller that returns a JSON array. Then in my test I have:
#Test
public void shouldGetAllUsersAsJson() throws Exception {
mockMvc.perform(get("/v1/users").accept(MediaType.APPLICATION_JSON))
.andExpect(content().mimeType(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("fName").exists());
}
The above test returns:
java.lang.AssertionError: No value for JSON path: fName
To quickly check what I actually get I ran the below test:
#Test
public void shouldPrintResults() throws Exception {
mockMvc.perform(get("/v1/users").accept(MediaType.APPLICATION_JSON))
.andDo(print());
}
And it returns the correct JSON array in the body of MockHttpServletResponse
I'm not sure why jsonPath is not able to see fName in the JSON array.
If you add the json path dependency to maven, or add the jar to your lib, then it will work. I think that Spring is not including the jsonPath dependency in the latest Spring 3.2.0 RC1 release. I'm guessing that this is the same for Spring-Test-MVC standalone project as well.
Here is the dependency for Maven:
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>0.8.1</version>
<scope>test</scope>
</dependency>
You might also need the hamcrest library to use the jsonPath("$.test").value("test")
<dependency>
<groupId>org.hamcrest</groupId>
<artifactId>hamcrest-library</artifactId>
<version>1.3</version>
<scope>test</scope>
</dependency>
What does your json response body look like? You can see it by doing an .andDo(print())
You might want to try jsonPath("$.fName").
This is assuming that your json response is:
{"fName":"first name"}
If your response is an array then you need jsonPath("$[0].fName") for a response like:
[{"fName":"first name"},{"fName":"first name #2"}]
You can see more examples at: http://goessner.net/articles/JsonPath/

Resources