Spring Boot: Extend/Edit Apache HttpClientBuilder with different configurations? - spring-boot

I am having an architectural issue with the Apache HttpComponents HttpClient.
We have a system where we have several different remote endpoints that we want to contact, and each have some different configurations like ssl, basic auth, et cetera.
I am using Spring Boot and Cloud Sleuth from which I get a HttpClientBuilder that gives me tracing and other things. I want to re-use that HttpClientBuilder but on-top of that add my own specific configurations, for each unique endpoint.
The problem though is that the HttpCientBuilder is not immutable with withXYZ() methods, nor is there a copy or clone method on the builder, so I can't copy the original and change just my specific changes there without altering the base HttpClientBuilder and get into conflicts with others that use the same instance of the builder. Be it racing conditions between threads or conflicting configurations between the different endpoints.
One place in the Spring Boot project where I have seen them seemingly wanting to do something similar is in HttpClientConfiguration of Spring Cloud Commons where it creates an own ApacheHttpClientFactory which takes the original autowired HttpClientBuilder and then sets disableContentCompression(), disableCookieManagement() and useSystemProperties() -- but it seemingly does it to the original instance of the HttpClientBuilder which just seems completely wrong to me. It will alter how all the built HttpClient works, and not just the one they will later be using in their Ribbon code in HttpClientRibbonConfiguration of Spring Cloud Netflix Ribbon. A potential bug in hiding? To me it seems like it, since it highly depends on calling order.
Does anyone have any ideas how something like this should be solved?
The easy alternative that I could do is to just not try and build upon the given HttpClientBuilder from Sleuth, but instead build a completely new one from the ground-up every time I need one, and check if a HttpTracing bean is available and use TracingHttpCientBuilder instead of HttpClientBuilder in that case, but this seems counter-intuitive.

I ran into the exact same problem. However, I had the option of defining my own HttpClientBuilder bean. I am not sure you are in the same position?
But by making the bean scope "prototype" a new bean instance is created every time it is injected somewhere. Then I could safely modify the HttpClientBuilder after injection.
#Bean
#Scope("prototype")
public HttpClientBuilder tracingHttpClientBuilder(..) {
...
}

Related

What is the correct way to add custom Prometheus metrics to a client library?

We have recently started monitoring our springboot apps with the micrometer prometheus integration. For the most part it works great out of the box; however, we have a client lib which wraps an http client for communicating with one of our apis that does NOT use Spring components, and is therefore excluded from the http_client_requests_* metric set.
The solution is obviously a #Timer annotation to manually add those custom metrics, and since our client api lib only exposes two methods, it would be ideal to just annotate these methods instead of having to add a timer anywhere I make a call with the lib in my app. The problem is, all of the setup instructions I find assume you're adding the integration to a server app instead of a lib, and I'm having trouble getting it to work.
I first tried adding the actuator and micrometer prometheus dependencies using compileOnly and runtimeOnly to hopefully not collide with the same dependencies being imported into my app, but even when that doesnt work and I change the imports to 'implementation' I get the 'No bean found with type of MeterRegistry' error other people have reported when I try to expose the TimedAspect bean like so:
#Bean
public TimedAspect timedAspect(MeterRegistry registry) {
return new TimedAspect(registry);
}
Even if I got this to work, my thinking is I'd run into issues again with the
management.endpoints.web.exposure.include=health,info,prometheus
configuration the tutorials say is necessary to enable metrics collection, since my app already does this. So, before I get much deeper in attempting this approach I'd like to ask: Is there a better way to accomplish what I'm trying to do?

OAuth2AccessTokenResponseClient - Interface is blocking?

The code-base I work with has a working OAuth model that uses OAuth2RestTemplate to manage access-tokens & access-token requests. As OAuth2RestTemplate is deprecated, I want to move to Spring Security OAuth & WebClient.
When I looked at some of the classes involved, I was surprised to see that OAuth2AccessTokenResponseClient does not return a Mono, and the default implementation - DefaultPasswordTokenResponseClient - uses RestTemplate internally.
I thought one of the primary advantages of WebClient was that it was non-blocking? If that is the case, why is blocking I/O one of the default strategies for requesting access-tokens? From the perspective of someone new to reactive/WebClient, I do not understand why the OAuth2AccessTokenResponseClient isn't itself a WebClient instance.
If I try to write a custom filter that uses WebClient to request the token, will I encounter major roadblocks or hard-to-detect bugs? I do not have much knowledge to build off in this area but would still appreciate if someone could try to help out.
You are wrong a little: OAuth2RestTemplate is not deprecated; since Spring version 2.2.0 plenty classes are moved to new and other libraries, Spring left in OAuth module only the Authentication server, all other classes annotated as deprecated. OAuth2RestTemplate is used further, just with another package.
In light of this you can use RestTemplate further, but with changes in a project. Or, of course, to move to WebClient. This approach is not better or worse, it's just can work asynchronous and non-blocking.
We in our projects decided while not to move to new version, waiting for clear and fully understandable documentation about migration (at least last month it was not full and not fully understandable).

