How to configure rest client in quarkus microprofile case - quarkus

When using Quarkus microprofile as a rest client, how can I configure underlying HttpClient?
Like number of retries, connection pool size per host and so on?
Also is it possible to force client restart somehow (so connections pool will be restarted)?

https://download.eclipse.org/microprofile/microprofile-rest-client-2.0-RC2/microprofile-rest-client-2.0-RC2.html#_configuration_keys outlines the full set of configuration keys that can be used.
The ones you're looking for are:
{packageName}.{interfaceName}/mp-rest/connectTimeout
{packageName}.{interfaceName}/mp-rest/readTimeout
The RestClientBuilder also has methods for setting those properties if you're using the programmatic API instead of the CDI approach.
I'm not aware of any means of restarting the underlying HTTP client connection pool. What would be the use case for such a situation that doesn't require the whole application to be restarted?

So... After a lot of digging, here is a solution I've found so far. It is not obvious apparently:
To make it work in pure Java (no native)
Under resources/META-INF/services directory add file named org.eclipse.microprofile.rest.client.spi.RestClientBuilderListener containing class name of your implementation of RestClientBuilderListener interface. For example my.test.MyBuilderListener. This will allow ServiceLocator to execute your listener
Refer a property you want to modify from ResteasyClientBuilder, for example to set your custom value to connectionTTL code will looks like this:
public void onNewBuilder(RestClientBuilder builder) {
log.info("Changing TTL for connections");
builder.property("resteasy.connectionTTL", List.of(2L, TimeUnit.SECONDS));
}
Ie. add a resteasy. prefix to a property name
Profit
Now native support:
After steps above:
Set both MyBuildListener and ResteasyClientBuilder available for reflection by creating a file reflection-config.json:
[
{
"name": "org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
}, {
"name": "my.test.MyBuilderListener",
"allDeclaredConstructors": true,
"allPublicConstructors": true,
"allDeclaredMethods": true,
"allPublicMethods": true,
"allDeclaredFields": true,
"allPublicFields": true
}
]
Add service registration file to resources. Create a file named resources-config.json with content
{
"resources": [
{
"pattern": "META-INF/services/org\\.eclipse\\.microprofile\\.rest\\.client\\.spi\\.RestClientBuilderListener$"
}
]
}
register both files in application.yaml:
quarkus:
native:
additional-build-args: -H:ResourceConfigurationFiles=resources-config.json, -H:ReflectionConfigurationFiles=reflection-config.json
Native profit
Have fun

Related

Ocelot QoS doesn't break circuit when n number of exception arises

I am carrying out a PoC on Ocelot Gateway to use for our microservices architecture. I have successfully used the Gateway to perform all the routing tasks uptil now.
It provides a QoS Service that helds configuration in ocelot.json for circuit breaker and breaks the circuit for a duration.
The configurations set in my ocelot.json file are as follows for a specific route:
{
"DownstreamPathTemplate": "/api/classes/exception/{id}",
"DownstreamScheme": "http",
"UpstreamPathTemplate": "/classes/exception/{id}",
"ServiceName": "class-service",
"UpstreamHttpMethod": [ "Get" ],
"LoadBalancerOptions": {
"Type": "LeastConnection"
},
"QoSOptions": {
"ExceptionsAllowedBeforeBreaking": 2,
"DurationOfBreak": 10000,
"TimeoutValue": 3000
}
}
Now, this works fine for the timeout issue, it breaks the circuit for 10s when the route does not respond in 3s.
But for the exception case, it does not break the circuit when there is an exception arising for 2 times when the route is being called.
Are there any more configurations required?
I have added Nuget Package for Ocelot and Ocelot.Provider.Polly and also added the following in my Startup.cs file:
s.AddOcelot().AddPolly();
Please help me through this.
I have followed the [Ocelot Documentation] https://ocelot.readthedocs.io/en/latest/features/qualityofservice.html to implement this

Hide details for health indicators in Spring Boot Actuator

I'm using Spring Boot health indicator from an actuator. So far example response looks like:
{
"status":"DOWN",
"details": {
"diskSpace": {
"status":"UP",
"details": {
"total":499963170816,
"free":250067189760,
"threshold":10485760
}
}
}
}
Because I need to make /actuator/health endpoint public, I need to hide details for health indicators, so I expect to get something like this:
{
"status":"DOWN",
"details": {
"diskSpace": {
"status":"UP"
}
}
}
For disk space it's not a big problem but e.g. for database I don't want to share exception message and details in case of it's outage. Also (as I mentioned at the beginning) it must be public so I don't want to make this endpoint 'when-authorized'. And at the end - it would be great if it's possible to do that without writing my own custom endpoint.
Is it possible at all?
This isn't possible at the time of writing (in Spring Boot 2.1 and earlier) without writing your own custom endpoint. I've opened an issue to consider it as an enhancement for a future version of Spring Boot.
There is a way to achieve this in Spring Boot 2.X
management:
health:
db:
enabled: false
diskspace:
enabled: false
mongo:
enabled: false
refresh:
enabled: false
More information can be found here https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html#_auto_configured_healthindicators

