Dynamic client configuration

Sometimes you need to reconfigure the client after the application has been started, or even before every request. This might be the case, if, for example, each request needs to be sent to a different remote URL.

CXF offers an API to set the URL of the remote endpoint. However using that API on a client instance that may be accessed from other threads can lead to race conditions.

Preventing concurrent access to a CXF client

If your client is used as a part of serving an external request, you can inject the client into a @RequestScoped bean. Then every request will be served by a fresh client instance and you can configure it safely.

For example, this solution is applicable when your client is called from a REST-handler method (see below) or from a @WebMethod that are serving external requests.

package io.quarkiverse.cxf.client.it;

import java.util.Map;

import jakarta.enterprise.context.RequestScoped;
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 jakarta.xml.ws.BindingProvider;

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

import io.quarkiverse.cxf.annotation.CXFClient;

/*
 * The @RequestScoped annotation causes that the REST resource is instantiated
 * anew for every call of the add() method. Therefore also a new client instance
 * is injected into the calculator field for every request served by add().
 */
@RequestScoped
@Path("/cxf/dynamic-client")
public class DynamicClientConfigRestResource {

    @CXFClient("requestScopedVertxHttpClient")
    CalculatorService calculator;

    @GET
    @Path("/add")
    @Produces(MediaType.TEXT_PLAIN)
    public int add(@QueryParam("a") int a, @QueryParam("b") int b, @QueryParam("baseUri") String baseUri) {
        Map<String, Object> ctx = ((BindingProvider) calculator).getRequestContext();
        /* We are setting the remote URL safely, because the client is associated exclusively with the current request */
        ctx.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, baseUri + "/calculator-ws/CalculatorService");
        return calculator.add(a, b);
    }

}