pool of connection with org.eclipse.microprofile.rest.client

668 views
Skip to first unread message

yeyetiti

unread,
Jun 7, 2018, 9:36:33 AM6/7/18
to Thorntail
Hi everybody,

I would like to know if it was possible to create a client (org.eclipse.microprofile.rest.client) with a pool of connection.
I have created my client as follow:
Client client = RestClientBuilder.newBuilder()
.baseUrl(url)
.build(Client.class);

But it is a single connection client...

Thanks for your feedbacks!

Ken Finnigan

unread,
Jun 7, 2018, 9:40:44 AM6/7/18
to Thorntail
Does JAX-RS Client provide a way to create a connection pool?

If it does, then there's probably a way to make it work for REST Client as well.

Martin Kouba

unread,
Jun 7, 2018, 9:55:58 AM6/7/18
to Thorntail, Ken Finnigan
Dne 7.6.2018 v 15:40 Ken Finnigan napsal(a):
> Does JAX-RS Client provide a way to create a connection pool?

I don't think there's a portable way to do this.

In resteasy (JAX-RS impl used by thorntail) it's possible to change the
default bahaviour by using
org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder.connectionPoolSize(int).

However, if using MP Rest Client APIs you can't really use this method.
Therefore, in Thorntail 2.0.0 you will be able to change the defaults
like this:
https://github.com/thorntail/thorntail/blob/master/testsuite/testsuite-microprofile-restclient/src/test/java/org/wildfly/swarm/microprofile/restclient/ft/FaultToleranceTest.java#L175

Martin

>
> If it does, then there's probably a way to make it work for REST Client
> as well.
>
> On Thursday, June 7, 2018 at 9:36:33 AM UTC-4, yeyetiti wrote:
>
> Hi everybody,
>
> I would like to know if it was possible to create a client
> (org.eclipse.microprofile.rest.client) with a pool of connection.
> I have created my client as follow:
> Client client = RestClientBuilder.newBuilder()
> .baseUrl(url)
> .build(Client.class);
>
> But it is a single connection client...
>
> Thanks for your feedbacks!
>
> --
> You received this message because you are subscribed to the Google
> Groups "Thorntail" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to thorntail+...@googlegroups.com
> <mailto:thorntail+...@googlegroups.com>.
> To post to this group, send email to thor...@googlegroups.com
> <mailto:thor...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/thorntail/9205a5c0-863e-4cd1-8563-d06bac33b516%40googlegroups.com
> <https://groups.google.com/d/msgid/thorntail/9205a5c0-863e-4cd1-8563-d06bac33b516%40googlegroups.com?utm_medium=email&utm_source=footer>.
> For more options, visit https://groups.google.com/d/optout.

--
Martin Kouba
Senior Software Engineer
Red Hat, Czech Republic

Werner Keil

unread,
Jun 7, 2018, 10:13:21 AM6/7/18
to Thorntail
Hopefully some day these could end up in a future Jakarta EE Rest standard, then there could be a portable way to do this.

Werner

yeyetiti

unread,
Jun 11, 2018, 11:57:27 AM6/11/18
to Thorntail
Thanks Martin for your answer.
I am precisely trying to implement your solution by helping me with this tutorial:

And I am facing an issue while running the command java -jar my-swarm-app.jar.
Here is the stackTrace of the error:

==========================================================
======================== Error StackTrace ====================
==========================================================
2018-06-11 16:36:40,795 INFO  [org.jboss.weld.Bootstrap] (Weld Thread Pool -- 1) WELD-000119: Not generating any bean definitions from com.mydomain.prf.flex.client.ResteasyTripClient because of underlying class loading error: Type org.apache.http.conn.HttpClientConnectionManager from [Module "deployment.flex.war" from Service Module Loader] not found.  If this is unexpected, enable DEBUG logging to see the full error.
2018-06-11 16:36:42,452 ERROR [org.jboss.msc.service.fail] (MSC service thread 1-6) MSC000001: Failed to start service jboss.deployment.unit."flex.war".WeldStartService: org.jboss.msc.service.StartException in service jboss.deployment.unit."flex.war".WeldStartService: Failed to start service
        at org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1978)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type TripClient with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject com.mydomain.prf.flex.mdw.Exporter.tripClient
  at com.mydomain.prf.flex.mdw.Exporter.tripClient(Exporter.java:0)

        at org.jboss.weld.bootstrap.Validator.validateInjectionPointForDeploymentProblems(Validator.java:362)
        at org.jboss.weld.bootstrap.Validator.validateInjectionPoint(Validator.java:284)
        at org.jboss.weld.bootstrap.Validator.validateGeneralBean(Validator.java:137)
        at org.jboss.weld.bootstrap.Validator.validateRIBean(Validator.java:158)
        at org.jboss.weld.bootstrap.Validator.validateBean(Validator.java:501)
        at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:61)
        at org.jboss.weld.bootstrap.ConcurrentValidator$1.doWork(ConcurrentValidator.java:59)
        at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:62)
        at org.jboss.weld.executor.IterativeWorkerTaskFactory$1.call(IterativeWorkerTaskFactory.java:55)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
        at java.lang.Thread.run(Thread.java:745)
        at org.jboss.threads.JBossThread.run(JBossThread.java:320)