Apply further configuration to Jackson2ObjectMapperBuilder before it is used

SpringBoot comes with its own pre-configured Jackson2ObjectMapperBuilder that is used through the framework to configure the various ObjectMapper.
The builder doesn't expose all facets of the ObjectMapper and I was wondering how I could apply additional configuration to the builder before it is used?
I can obviously provide my own Jackson2ObjectMapperBuilder instance but then I would loose the default initialisation provided by SpringBoot...
Is there another way?
Create beans that extend com.fasterxml.jackson.databind.module.SimpleModule,
there you configure for example your own seriealizers and deserializers.
In the newer spring versions (dont know since when but at least since spring 4 ) these beans are picked up automatically.
In older versions of spring you may need to add the Modules manually to the ObjectMapper, which is tricky, because spring creates many beans of type ObjetMapper and its not easy to find the right one.

Spring transaction support in Netty handlers

I am using the following versions:
Spring 3.1.1.RELEASE
Netty 3.4.0.Final
Hibernate 3.5.6-Final
Now, I have a Netty server that works fairly well - the root of the server, the pipeline factories and the base "stub" of the server that owns everything are all set up with Spring. In this stub, spring #Transactional annotations work just fine.
However, in the handlers, which are stateful and created dynamically depending on what state the user is in - #Transactional doesn't work. I'm fairly sure I understand why. I even have a "solution" - but it's not very good.
After the decoders and encoders, I add an ExecutionHandler:
pipeline.addLast("execution", new ExecutionHandler(new OrderedMemoryAwareThreadPoolExecutor(16,1000000, 1000000)));
This appears to be where the Spring transaction support is breaking. Since Spring is unaware of these threads, it can't bind any transactions to them. The classes are proxied correctly, but in debug they have no associated transactions.
My solution is crappy, and it needs to be replaced by a real solution:
Session sess = SessionFactoryUtils.getSession(getSessionFactory(), true);
That's bad because it relies on me to release the session, and it may not even be transactional, I haven't checked. It sucks in a lot of ways.
Anyway - the root of the question. Given the above tech, what's my path to getting my #Transactional notations working on the Netty handlers?
Write an ExecutionHandler that's Spring aware?
NOTE: I can't upgrade to Hibernate 4, due to lack of compatibility with Spring-Flex, used in another project in the group. Probably the same story for the Spring version, can't remember.
I suggest you create these netty's handler inside spring container and inject the service or persistence layer into the handlers so you can have these layers independence from netty and of course these are old school spring beans.

in Spring, what is the best way to dynamically create different objects of a certain class, each object being able to access a Spring bean?

Say I have a file with each line depicting a different command (but of the same kind), which I want to read out and check and run and maybe do other operations such as merging, comparing and most importantly, store the commands into database.
To do that, I create the Command Class, and new a new Command object while reading each line of the file. Now the problem is, a Command object need to make use of, say a Spring bean which provides database access. As a result, I have to pass in that bean as a constructor argument of the Command class, which is very ugly, which doesn't seem to be the "Spring way"...
and I don't want to use ApplicationContextAware to make my class coupled to the Spring context.
Is there a best practice for this situation?
I very new to Spring and I know it might be a dumb question ...
I would create a CommandFactory that is coupled with spring and use that in your consumer instead. If the factory implements an interface you are not coupling yourself in the consumer and you don't close your possibilities of using a different -non spring coupled- one at a later point (e.g. testing).
In this case I think it is the best way to make the classes created by new Spring Beans.
Therefor annotate them with #Configurable, enable AspectJ, and read the Spring Reference Chapter 7.8.1 Using AspectJ to dependency inject domain objects with Spring

Resources