Cannot fire Bigcommerce webhooks

so far I've managed to create two webhooks by using their official gem (https://github.com/bigcommerce/bigcommerce-api-ruby) with the following events:
store/order/statusUpdated
store/app/uninstalled
The destination URL is a localhost tunnel managed by ngrok (the https) version.
status_update_hook = Bigcommerce::Webhook.create(connection: connection, headers: { is_active: true }, scope: 'store/order/statusUpdated', destination: 'https://myapp.ngrok.io/bigcommerce/notifications')
uninstall_hook = Bigcommerce::Webhook.create(connection: connection, headers: { is_active: true }, scope: 'store/app/uninstalled', destination: 'https://myapp.ngrok.io/bigcommerce/notifications')
The webhooks seems to be active and correctly created as I can retrieve and list them.
Bigcommerce::Webhook.all(connection:connection)
I manually created an order in my store dashboard but no matter to which state or how many states I change it, no notification is fired. Am I missing something?
The exception that I'm seeing in the logs is:
ExceptionMessage: true is not a valid header value
The "is-active" flag should be sent as part of the request body--your headers, if you choose to include them, would be an arbitrary key value pair that you can check at runtime to verify the hook's origin.
Here's an example request body:
{
"scope": "store/order/*",
"headers": {
"X-Custom-Auth-Header": "{secret_auth_password}"
},
"destination": "https://app.example.com/orders",
"is_active": true
}
Hope this helps!

Change to desiredCapabilities in beforeEach not reflecting

I am trying to record all browser request and responses. This can be done via browsermob-proxy api's.
For this, I have to change desired capabilities and change httpProxy for browser.
In beforeEach at global or file level, I am trying to change this. Though it reflects in browser object, actual browser is not initiated with those settings.
Simple example:
globalhook file
module.exports = {
before : function (done) {
},
beforeEach: function(browser, done){
browser.options.desiredCapabilities = {
"browserName": "chrome",
"proxy": {
"proxyType": "manual",
"httpProxy": "127.0.0.1:" + someport,
"sslProxy": "127.0.0.1:" + someport
},
"javascriptEnabled": true,
"acceptSslCerts": true,
}
done()
},
afterEach: function(browser, done){
//some code
}
after : function (done) {
//some code
},
}
If i change desired capabilities in before hook, chrome browser is taking those changes. Problem is with beforeEach [global, file level].
Further debugging, I've found setCapabilities function is run just before beforeEach Hook.
Could anyone please have a look or suggest if I am doing something wrong.
Thanks for moving the issue here.
The issue is that the desiredCapabilities are applied to a browser session.
beforeEach and afterEach run on the same browser session therefore any change in the desiredCapabilities won't be applied unless the session is restarted.
If you need to dynamically change the desiredCapabilities you have to structure your tests in the different way, e.g. split your tests in separate test classes
First of all, you probably want to use before() hook instead of beforeEach(), since beforeEach() will run before each test case and you won't be able to modify already started browser session. before() will run before browser session is initiated.
To solve your issue you need to define desiredCapabilities property on your test run module and in case you need to set some dynamic values, use before() hook to modify that object:
module.exports = {
desiredCapabilities: {
"browserName": "chrome",
"proxy": {
"proxyType": "manual",
"httpProxy": "127.0.0.1",
"sslProxy": "127.0.0.1"
},
"javascriptEnabled": true,
"acceptSslCerts": true,
},
before: function(client, done) {
this.desiredCapabilities.proxy.sslProxy = '127.0.0.1' + someport;
done();
}
}
I've searched official docs on this feature but couldn't find anything, though we used this in our tests and it worked well.
Update:
Since you only need to change proxy on desiredCapabilities object, there is a little hack:
// global hooks file:
module.exports = {
beforeEach: function(client, done) {
client.options.desiredCapabilities.proxy = {
"proxyType": "manual",
"httpProxy": "127.0.0.1:" + someport,
"sslProxy": "127.0.0.1:" + someport
};
done(client);
}
};
Changing desiredCapabilities object won't work, since reference to original object is already stored somewhere under the hood of Nightwatch. But nothing stops you from overriding proxy property on that object.
After checking sources and tests in Nightwatch I believe this is the only solution for your case.

Can't change session service name in torii

I'm using ember-simple-auth and emberfire to authenticate users on my app. One thing I don't like about the defaults is that there is both a "session" service and a "session" object on the service. So, I opened config/environment.js and changed:
var Env = {
torii: {
sessionServiceName: 'session',
providers: {
'firebase-simple-auth': {}
}
}
...
to
var Env = {
torii: {
sessionServiceName: 'auth',
providers: {
'firebase-simple-auth': {}
}
}
...
But, the newly named "auth" service doesn't have the "invalidate" and "authenticate" methods. Those are still on the "session" service (which I'm surprised is still around).
How do I move the entire "session" service over to an "auth" service?
Thanks!
You are configuring torii, not ESA. When you use the 2 in combination though you're not actually using torii's session at all. Ember Simple Auth's session service cannot be renamed but that's also not necessary anyway as you explicitly inject it anyway and can specify a custom name when doing so.

Resources