2018-06-11 16:36:42,477 ERROR [org.jboss.as.controller.management-operation] (main) WFLYCTL0013: Operation ("add") failed - address: (("deployment" => "flex.war")) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"flex.war\".WeldStartService" => "Failed to start service
    Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type TripClient with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject com.mydomain.prf.flex.mdw.Exporter.tripClient
  at com.mydomain.prf.flex.mdw.Exporter.tripClient(Exporter.java:0)
"}}
2018-06-11 16:36:42,490 ERROR [org.jboss.as.server] (main) WFLYSRV0021: Deploy of deployment "flex.war" was rolled back with the following failure message:
{"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"flex.war\".WeldStartService" => "Failed to start service
    Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type TripClient with qualifiers @Default
  at injection point [BackedAnnotatedField] @Inject com.mydomain.prf.flex.mdw.Exporter.tripClient
  at com.mydomain.prf.flex.mdw.Exporter.tripClient(Exporter.java:0)
"}}
2018-06-11 16:36:42,681 INFO  [org.wildfly.extension.undertow] (MSC service thread 1-4) WFLYUT0019: Host default-host stopping
2018-06-11 16:36:44,379 INFO  [org.jboss.as.server.deployment] (MSC service thread 1-4) WFLYSRV0028: Stopped deployment flex.war (runtime-name: flex.war) in 1892ms
2018-06-11 16:36:44,445 ERROR [stderr] (main) org.wildfly.swarm.container.DeploymentException: org.wildfly.swarm.container.DeploymentException: WFSWARM0004: Deployment failed: {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"flex.war\".WeldStartService" => "Failed to start service
2018-06-11 16:36:44,445 ERROR [stderr] (main)     Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type TripClient with qualifiers @Default
2018-06-11 16:36:44,446 ERROR [stderr] (main)   at injection point [BackedAnnotatedField] @Inject com.mydomain.prf.flex.mdw.Exporter.tripClient
2018-06-11 16:36:44,446 ERROR [stderr] (main)   at com.mydomain.prf.flex.mdw.Exporter.tripClient(Exporter.java:0)
2018-06-11 16:36:44,446 ERROR [stderr] (main) "}}
2018-06-11 16:36:44,446 ERROR [stderr] (main)   at org.wildfly.swarm.container.runtime.RuntimeDeployer.deploy(RuntimeDeployer.java:301)
2018-06-11 16:36:44,447 ERROR [stderr] (main)   at org.wildfly.swarm.container.runtime.RuntimeDeployer.deploy(RuntimeDeployer.java:174)
2018-06-11 16:36:44,447 ERROR [stderr] (main)   at org.wildfly.swarm.container.runtime.RuntimeDeployer.deploy(RuntimeDeployer.java:107)
2018-06-11 16:36:44,447 ERROR [stderr] (main)   at org.wildfly.swarm.container.runtime.RuntimeDeployer$Proxy$_$$_WeldClientProxy.deploy(Unknown Source)
2018-06-11 16:36:44,454 ERROR [stderr] (main)   at org.wildfly.swarm.Swarm.deploy(Swarm.java:473)
2018-06-11 16:36:44,455 ERROR [stderr] (main)   at org.wildfly.swarm.Swarm.main(Swarm.java:744)
2018-06-11 16:36:44,457 ERROR [stderr] (main)   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
2018-06-11 16:36:44,457 ERROR [stderr] (main)   at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
2018-06-11 16:36:44,457 ERROR [stderr] (main)   at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
2018-06-11 16:36:44,457 ERROR [stderr] (main)   at java.lang.reflect.Method.invoke(Method.java:498)
2018-06-11 16:36:44,457 ERROR [stderr] (main)   at org.wildfly.swarm.bootstrap.MainInvoker.invoke(MainInvoker.java:53)
2018-06-11 16:36:44,458 ERROR [stderr] (main)   at org.wildfly.swarm.bootstrap.Main.run(Main.java:132)
2018-06-11 16:36:44,459 ERROR [stderr] (main)   at org.wildfly.swarm.bootstrap.Main.main(Main.java:85)
2018-06-11 16:36:44,461 ERROR [stderr] (main) Caused by: org.wildfly.swarm.container.DeploymentException: WFSWARM0004: Deployment failed: {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"flex.war\".WeldStartService" => "Failed to start service
2018-06-11 16:36:44,461 ERROR [stderr] (main)     Caused by: org.jboss.weld.exceptions.DeploymentException: WELD-001408: Unsatisfied dependencies for type TripClient with qualifiers @Default
2018-06-11 16:36:44,461 ERROR [stderr] (main)   at injection point [BackedAnnotatedField] @Inject com.mydomain.prf.flex.mdw.Exporter.tripClient
2018-06-11 16:36:44,461 ERROR [stderr] (main)   at com.mydomain.prf.flex.mdw.Exporter.tripClient(Exporter.java:0)
2018-06-11 16:36:44,461 ERROR [stderr] (main) "}}
2018-06-11 16:36:44,462 ERROR [stderr] (main)   at org.wildfly.swarm.container.runtime.RuntimeDeployer.deploy(RuntimeDeployer.java:296)
2018-06-11 16:36:44,462 ERROR [stderr] (main)   ... 12 more



Here is the situation:
Below is a class (Exporter.java) that uses a client (TripClient ) to make rest-calls on a Rest-API.
I inject this client using CDI's @Inject annotation.
The for loop in the function collect() loops over a List<Simulation> simulations that contains hundreds of elements such that it would be better to have a client provided with a pool of connections.

==========================================================
========================= Exporter.java ======================
==========================================================
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import org.eclipse.microprofile.config.inject.ConfigProperty;

@RequestScoped
public class Exporter extends Collector {

@Inject private Importer importer;

@Inject
@ConfigProperty(name = "tripUrl", defaultValue = "")
String tripUrl;
@Inject
TripClient tripClient;

@Override
public List<MetricFamilySamples> collect() {
List<Simulation> simulations = getSimulations();
for(Simulation s : simulations) {
campaignName = tripClient.getCampaignNameBySimulationId(simulationId);
// ...do something with campaignName...//
}
}
}

Thanks to the CDI's @Inject annotation, CDI looks for a method annotated with the CDI's @Produces annotation that returns an object of type TripClient.
This @Produces annotated method is named getTripClient() and is contained in the class ResteasyTripClient

This ResteasyTripClient class sets a pool of connections on the rest TripClient client.
This pool of connections is configured using:
    - org.apache.http.impl.conn.PoolingHttpClientConnectionManager
    - org.apache.http.impl.client.CloseableHttpClient
    - org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine

==========================================================
========= ResteasyTripClient.java ==== pool of connections ==========
==========================================================
@ApplicationScoped
public class ResteasyTripClient {
@Inject
@ConfigProperty(name = "tripUrl", defaultValue = "")
String tripUrl;

private ResteasyClient client;
private ResteasyWebTarget target;
private TripClient tripClient;
@Produces
public TripClient getTripClient() {

if (tripClient == null) {
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(cm).build();
cm.setMaxTotal(200); // Increase max total connection to 200
cm.setDefaultMaxPerRoute(20); // Increase default max connection per route to 20
ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient);
client = new ResteasyClientBuilder().httpEngine(engine).build();
target = client.target(UriBuilder.fromPath(tripUrl));
tripClient = target.proxy(TripClient.class);
}

return tripClient;
}
}

And finally, here is the TripClient:
==========================================================
===================== ResteasyTripClient.java ==================
==========================================================
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;

@Path("/simulations")
public interface TripClient {
@GET
@Path("/externalReference/{extRefId}")
String getCampaignNameBySimulationExtRefId(@PathParam("extRefId") String extRefId);

}

Be aware that when I do not try to create a pool of connection on TripClient, the command java -jar my-swarm-app.jar works and my app behaves well (but slowly due to the single connection client)
Below is the single connection version of  ResteasyTripClient class:
==========================================================
========= ResteasyTripClient.java ====== single connection ==========
==========================================================
@ApplicationScoped
public class ResteasyTripClient {
@Inject
@ConfigProperty(name = "tripUrl", defaultValue = "")
String tripUrl;

private ResteasyClient client;
private ResteasyWebTarget target;
private TripClient tripClient;
@Produces
public TripClient getTripClient() {

if (tripClient == null) {
client = new ResteasyClientBuilder().build();
target = client.target(UriBuilder.fromPath(tripUrl));
tripClient = target.proxy(TripClient.class);
}

return tripClient;
}
}

What is the problem?

Thanks for potential answers!

Regards

Jérôme

Martin Kouba

unread,
Jun 13, 2018, 4:18:28 AM6/13/18
to yeyetiti, Thorntail
Hm, verify that @Produces used on getTripClient() is
"javax.enterprise.inject.Produces" and not "javax.ws.rs.Produces".

Dne 11.6.2018 v 17:57 yeyetiti napsal(a):
> The forloop in the function collect() loops over a List<Simulation>
> --
> You received this message because you are subscribed to the Google
> Groups "Thorntail" group.
> To unsubscribe from this group and stop receiving emails from it, send
> an email to thorntail+...@googlegroups.com
> <mailto:thorntail+...@googlegroups.com>.
> To post to this group, send email to thor...@googlegroups.com
> <mailto:thor...@googlegroups.com>.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/thorntail/8ccc6ec5-2e9e-43c2-b08d-5a21539fd22a%40googlegroups.com
> <https://groups.google.com/d/msgid/thorntail/8ccc6ec5-2e9e-43c2-b08d-5a21539fd22a%40googlegroups.com?utm_medium=email&utm_source=footer>.
Reply all
Reply to author
Forward
0 new messages