HTTP Async Transport

Stable • Since 1.1.0

Implement async SOAP Clients using Apache HttpComponents HttpClient 5.

Maven coordinates

Create a new project using quarkus-cxf-rt-transports-http-hc5 on code.quarkus.io or add these coordinates to your existing project:

<dependency>
    <groupId>io.quarkiverse.cxf</groupId>
    <artifactId>quarkus-cxf-rt-transports-http-hc5</artifactId>
</dependency>

Check the User guide and especially its Dependency management section for more information about writing applications with Quarkus CXF.

Usage

Once the quarkus-cxf-rt-transports-http-hc5 dependency is available in the classpath, CXF will use HttpAsyncClient for asynchronous calls and will continue using HttpURLConnection for synchronous calls.

Generate async methods

Asynchronous client invocations require some additional methods in the service endpoint interface. That code is not generated by default.

To enable it, you need to create a JAX-WS binding file with enableAsyncMapping set to true:

The sample code snippets used in this section come from the HC5 integration test in the source tree of Quarkus CXF

src/main/resources/wsdl/async-binding.xml
<?xml version="1.0"?>
<bindings
        xmlns:xsd="http://www.w3.org/2001/XMLSchema"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
        xmlns="https://jakarta.ee/xml/ns/jaxws"
        wsdlLocation="CalculatorService.wsdl">
    <bindings node="wsdl:definitions">
        <enableAsyncMapping>true</enableAsyncMapping>
    </bindings>
</bindings>

This file should then be passed to wsdl2java through its additional-params property:

application.properties
quarkus.cxf.codegen.wsdl2java.includes = wsdl/*.wsdl
quarkus.cxf.codegen.wsdl2java.additional-params = -b,src/main/resources/wsdl/async-binding.xml

Asynchronous Clients and Mutiny

Once the asynchronous stubs are available, it is possible to wrap a client call in io.smallrye.mutiny.Uni as shown below:

package io.quarkiverse.cxf.hc5.it;

import java.util.concurrent.Future;

import jakarta.inject.Inject;
import jakarta.ws.rs.GET;
import jakarta.ws.rs.Path;
import jakarta.ws.rs.Produces;
import jakarta.ws.rs.QueryParam;
import jakarta.ws.rs.core.MediaType;

import org.jboss.eap.quickstarts.wscalculator.calculator.AddResponse;
import org.jboss.eap.quickstarts.wscalculator.calculator.CalculatorService;

import io.quarkiverse.cxf.annotation.CXFClient;
import io.smallrye.mutiny.Uni;

@Path("/hc5")
public class Hc5Resource {

    @Inject
    @CXFClient("myCalculator") // name used in application.properties
    CalculatorService myCalculator;

    @SuppressWarnings("unchecked")
    @Path("/add-async")
    @GET
    @Produces(MediaType.TEXT_PLAIN)
    public Uni<Integer> addAsync(@QueryParam("a") int a, @QueryParam("b") int b) {
        return Uni.createFrom()
                .future(
                        (Future<AddResponse>) myCalculator
                                .addAsync(a, b, res -> {
                                }))
                .map(addResponse -> addResponse.getReturn());
    }

}

Thread pool

Asynchronous clients delivered by this extension leverage ManagedExecutor with a thread pool provided by Quarkus. The thread pool can be configured using the quarkus.thread-pool.* family of options. As a consequence of this, the executor and thread pool related attributes of org.apache.cxf.transports.http.configuration.HTTPClientPolicy are not honored for async clients on Quarkus.

You can see more details about the CXF asynchronous client and how to tune it further in CXF documentation.