diff --git a/docs/modules/ROOT/pages/includes/quarkus-cxf.adoc b/docs/modules/ROOT/pages/includes/quarkus-cxf.adoc
index 4107e6922..589b012d3 100644
--- a/docs/modules/ROOT/pages/includes/quarkus-cxf.adoc
+++ b/docs/modules/ROOT/pages/includes/quarkus-cxf.adoc
@@ -250,6 +250,24 @@ endif::add-copy-button-to-env-var[]
|`%CLASSES_DIR%/wsdl/%SIMPLE_CLASS_NAME%.wsdl`
+a|icon:lock[title=Fixed at build time] [[quarkus-cxf_quarkus.cxf.http-conduit-factory]]`link:#quarkus-cxf_quarkus.cxf.http-conduit-factory[quarkus.cxf.http-conduit-factory]`
+
+
+[.description]
+--
+If not set or set to `DefaultHTTPConduitFactory`, the selection of `HTTPConduitFactory` implementation will be left to CXF. If set to `URLConnectionHTTPConduitFactory`, the `HTTPConduitFactory` for the CXF Bus will be set to an implementation returning `org.apache.cxf.transport.http.URLConnectionHTTPConduit` - this is equivalent to setting `org.apache.cxf.transport.http.forceURLConnection` system property to `true` in CXF 4.0.3{plus}. Using the `URLConnectionHTTPConduitFactory` value in combination with `io.quarkiverse.cxf:quarkus-cxf-rt-transports-http-hc5` causes a build time error.
+
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CXF_HTTP_CONDUIT_FACTORY+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CXF_HTTP_CONDUIT_FACTORY+++`
+endif::add-copy-button-to-env-var[]
+-- a|
+`DefaultHTTPConduitFactory`, `URLConnectionHTTPConduitFactory`
+|`default-http-conduit-factory`
+
+
a|icon:lock[title=Fixed at build time] [[quarkus-cxf_quarkus.cxf.codegen.wsdl2java.-named-parameter-sets-.includes]]`link:#quarkus-cxf_quarkus.cxf.codegen.wsdl2java.-named-parameter-sets-.includes[quarkus.cxf.codegen.wsdl2java."named-parameter-sets".includes]`
@@ -1329,4 +1347,22 @@ endif::add-copy-button-to-env-var[]
--|string
|
+
+a| [[quarkus-cxf_quarkus.cxf.client.-clients-.http-conduit-factory]]`link:#quarkus-cxf_quarkus.cxf.client.-clients-.http-conduit-factory[quarkus.cxf.client."clients".http-conduit-factory]`
+
+
+[.description]
+--
+If not set or set to `DefaultHTTPConduitFactory`, the selection of `HTTPConduitFactory` implementation will be left to CXF; if set to `URLConnectionHTTPConduitFactory`, the `HTTPConduitFactory` for this client will be set to an implementation returning `org.apache.cxf.transport.http.URLConnectionHTTPConduit`.
+
+ifdef::add-copy-button-to-env-var[]
+Environment variable: env_var_with_copy_button:+++QUARKUS_CXF_CLIENT__CLIENTS__HTTP_CONDUIT_FACTORY+++[]
+endif::add-copy-button-to-env-var[]
+ifndef::add-copy-button-to-env-var[]
+Environment variable: `+++QUARKUS_CXF_CLIENT__CLIENTS__HTTP_CONDUIT_FACTORY+++`
+endif::add-copy-button-to-env-var[]
+-- a|
+`DefaultHTTPConduitFactory`, `URLConnectionHTTPConduitFactory`
+|`default-http-conduit-factory`
+
|===
\ No newline at end of file
diff --git a/extensions/core/deployment/src/main/java/io/quarkiverse/cxf/deployment/CxfBuildTimeConfig.java b/extensions/core/deployment/src/main/java/io/quarkiverse/cxf/deployment/CxfBuildTimeConfig.java
index 7c1b8d3d1..eb8985360 100644
--- a/extensions/core/deployment/src/main/java/io/quarkiverse/cxf/deployment/CxfBuildTimeConfig.java
+++ b/extensions/core/deployment/src/main/java/io/quarkiverse/cxf/deployment/CxfBuildTimeConfig.java
@@ -4,6 +4,7 @@
import java.util.Map;
import java.util.Optional;
+import io.quarkiverse.cxf.CxfClientConfig.HTTPConduitImpl;
import io.quarkus.runtime.annotations.ConfigGroup;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConfigPhase;
@@ -43,6 +44,18 @@ public class CxfBuildTimeConfig {
@ConfigItem(name = "java2ws")
public Java2WsConfig java2ws;
+ /**
+ * If not set or set to {@code DefaultHTTPConduitFactory}, the selection of {@code HTTPConduitFactory} implementation will
+ * be left to CXF.
+ * If set to {@code URLConnectionHTTPConduitFactory}, the {@code HTTPConduitFactory} for the CXF Bus will be set to an
+ * implementation returning {@code org.apache.cxf.transport.http.URLConnectionHTTPConduit} - this is equivalent to
+ * setting {@code org.apache.cxf.transport.http.forceURLConnection} system property to {@code true} in CXF 4.0.3+.
+ * Using the {@code URLConnectionHTTPConduitFactory} value in combination with
+ * {@code io.quarkiverse.cxf:quarkus-cxf-rt-transports-http-hc5} causes a build time error.
+ */
+ @ConfigItem(defaultValue = "DefaultHTTPConduitFactory")
+ public HTTPConduitImpl httpConduitFactory;
+
@ConfigGroup
public static class CodeGenConfig {
diff --git a/extensions/core/deployment/src/main/java/io/quarkiverse/cxf/deployment/CxfClientProcessor.java b/extensions/core/deployment/src/main/java/io/quarkiverse/cxf/deployment/CxfClientProcessor.java
index 1efa1f092..9026c600e 100644
--- a/extensions/core/deployment/src/main/java/io/quarkiverse/cxf/deployment/CxfClientProcessor.java
+++ b/extensions/core/deployment/src/main/java/io/quarkiverse/cxf/deployment/CxfClientProcessor.java
@@ -34,6 +34,7 @@
import io.quarkiverse.cxf.CXFClientData;
import io.quarkiverse.cxf.CXFClientInfo;
import io.quarkiverse.cxf.CXFRecorder;
+import io.quarkiverse.cxf.CxfClientConfig.HTTPConduitImpl;
import io.quarkiverse.cxf.CxfClientProducer;
import io.quarkiverse.cxf.CxfFixedConfig;
import io.quarkiverse.cxf.CxfFixedConfig.ClientFixedConfig;
@@ -285,7 +286,8 @@ void generateClientProducers(
* to the user application. Why we have do that: First, the interface is package-visible so that adding it to
* the client proxy definition forces GraalVM to generate the proxy class in
* {@value CxfClientProducer#RUNTIME_INITIALIZED_PROXY_MARKER_INTERFACE_PACKAGE} package rather than under a random
- * package/class name. Thanks to that we can request the postponed initialization of the generated proxy class by package
+ * package/class name. Thanks to that we can request the postponed initialization of the generated proxy class by
+ * package
* name.
* More details in #580.
*
@@ -449,6 +451,39 @@ private void produceUnremovableBean(
.forEach(unremovables::produce);
}
+ @BuildStep
+ @Record(ExecutionTime.STATIC_INIT)
+ void customizers(
+ CXFRecorder recorder,
+ CxfBuildTimeConfig config,
+ BuildProducer customizers) {
+ switch (config.httpConduitFactory) {
+ case DefaultHTTPConduitFactory:
+ // nothing to do
+ break;
+ case URLConnectionHTTPConduitFactory:
+ try {
+ Class.forName(
+ "io.quarkiverse.cxf.transport.http.hc5.QuarkusAsyncHTTPConduitFactory.QuarkusAsyncHTTPConduitFactory");
+ /*
+ * This is bad: the user has to choose whether he wants URLConnectionHTTPConduitFactory or
+ * QuarkusAsyncHTTPConduitFactory
+ */
+ throw new RuntimeException(
+ "Cannot use quarkus.cxf.http-conduit-impl=URLConnectionHTTPConduitFactory and io.quarkiverse.cxf:quarkus-cxf-rt-transports-http-hc5 simultaneously."
+ + " Either remove quarkus.cxf.http-conduit-impl=URLConnectionHTTPConduitFactory from application.properties"
+ + " or remove the io.quarkiverse.cxf:quarkus-cxf-rt-transports-http-hc5 dependency");
+ } catch (ClassNotFoundException e) {
+ /* Fine, we can set the URLConnectionHTTPConduitFactory */
+ customizers.produce(new RuntimeBusCustomizerBuildItem(recorder.setURLConnectionHTTPConduit()));
+ }
+ break;
+ default:
+ throw new IllegalStateException("Unexpected " + HTTPConduitImpl.class.getSimpleName() + " value: "
+ + config.httpConduitFactory);
+ }
+ }
+
private static class ProxyInfo {
public static ProxyInfo of(
diff --git a/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CXFClientInfo.java b/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CXFClientInfo.java
index 91d8f4a9e..5e7ddbd09 100644
--- a/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CXFClientInfo.java
+++ b/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CXFClientInfo.java
@@ -7,6 +7,7 @@
import org.apache.cxf.transports.http.configuration.ConnectionType;
import org.apache.cxf.transports.http.configuration.ProxyServerType;
+import io.quarkiverse.cxf.CxfClientConfig.HTTPConduitImpl;
import io.quarkus.arc.Unremovable;
@Unremovable
@@ -161,6 +162,8 @@ public class CXFClientInfo {
*/
private String proxyPassword;
+ private HTTPConduitImpl httpConduitImpl;
+
public CXFClientInfo() {
}
@@ -222,6 +225,7 @@ public CXFClientInfo(CXFClientInfo other) {
this.proxyServerType = other.proxyServerType;
this.proxyUsername = other.proxyUsername;
this.proxyPassword = other.proxyPassword;
+ this.httpConduitImpl = other.httpConduitImpl;
}
public CXFClientInfo withConfig(CxfClientConfig config) {
@@ -260,6 +264,7 @@ public CXFClientInfo withConfig(CxfClientConfig config) {
this.proxyServerType = config.proxyServerType;
this.proxyUsername = config.proxyUsername.orElse(null);
this.proxyPassword = config.proxyPassword.orElse(null);
+ this.httpConduitImpl = config.httpConduitFactory;
return this;
}
@@ -460,4 +465,9 @@ public String getProxyUsername() {
public String getProxyPassword() {
return proxyPassword;
}
+
+ public HTTPConduitImpl getHttpConduitImpl() {
+ return httpConduitImpl;
+ }
+
}
diff --git a/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CXFRecorder.java b/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CXFRecorder.java
index 5aad53271..6a8b61b0a 100644
--- a/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CXFRecorder.java
+++ b/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CXFRecorder.java
@@ -9,6 +9,7 @@
import java.util.function.Consumer;
import org.apache.cxf.Bus;
+import org.apache.cxf.transport.http.HTTPConduitFactory;
import org.jboss.logging.Logger;
import io.quarkiverse.cxf.devconsole.DevCxfServerInfosSupplier;
@@ -153,4 +154,8 @@ public void resetDestinationRegistry(ShutdownContext context) {
public void addRuntimeBusCustomizer(RuntimeValue> customizer) {
QuarkusBusFactory.addBusCustomizer(customizer.getValue());
}
+
+ public RuntimeValue> setURLConnectionHTTPConduit() {
+ return new RuntimeValue<>(bus -> bus.setExtension(new URLConnectionHTTPConduitFactory(), HTTPConduitFactory.class));
+ }
}
diff --git a/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CxfClientConfig.java b/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CxfClientConfig.java
index 14f2516c6..bb814ecfe 100644
--- a/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CxfClientConfig.java
+++ b/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CxfClientConfig.java
@@ -6,6 +6,7 @@
import org.apache.cxf.transports.http.configuration.ConnectionType;
import org.apache.cxf.transports.http.configuration.ProxyServerType;
+import io.quarkus.runtime.annotations.ConfigDocEnumValue;
import io.quarkus.runtime.annotations.ConfigGroup;
import io.quarkus.runtime.annotations.ConfigItem;
import io.quarkus.runtime.annotations.ConvertWith;
@@ -266,4 +267,20 @@ public class CxfClientConfig {
@ConfigItem
public Optional proxyPassword;
+ /**
+ * If not set or set to {@code DefaultHTTPConduitFactory}, the selection of {@code HTTPConduitFactory} implementation will
+ * be left to CXF;
+ * if set to {@code URLConnectionHTTPConduitFactory}, the {@code HTTPConduitFactory} for this client will be set to an
+ * implementation returning {@code org.apache.cxf.transport.http.URLConnectionHTTPConduit}.
+ */
+ @ConfigItem(defaultValue = "DefaultHTTPConduitFactory")
+ public HTTPConduitImpl httpConduitFactory;
+
+ public enum HTTPConduitImpl {
+ @ConfigDocEnumValue("DefaultHTTPConduitFactory")
+ DefaultHTTPConduitFactory,
+ @ConfigDocEnumValue("URLConnectionHTTPConduitFactory")
+ URLConnectionHTTPConduitFactory;
+ }
+
}
diff --git a/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CxfClientProducer.java b/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CxfClientProducer.java
index 0832056cb..06f6c3ff3 100644
--- a/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CxfClientProducer.java
+++ b/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/CxfClientProducer.java
@@ -3,6 +3,7 @@
import static java.util.stream.Collectors.toList;
import java.io.Closeable;
+import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
@@ -22,9 +23,11 @@
import org.apache.cxf.interceptor.Interceptor;
import org.apache.cxf.message.Message;
import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.http.HTTPConduitFactory;
import org.apache.cxf.transports.http.configuration.HTTPClientPolicy;
import org.jboss.logging.Logger;
+import io.quarkiverse.cxf.CxfClientConfig.HTTPConduitImpl;
import io.quarkiverse.cxf.annotation.CXFClient;
/**
@@ -128,6 +131,20 @@ private Object produceCxfClient(CXFClientInfo cxfClientInfo) {
addToCols(inFaultInterceptor, factory.getInFaultInterceptors());
}
+ switch (cxfClientInfo.getHttpConduitImpl()) {
+ case DefaultHTTPConduitFactory:
+ // nothing to do
+ break;
+ case URLConnectionHTTPConduitFactory:
+ final Map props = new HashMap<>();
+ props.put(HTTPConduitFactory.class.getName(), new URLConnectionHTTPConduitFactory());
+ factory.setProperties(props);
+ break;
+ default:
+ throw new IllegalStateException("Unexpected " + HTTPConduitImpl.class.getSimpleName() + " value: "
+ + cxfClientInfo.getHttpConduitImpl());
+ }
+
LOGGER.debug("cxf client loaded for " + cxfClientInfo.getSei());
Object result = factory.create();
final HTTPConduit httpConduit = (HTTPConduit) ClientProxy.getClient(result).getConduit();
diff --git a/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/URLConnectionHTTPConduitFactory.java b/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/URLConnectionHTTPConduitFactory.java
new file mode 100644
index 000000000..dad38eeb0
--- /dev/null
+++ b/extensions/core/runtime/src/main/java/io/quarkiverse/cxf/URLConnectionHTTPConduitFactory.java
@@ -0,0 +1,19 @@
+package io.quarkiverse.cxf;
+
+import java.io.IOException;
+
+import org.apache.cxf.Bus;
+import org.apache.cxf.service.model.EndpointInfo;
+import org.apache.cxf.transport.http.HTTPConduit;
+import org.apache.cxf.transport.http.HTTPConduitFactory;
+import org.apache.cxf.transport.http.HTTPTransportFactory;
+import org.apache.cxf.transport.http.URLConnectionHTTPConduit;
+import org.apache.cxf.ws.addressing.EndpointReferenceType;
+
+public class URLConnectionHTTPConduitFactory implements HTTPConduitFactory {
+ @Override
+ public HTTPConduit createConduit(HTTPTransportFactory f, Bus bus, EndpointInfo endpointInfo, EndpointReferenceType target)
+ throws IOException {
+ return new URLConnectionHTTPConduit(bus, endpointInfo, target);
+ }
+}
diff --git a/integration-tests/mtom/src/main/resources/application.properties b/integration-tests/mtom/src/main/resources/application.properties
index cacbcb6fd..c9a20bcc4 100644
--- a/integration-tests/mtom/src/main/resources/application.properties
+++ b/integration-tests/mtom/src/main/resources/application.properties
@@ -3,3 +3,6 @@ quarkus.cxf.endpoint."/mtom".implementor = io.quarkiverse.cxf.it.ws.mtom.server.
quarkus.cxf.endpoint."/mtom".handlers = io.quarkiverse.cxf.it.ws.mtom.server.MtomEnforcer
quarkus.native.resources.includes = *.properties,*.jks,*.wsdl,*.xml
+
+# Workaround for https://github.com/quarkiverse/quarkus-cxf/issues/992
+quarkus.cxf.http-conduit-factory = URLConnectionHTTPConduitFactory