ClientHttpRequestInterceptor with a http:outbound-gateway using a request-factory attribute - spring

I'm still on the subject of logging http requests. It's been mentioned that using a ClientHttpRequestInterceptor with a rest-template attribute of the http:outbound-gateway can be an approach.
Spring Integration AOP for Logging outbound Http requests
Logging http request in Spring integration http outbound gateway
However, I'm already using request-factory on my http:outbound-gateway objects since I want the Apache httpClient, using HttpComponentsClientHttpRequestFactory. This excludes defining a rest-template attribute on the http:outbound-gateway. Can the ClientHttpRequestInterceptor approach work this way? Or will I need to subclass the factory and produce a HttpClientRequest with an execute() method that does the logging? Thanks for any pointers.

The ClientHttpRequestFactory is a part of the RestTemplate as well. so, you just move that your HttpComponentsClientHttpRequestFactory configuration to the RestTemplate along side with that ClientHttpRequestInterceptor and inject into an http:outbound-gateway only that RestTemplate.

Related

Spring Boot metrics http.client.requests do not work for WebClient reactive applications

I have a spring boot 2.2.2 microservices, which integrations with other services using WebClient (rective). According to Spring documentation, the actuator should return "http.client.requests" metrics by default as Timer is enabled by default. But it does not work for me. I am able to get http.server.requests" metrics.
My WebClient is a bean configured and build with WebClient.builder(), as documented here: https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready-metrics-http-clients
Use Spring Boot's preconfigured WebClient.Builder instead of WebClient.builder() to have an instance of WebClient.
You can find more detail here.
As in the following you can have a bean of WebClient.
#Configuration
public class ClientConfiguration {
#Bean
public WebClient webClient(WebClient.Builder webClientBuilder) {
return webClientBuilder
.baseUrl("https://example.org")
.build();
}
}
WebClient.Builder is an Auto-configuration, means the injected point above will receive a newly cloned instance of the builder.
Here is the source for WebClientAutoConfiguration
I've noticed my application has to make a WebClient call before the metrics/http.client.requests endpoint exists. Prior to my application making a WebClient call that endpoint isn't discoverable and returns NOT FOUND.
Hope that helps others in a similar situation!

Spring: Inject initialized RestTemplates

Currently I have several services making requests to other services.
In order to build the requests I'm using Spring RestTemplates.
Is there anyway to inject a RestTemplate initialized with some headers...?
I was thinking about Factory injectors.
Any ideas?
I think you are approaching the problem incorrectly.
Instead of injecting a RestTemplate,
consider injecting an HttpEntity<?>.
Setup the HttpEntity<?> bean in your configuration #Bean method.
Then use which ever RestTemplate.exchange() method is appropriate to send your desired request.
Edits
The exchange method sends an HTTP message and returns the response.
Here is the RestTemplate JavaDoc Page

Spring-webflux, how to get the request as parameter in #ExceptionHandler

With spring webflux and the #RestController model, I have a #RestControllerAdvice with some #ExceptionHandler methods.
I would like to get the original request as parameter because I want to log it and use it in my response.
However I have tried all the possible types for an handler method in the classic MVC model but none of them was accepted (HttpServletRequest, WebRequest and ServerRequest).
What type can I use to access the original request in a webflux annotated handler method ?
You should use org.springframework.http.server.reactive.ServerHttpRequest, because:
HttpServletRequest and WebRequest are Servlet/Spring MVC specific
ServerRequest belongs to Spring WebFlux, but the functional variant

How to inject ResourceInfo in a ContainerRequestFilter in CXF

I am trying to build a token based authentication and authorization system using Apache CXF and Spring. I am completely following this fantastic post for doing this.
But I am stuck in a problem with my AuthorizationFilter at the very beginnig. I have seen many posts, apache JIRA, github comments about it, but could not yet found the workaround about this seemingly CXF issue.
#PreMatching
#Priority(Priorities.AUTHORIZATION)
public class AuthorizationFilter implements ContainerRequestFilter {
private ResourceInfo resourceInfo;
#Context
public void setResourceInfo(ResourceInfo resourceInfo) {
this.resourceInfo = resourceInfo;
}
#Override
public void filter(final ContainerRequestContext requestContext) throws IOException {
Method method = resourceInfo.getResourceMethod();
In the above code, the injected resourceInfo is a proxy object, and it has none of the associated properties present. So, anything from that resourceInfo object is returning null, more specifically resourceInfo.getResourceMethod() is null, leading to NPE.
This is the JIRA post pertaining to this very issue, saying that:
In some circumstances (like using #ApplicationScoped annotation for example) the CDI runtime will create a proxy class for a particular bean. As the result, the CXF side is going to bind the particular provider metadata to this proxy instance. It looks logical and unambiguous.
However, the interesting things are happening when CXF will try to inject contextual proxies (#Context annotations) into the provider instance. The injections are successful but the target object for them will be the proxy instance (not the real instance behind it). Consequently, at runtime, when the proxy delegates the call to a backing instance, all contextual proxies are null in there (simply put, not set).
Referring to the recent discussions with Sergey Beryozkin, the best solution would be to delegate the #Context annotation to CDI framework (as such, relieving the CXF from doing the injection work). This proposal may need a support from the JAX-RS specification side.
Simpler (interim?) possible solution would be to complement the CDI injection with #Context injection (delegating this work to the CXF as it works right now for non-proxy beans and non-CDI deployments). This could be done by observing ProcessInjectionTarget events and supplying our own InjectionTarget (have working PoC for this approach).
Regarding constructor injection, it seems like CXF does not support passing the arguments to provider constructor (in case of CDI, w/o #Context annotation) so I it would be another (separate) issue to look at.
Can someone help me point out what is this simpler approach is all about:
Simpler (interim?) possible solution would be to complement the CDI injection with #Context injection (delegating this work to the CXF as it works right now for non-proxy beans and non-CDI deployments). This could be done by observing ProcessInjectionTarget events and supplying our own InjectionTarget (have working PoC for this approach)
Or is there any other way, where Spring Framework can inject the ResourceInfo object in a correct way?
I have registered the filters like this in my applicationContext.xml :
<jaxrs:server id="endpoints">
<jaxrs:providers>
<ref bean="authenticationFilter" />
<ref bean="authorizationFilter" />
</jaxrs:providers>
</jaxrs:server>
The problem is the #PreMatching annotation.
Global binding annotation that can be applied to a container request filter to indicate that such filter should be applied globally on all resources in the application before the actual resource matching occurs.
The key is highlighted part "before the actual resource matching occurs". So even before the resource is matched to the request, the filter is called. And if there is no resource matched yet, then it is impossible to get any information from the ResourceInfo. If you just remove the #PreMatching annotation, then the filter will be called after a matching resource is found, and you will be able to access all the info from the ResourceInfo.

What does context annotation do in Spring?

In Rest API design, I am wondering what the exact purpose of the context annotation is?
private HttpServletRequest request;
#Context
public void setRequest(final HttpServletRequest req) {
request = req;
}
The purpose is to indicate that the request property should be set from the context.
#Context is used to inject various HTTP-ish contextual data, from here:
In general #Context can be used to obtain contextual Java types related to the request or response.
API docs (Not horribly useful IMO. Or, perhaps more accurately, horribly-useful.)
This annotation is used to inject information into a class field, bean property or method parameter.
JAX-RS #Context to get the ServletContext, and WebApplicationContextUtils to get the Spring application context, with this Spring application context, you are able to access and get beans from Spring container

Resources