이 콘텐츠는 선택한 언어로 제공되지 않습니다.
Chapter 5. Quarkus CXF user guide
This chapter provides information about Quarkus CXF usage and configuration.
5.1. User guide 링크 복사링크가 클립보드에 복사되었습니다!
This User guide explains typical use cases of Quarkus CXF.
You may want to start with some of the following topics:
5.1.1. Create a new project 링크 복사링크가 클립보드에 복사되었습니다!
This guide explains how to set up a new project for a Quarkus application hosting a CXF client or server or both.
5.1.1.1. Prerequisites 링크 복사링크가 클립보드에 복사되었습니다!
Read the Prerequisites section of Quarkus getting started guide.
In addition to that, you may need
-
GraalVM with the
native-imagecommand installed and theGRAALVM_HOMEenvironment variable set. See Building a native executable section of the Quarkus documentation. -
If you are on Linux, a container runtime like
dockeris sufficient for the native mode too. Use-Pnative -Dquarkus.native.container-build=trueinstead of-Pnativeif you choose this option.
5.1.1.2. Creating a project 링크 복사링크가 클립보드에 복사되었습니다!
New project skeletons can be generated using code.quarkus.redhat.com.
- Here you can select the extensions that you want to work with.
-
For a simple Hello world Web service or client the
quarkus-cxfextension is enough. -
Click the blue
Generate your applicationbutton to download a basic skeleton project. - Unpack the zip file and import the project the into your favorite IDE.
5.1.1.3. Quarkus Platform 링크 복사링크가 클립보드에 복사되었습니다!
Quarkus CXF is a part of Quarkus Platform since Quarkus Platform version 3.1.0.Final.
Quarkus Platform aggregates Quarkus extensions produced by various independent projects, such as Quarkus Core, Quarkus CXF, Apache Camel, Qpid JMS, Debezium and others.
Its main goals are:
- Produce BOMs aligned across all participating projects, thus ensuring that their extensions will work together
- Produce metadata for code.quarkus.redhat.com and other Quarkus development tools.
5.1.1.4. Dependency management 링크 복사링크가 클립보드에 복사되었습니다!
We recommend using Quarkus Platform BOMs to manage Quarkus CXF dependencies. That’s exactly what you get, when you use code.quarkus.redhat.com or other Quarkus development tools, such as Quarkus CLI.
You should always take care to import the same version of io.quarkus.platform:quarkus-bom and io.quarkus.platform:quarkus-cxf-bom into your project. That’s the most reliable way to get compatible versions of Quarkus, CXF, Quarkus CXF and all their transitive dependencies.
5.1.1.5. Where to go next 링크 복사링크가 클립보드에 복사되었습니다!
We recommend to proceed with any of the following chapters:
5.1.2. Your first SOAP Web service on Quarkus 링크 복사링크가 클립보드에 복사되었습니다!
In this guide we explain how to create a Quarkus application exposing a simple SOAP Web service.
Follow the Project creation guide before proceeding here.
5.1.2.1. Hello world! Web service 링크 복사링크가 클립보드에 복사되었습니다!
Having the pom.xml in place, you can add a simple Hello world! Web service in src/main/java.
The sample code snippets used in this section come from the server integration test in the source tree of Quarkus CXF
First add the service interface:
HelloService.java
and then the implementation:
HelloServiceImpl.java
For the implementation to get exposed under a certain path, you need to add the following configuration to application.properties:
All configuration properties are documented in the Configuration properties reference.
Check the Service endpoints and paths chapter to learn about alternative ways to expose a service endpoint under a specific path.
With these files in place, you can start Quarkus in dev mode:
mvn quarkus:dev
$ mvn quarkus:dev
This will compile the project and start the application on the background.
You can test the service using curl or some other SOAP client.
First let’s have a look at the auto-generated WSDL under http://localhost:8080/soap/hello?wsdl:
Second, let’s send a SOAP request to the service:
You can see the expected <return>Hello World!</return> in the SOAP response.
5.1.2.2. Add the logging feature while dev mode is running 링크 복사링크가 클립보드에 복사되었습니다!
Sometimes it may come in handy to be able to inspect the SOAP messages received or sent by the server or client. This is easily doable by adding the quarkus-cxf-rt-features-logging extension to pom.xml.
Try to do that while Quarkus dev mode is running. You should see the application being recompiled and redeployed upon saving your changes in the source tree.
Add this to pom.xml
<dependency>
<groupId>io.quarkiverse.cxf</groupId>
<artifactId>quarkus-cxf-rt-features-logging</artifactId>
</dependency>
<dependency>
<groupId>io.quarkiverse.cxf</groupId>
<artifactId>quarkus-cxf-rt-features-logging</artifactId>
</dependency>
Enable SOAP payload logging in application.properties
quarkus.cxf.endpoint."/hello".features=org.apache.cxf.ext.logging.LoggingFeature
quarkus.cxf.endpoint."/hello".features=org.apache.cxf.ext.logging.LoggingFeature
After that you can send a new SOAP request and see some SOAP payloads in the application console:
5.1.2.3. Further steps 링크 복사링크가 클립보드에 복사되었습니다!
You may want to proceed with packaging your application for running on a JVM or natively.
5.1.3. Your first SOAP Client on Quarkus 링크 복사링크가 클립보드에 복사되었습니다!
In this guide we explain how to create a simple Quarkus application acting as a client of a remote Web service.
Follow the Project creation guide before proceeding here.
5.1.3.1. Remote Web service for testing 링크 복사링크가 클립보드에 복사되었습니다!
First, we need some remote Web service to connect to. We can use a simple Calculator Web service running in a container for that purpose.
docker run -p 8082:8080 quay.io/l2x6/calculator-ws:1.0
$ docker run -p 8082:8080 quay.io/l2x6/calculator-ws:1.0
Once the container is up and running, we can inspect its WSDL
As you can see in the WSDL, the service offers some basic arithmetic operations, such as add, subtract, etc.
Let’s test it with curl:
5.1.3.2. SOAP client 링크 복사링크가 클립보드에 복사되었습니다!
Now let’s have a look how we can get the client inside a Quarkus application.
First, we need the Service Endpoint Interface (SEI) and all other model classes it requires.
There are several ways to get them:
- Write by hand
- Copy from the Web Sevice project, if it is written in Java
- Have a Maven artifact containing the model classes, perhaps it is offered by the Service project
- Generate the model classes from WSDL
The last option tends to be the easiest and most flexible for client applications.
If you want to use this approach, first follow the Generate Java from WSDL section and then continue with the next steps.
5.1.3.3. Using SEI as a client 링크 복사링크가 클립보드에 복사되었습니다!
In our case, the Service Endpoint Interface (SEI) is org.jboss.eap.quickstarts.wscalculator.calculator.CalculatorService.
As usual on Quarkus, we can obtain an instance of it via CDI.
To make it testable easily, we’ll wrap it in a REST service:
CxfClientResource.java
Is this all we need for the client to work? - No, in addition to the above, we need to tell a few other things to the CXF Quarkus extension in application.properties:
application.properties
cxf.it.calculator.baseUri=http://localhost:8082
quarkus.cxf.client.myCalculator.wsdl = ${cxf.it.calculator.baseUri}/calculator-ws/CalculatorService?wsdl
quarkus.cxf.client.myCalculator.client-endpoint-url = ${cxf.it.calculator.baseUri}/calculator-ws/CalculatorService
quarkus.cxf.client.myCalculator.service-interface = org.jboss.eap.quickstarts.wscalculator.calculator.CalculatorService
cxf.it.calculator.baseUri=http://localhost:8082
quarkus.cxf.client.myCalculator.wsdl = ${cxf.it.calculator.baseUri}/calculator-ws/CalculatorService?wsdl
quarkus.cxf.client.myCalculator.client-endpoint-url = ${cxf.it.calculator.baseUri}/calculator-ws/CalculatorService
quarkus.cxf.client.myCalculator.service-interface = org.jboss.eap.quickstarts.wscalculator.calculator.CalculatorService
All client configuration properties are documented in the Configuration properties reference.
With all the above files in place, we should be able to start the application in Quarkus dev mode
mvn quarkus:dev ... INFO [io.quarkus] (Quarkus Main Thread) ... Listening on: http://localhost:8080
$ mvn quarkus:dev
...
INFO [io.quarkus] (Quarkus Main Thread) ... Listening on: http://localhost:8080
and test it by sending some requests to it:
curl -s 'http://localhost:8080/cxf/calculator-client/add?a=5&b=6' 11
$ curl -s 'http://localhost:8080/cxf/calculator-client/add?a=5&b=6'
11
where 11 is the correct result of adding 5 and 6.
5.1.3.4. Further steps 링크 복사링크가 클립보드에 복사되었습니다!
You may want to proceed with
5.1.4. Configuration 링크 복사링크가 클립보드에 복사되었습니다!
Quarkus CXF exposes a large number of configuration options. Each extension documents its options at the bottom of its reference page.
The configuration options can be set in application.properties file or via environment variables - see Quarkus configuration reference for details.
5.1.4.1. Bean references 링크 복사링크가 클립보드에 복사되었습니다!
Several configuration options of Quarkus CXF allow referring to beans present in Quarkus CDI container. Features and interceptors are typical examples of those.
There are two ways how to set a bean reference in the configuration: by type or by bean name.
5.1.4.1.1. Bean reference by type 링크 복사링크가 클립보드에 복사되었습니다!
Here is an example:
application.properties
bean reference by type quarkus.cxf.endpoint."/hello".features = org.apache.cxf.ext.logging.LoggingFeature
# bean reference by type
quarkus.cxf.endpoint."/hello".features = org.apache.cxf.ext.logging.LoggingFeature
When using a reference by type name, the resolution proceeds as follows:
- Fist the bean is looked up in Quarkus CDI container by type.
- If the bean is available, it is used.
- If multiple beans assignable to the given type, then an exception is thrown.
- If no matching bean is available, then the class is loaded and an attempt is performed to instantiate it using its default constructor.
5.1.4.1.2. Bean reference by bean name 링크 복사링크가 클립보드에 복사되었습니다!
Here is an example:
application.properties
bean reference by bean name quarkus.cxf.endpoint."/fruit".features = #myCustomLoggingFeature
# bean reference by bean name
quarkus.cxf.endpoint."/fruit".features = #myCustomLoggingFeature
When using a reference by bean name, then unsurprisingly, the bean is looked up in Quarkus CDI container by name. A named bean called myCustomLoggingFeature can be defined as follows:
5.1.5. Package for running on a JVM or natively 링크 복사링크가 클립보드에 복사되었습니다!
In this chapter, we explain how to package a Quarkus CXF application for running on a JVM or for running it natively.
5.1.5.1. JVM mode 링크 복사링크가 클립보드에 복사되었습니다!
In the introductory guides for SOAP client and SOAP service, we worked only in Quarkus dev mode: Quarkus tooling was running on the background, watching for changes in our workspace, recompiling and reloading the application as needed.
How do we run the application on a JVM once we are done with the development?
First we need to package it with Maven:
mvn package
$ mvn package
The libraries needed to run the application on a JVM can be found in target/quarkus-app directory:
We can start the application as follows:
java -jar target/quarkus-app/quarkus-run.jar
$ java -jar target/quarkus-app/quarkus-run.jar
You can send some SOAP requests using curl to make sure that the application works.
5.1.5.2. Native mode 링크 복사링크가 클립보드에 복사되었습니다!
Quarkus offers first class support for building GraalVM native images and Quarkus CXF fully honors that promise too.
GraalVM native images are platform specific executable files that you can run directly without a JVM. They boot faster and spend less memory compared to running the same application in JVM mode.
The pom.xml file generated by code.quarkus.redhat.com contains the native profile needed for building the native image:
Further, as mentioned in the Section 5.1.1, “Create a new project” section, you need the GraalVM native-image tool.
You should either have it installed locally and have GRAALVM_HOME environment variable set properly, or — if you only need to produce a Linux native executable — you can use docker.
With local installation of GraalVM
Quarkus is quite picky about the GraalVM version. When using the local installation, always make sure that you use the version preferred by Quarkus. You can do that by opening quarkus-bom imported in your pom.xml and searching for graalvm there. If you use Docker, Quarkus takes care for pulling the right version for you.
With docker
# Produce the native executable mvn package -Pnative -Dquarkus.native.container-build=true
# Produce the native executable
mvn package -Pnative -Dquarkus.native.container-build=true
This can take a minute or so for a simple application.
When the build is done, the native executable should be available in target directory:
ls -l target ... -rwxr-xr-x. 1 ppalaga ppalaga 71M Jan 11 22:42 quarkus-cxf-integration-test-server-1.8.0-SNAPSHOT-runner ...
$ ls -l target
...
-rwxr-xr-x. 1 ppalaga ppalaga 71M Jan 11 22:42 quarkus-cxf-integration-test-server-1.8.0-SNAPSHOT-runner
...
As you can see, it has a size of only 71 MB, and is executable.
You can run it as follows:
target/*-runner ... INFO [io.quarkus] (main) quarkus-cxf-integration-test-server 1.8.0-SNAPSHOT native (powered by Quarkus 2.15.2.Final) started in 0.042s. Listening on: http://0.0.0.0:8080 ...
$ target/*-runner
...
INFO [io.quarkus] (main) quarkus-cxf-integration-test-server 1.8.0-SNAPSHOT native (powered by Quarkus
2.15.2.Final) started in 0.042s. Listening on: http://0.0.0.0:8080
...
Again, you can send some SOAP requests using curl to make sure that the native executable works.
Do not forget to compare the memory usage, time to first request and other performance metrics with the stack you used before and share your results!
5.1.5.3. Native Image: Additional Resources 링크 복사링크가 클립보드에 복사되었습니다!
You may also refer to the links below which contain tips on how to work with native images.
5.1.5.4. Create container image 링크 복사링크가 클립보드에 복사되었습니다!
Refer to Quarkus Container image guide.
5.1.6. Logging 링크 복사링크가 클립보드에 복사되었습니다!
Refer to Quarkus Logging guide for basic information about logging on Quarkus, such as
- Getting a logger in your application code
- Log levels
- Categories
- Format
- JSON format
5.1.6.1. Payload logging 링크 복사링크가 클립보드에 복사되었습니다!
Since Quarkus CXF 2.6.0, the payload logging functionality is available via io.quarkiverse.cxf:quarkus-cxf extension. Before 2.6.0, it was available through a separate extension io.quarkiverse.cxf:quarkus-cxf-rt-features-logging which is now deprecated and will be removed in the future.
The payload logging functionality is implemented primarily through the org.apache.cxf.ext.logging.LoggingFeature class.
There are several ways how you can set the feature on a client or service endpoint.
5.1.6.2. Configuring payload logging through configuration properties 링크 복사링크가 클립보드에 복사되었습니다!
5.1.6.2.1. Global settings 링크 복사링크가 클립보드에 복사되었습니다!
The global logging options exist since Quarkus CXF 2.6.0. They need to be enabled using quarkus.cxf.logging.enabled-for. There are four possible values:
-
none(default) - the global logging feature is enabled for neither clients nor service endpoints -
clients- the global logging feature is enabled for all clients in the application -
services- the global logging feature is enabled for all service endpoints in the application -
both- the global logging feature is enabled for all clients and service endpoints in the application
The global settings can be overriden on the client or service endpoint level.
application.properties
# Global settings quarkus.cxf.logging.enabled-for = both quarkus.cxf.logging.pretty = true
# Global settings
quarkus.cxf.logging.enabled-for = both
quarkus.cxf.logging.pretty = true
All logging configuration options are listed on quarkus-cxf reference page.
All logging properties mentioned on this page are runtime configuration options. Hence you can pass them when starting the application without having to rebuild it. It can be done either by passing a system property on the command line (e.g. -Dquarkus.cxf.logging.enabled-for=both) or by setting an environment variable (e.g. export QUARKUS_CXF_LOGGING_ENABLED_FOR=both).
5.1.6.2.2. Per client and per service endpoint settings 링크 복사링크가 클립보드에 복사되었습니다!
Since Quarkus CXF 2.5.0, the LoggingFeature can be configured and attached to a client or a service endpoint declaratively by setting the appropriate options in application.properties:
application.properties
All logging configuration options are documented on quarkus-cxf reference page:
5.1.6.3. Alternative ways of adding a LoggingFeature to a client or service 링크 복사링크가 클립보드에 복사되었습니다!
To attach an instance with default settings, you can do one of the following:
In
application.properties:# For a service: quarkus.cxf.endpoint."/hello".features = org.apache.cxf.ext.logging.LoggingFeature # For a client: quarkus.cxf.client."myClient".features = org.apache.cxf.ext.logging.LoggingFeature
# For a service: quarkus.cxf.endpoint."/hello".features = org.apache.cxf.ext.logging.LoggingFeature # For a client: quarkus.cxf.client."myClient".features = org.apache.cxf.ext.logging.LoggingFeatureCopy to Clipboard Copied! Toggle word wrap Toggle overflow TipThere is an example in Your first SOAP Web service chapter of the User guide.
or alternatively
Use the
@Featuresannotation of CXF:Copy to Clipboard Copied! Toggle word wrap Toggle overflow
5.1.6.3.1. Producing a custom LoggingFeature bean 링크 복사링크가 클립보드에 복사되었습니다!
If you need some custom logic to setup the LoggingFeature, you can produce a named LoggingFeature bean:
Then you can refer to it by its name prefixed with # in application.properties:
# For a service: quarkus.cxf.endpoint."/hello".features = #limitedLoggingFeature # For a client: quarkus.cxf.client.hello.features = #limitedLoggingFeature
# For a service:
quarkus.cxf.endpoint."/hello".features = #limitedLoggingFeature
# For a client:
quarkus.cxf.client.hello.features = #limitedLoggingFeature
5.1.7. Complex SOAP payloads with JAXB 링크 복사링크가 클립보드에 복사되었습니다!
Our introductory guides for Quarkus SOAP client and SOAP service dealt with services having only primitive parameters and return values such as integers and strings. Let’s have a look at passing and receiving more complex objects.
As an example, let’s create an application for managing fruits.
The sample code snippets used in this section come from the server integration test in the source tree of Quarkus CXF
Because our representation of fruit is supposed to be a complex, let’s model it as a Java bean with a couple of attributes:
As you may have noticed, we have used some JAXB annotations, such as @XmlElement, @XmlRootElement and @XmlType. This is to control the serialization and deserialization of the bean from and to XML.
5.1.7.1. Automatic registration for reflection 링크 복사링크가 클립보드에 복사되었습니다!
JAXB is a reflection based serialization framework. When learning about GraalVM native images, one of the first things you typically hear is that you have to register classes, fields and methods for reflection at build time. With plain GraalVM you’d have to do this through reflection-config.json manually. Well, at least for the classes you have written yourself. Not so with Quarkus. quarkus-jaxb extension (which quarkus-cxf depends on) is able to scan your application’s class path for classes annotated with JAXB annotations and register them for reflection automatically.
Hence working with complex payloads on Quarkus is not different from stock CXF. The JAXB serialization and deserialization will work out of the box without any additional configuration.
5.1.7.2. SEI and implementation 링크 복사링크가 클립보드에 복사되었습니다!
The Service Endpoint Interface (SEI) for managing fruits might look like the following:
We can implement the SEI as simply as possible:
5.1.7.3. application.properties 링크 복사링크가 클립보드에 복사되었습니다!
The implementation is pretty straightforward and you just need to define your endpoints using the application.properties.
quarkus.cxf.endpoint."/fruits".implementor = io.quarkiverse.cxf.it.server.FruitServiceImpl quarkus.cxf.endpoint."/fruits".features = org.apache.cxf.ext.logging.LoggingFeature
quarkus.cxf.endpoint."/fruits".implementor = io.quarkiverse.cxf.it.server.FruitServiceImpl
quarkus.cxf.endpoint."/fruits".features = org.apache.cxf.ext.logging.LoggingFeature
5.1.7.4. Test with Quarkus dev mode and curl 링크 복사링크가 클립보드에 복사되었습니다!
Having the above files in place, you can start Quarkus tooling in dev mode:
mvn quarkus:dev ... INFO [io.quarkus] (Quarkus Main Thread) ... Listening on: http://localhost:8080
$ mvn quarkus:dev
...
INFO [io.quarkus] (Quarkus Main Thread) ... Listening on: http://localhost:8080
and then check whether the service is working by invoking its list operation:
As you can see, the endpoint has returned the two fruits Apple and Pineapple available by default.
Now let’s add another fruit, say an Orange:
We can see Orange having been added in the returned list as expected.
5.1.7.5. Further steps 링크 복사링크가 클립보드에 복사되었습니다!
You may want to proceed with packaging your application for running on a JVM or natively.
5.1.8. Contract first and code first approaches 링크 복사링크가 클립보드에 복사되었습니다!
Both contract first and code first development modes are fully supported by Quarkus CXF.
5.1.8.1. Contract first client 링크 복사링크가 클립보드에 복사되었습니다!
A SOAP service is described by WSDL. It is a contract defining operations, their parameters and return values, etc. WSDL is rich enough to be used for generating the code of a complete client. CXF provides the wsdl2java utility for that.
Quarkus CXF wraps wsdl2java in the quarkus-cxf extension so you do not need to use it directly.
Follow the Generate the Model classes from WSDL section of the user guide for more details about how to use it.
You may also want to check the CXF Developing a Consumer as a general introduction.
5.1.8.2. Contract first service 링크 복사링크가 클립보드에 복사되었습니다!
When implementing a service the generation of Java code from WSDL may also come in handy. wsdl2java can generate the model classes (with JAXB annotations) and service interfaces (with JAX-WS annotations) for you. Your task is then to provide implementations for those interfaces.
You may want to check the WSDL First Service Development section of CXF documentation for a better understanding of the underlying concepts.
5.1.8.3. Code first service 링크 복사링크가 클립보드에 복사되었습니다!
Another valid option at your disposal is to write your service in Java, using JAX-WS and JAXB. Then you have two options how to obtain the WSDL contract:
-
Start your service and point your clients at
http://your-host/your-service?wsdl - Generate the WSDL document from Java classes at build time
Check the Code first development section of CXF documentation for further information.
5.1.8.4. Generate the Model classes from WSDL 링크 복사링크가 클립보드에 복사되었습니다!
quarkus-cxf extension supports generating Java classes from WSDL during Quarkus code generation phase.
The code snippets shown in this section come from the client integration test in the source tree of Quarkus CXF. You may want to check it as an executable example.
You need to set up a couple of things for CXF code generation to work:
-
Have
io.quarkiverse.cxf:quarkus-cxfdependency in your project For Maven projects, the
generate-codegoal needs to be present in the configuration ofquarkus-maven-plugin:pom.xml
Copy to Clipboard Copied! Toggle word wrap Toggle overflow -
For Gradle projects no additional configurarion of
io.quarkusplugin is needed -
Put your WSDL files under
src/main/resourcesorsrc/test/resourcesor any subdirectory thereof. -
Your WSDL file names must end with
.wsdl Set
quarkus.cxf.codegen.wsdl2java.includesconfiguration property to a pattern matching the WSDL files you wish to process. If you want to process all WSDL files undersrc/main/resources/wsdlorsrc/test/resources/wsdl, set it as follows:application.properties
quarkus.cxf.codegen.wsdl2java.includes = wsdl/*.wsdl
quarkus.cxf.codegen.wsdl2java.includes = wsdl/*.wsdlCopy to Clipboard Copied! Toggle word wrap Toggle overflow
This will generate Java classes in target/generated-sources/wsdl2java or target/generated-test-sources/wsdl2java directory. They will be automatically picked by the compiler plugin there. Hence we are free to refer to them from our application or test code.
Note that quarkus-cxf code generation uses the wsdl2Java utility from CXF under the hood. wsdl2Java is called separately for each WSDL file selected by includes and excludes.
Passing custom parameters to wsdl2java is possible through quarkus.cxf.codegen.wsdl2java.additional-params configuration parameter.
If you need different additional-params for each WSDL file, you may want to define a separate named parameter set for each one of them. Here is an example:
application.properties
Add io.quarkiverse.cxf:quarkus-cxf-xjc-plugins dependency to your project to be able to use -xjc-Xbg, -xjc-Xdv, -xjc-Xjavadoc, -xjc-Xproperty-listener, -xjc-Xts and -xjc-Xwsdlextension wsdl2java parameters.
5.1.8.4.1. Non ASCII Characters 링크 복사링크가 클립보드에 복사되었습니다!
Sometimes the wsdl2java autogenerated Java classes may not be fully compatible with GraalVM due to non ASCII characters getting included in the code. Similar exceptions to the below may appear during native image builds.
[quarkus-dalkia-ticket-loader-1.0.0-SNAPSHOT-runner:26] compile: 161 459,15 ms, 8,54 GB
[quarkus-dalkia-ticket-loader-1.0.0-SNAPSHOT-runner:26] image: 158 272,73 ms, 8,43 GB
[quarkus-dalkia-ticket-loader-1.0.0-SNAPSHOT-runner:26] write: 205,82 ms, 8,43 GB
Fatal error:com.oracle.svm.core.util.VMError$HostedError: java.lang.RuntimeException: oops : expected ASCII string! com.oracle.svm.reflect.OperationOrderStatusType_CRÉÉ_f151156b0d42ecdbdfb919501d8a86dda8733012_1456.hashCode
at com.oracle.svm.core.util.VMError.shouldNotReachHere(VMError.java:72)
[quarkus-dalkia-ticket-loader-1.0.0-SNAPSHOT-runner:26] compile: 161 459,15 ms, 8,54 GB
[quarkus-dalkia-ticket-loader-1.0.0-SNAPSHOT-runner:26] image: 158 272,73 ms, 8,43 GB
[quarkus-dalkia-ticket-loader-1.0.0-SNAPSHOT-runner:26] write: 205,82 ms, 8,43 GB
Fatal error:com.oracle.svm.core.util.VMError$HostedError: java.lang.RuntimeException: oops : expected ASCII string! com.oracle.svm.reflect.OperationOrderStatusType_CRÉÉ_f151156b0d42ecdbdfb919501d8a86dda8733012_1456.hashCode
at com.oracle.svm.core.util.VMError.shouldNotReachHere(VMError.java:72)
Below is an example of auto-generated non ASCII characters in a Java class:
Anything starting with \u will be a problem. Consequently the following refactoring is needed:
5.1.8.5. Generate WSDL document from Java 링크 복사링크가 클립보드에 복사되었습니다!
If the WSDL served by your service at http://your-host/your-service?wsdl is not enough because you e.g. want to distribute it as a Maven artifact, then you can use java2ws to generate the WSDL document at build time.
You do not need to invoke the java2ws tool provided by CXF directly, neither you have to use the cxf-java2ws-plugin.
quarkus-cxf wraps java2ws and so you can configure it in application.properties as any other aspect of your application.
Here is an example:
The sample code snippets used in this section come from the server integration test in the source tree of Quarkus CXF
application.properties
quarkus.cxf.java2ws.includes = io.quarkiverse.cxf.it.server.HelloServiceImpl,io.quarkiverse.cxf.it.server.FaultyHelloServiceImpl quarkus.cxf.java2ws.wsdl-name-template = %TARGET_DIR%/Java2wsTest/%SIMPLE_CLASS_NAME%-from-java2ws.wsdl
quarkus.cxf.java2ws.includes = io.quarkiverse.cxf.it.server.HelloServiceImpl,io.quarkiverse.cxf.it.server.FaultyHelloServiceImpl
quarkus.cxf.java2ws.wsdl-name-template = %TARGET_DIR%/Java2wsTest/%SIMPLE_CLASS_NAME%-from-java2ws.wsdl
Here we have instructed java2ws to generate WSDLs for two service classes, namely HelloServiceImpl and FaultyHelloServiceImpl.
The service classes must be annotated with jakarta.xml.ws.WebService to be selected for java2ws processing.
The two generated WSDL documents will be stored as target/Java2wsTest/FaultyHelloServiceImpl-from-java2ws.wsdl and target/Java2wsTest/HelloServiceImpl-from-java2ws.wsdl respectively.
Unlike wsdl2java which is executed within Quarkus source generation phase, java2ws is a part Quarkus augmentation that happens after compilation. The input of java2ws are, after all, Java class files. Hence you do not need to add <goal>generate-code</goal> to quarkus-maven-plugin for java2ws.
5.1.8.5.1. See also 링크 복사링크가 클립보드에 복사되었습니다!
-
quarkus.cxf.java2ws.*configuration properties ofquarkus-cxf
5.1.9. CXF Interceptors and Features, JAX-WS Handlers 링크 복사링크가 클립보드에 복사되었습니다!
Check the following chapters to learn a bout various ways to customize the processing of SOAP requests and responses:
5.1.9.1. CXF Interceptors and Features 링크 복사링크가 클립보드에 복사되었습니다!
CXF interceptors and CXF features can be added to both your client or server using either annotations or application.properties configurations.
While CXF provides a number of out of the box embedded interceptors and features, you can also integrate your custom developed implementations.
Annotations can be used on either the service interface or implementor classes.
You may also define your configurations in the application.properties file.
quarkus.cxf.endpoint."/greeting-service".features=org.apache.cxf.ext.logging.LoggingFeature quarkus.cxf.endpoint."/greeting-service".in-interceptors=org.acme.Test1Interceptor quarkus.cxf.endpoint."/greeting-service".out-interceptors=org.acme.Test1Interceptor quarkus.cxf.endpoint."/greeting-service".in-fault-interceptors=org.acme.Test2Interceptor,org.acme.Test3Intercetpor quarkus.cxf.endpoint."/greeting-service".out-fault-interceptors=org.acme.Test1Intercetpor
quarkus.cxf.endpoint."/greeting-service".features=org.apache.cxf.ext.logging.LoggingFeature
quarkus.cxf.endpoint."/greeting-service".in-interceptors=org.acme.Test1Interceptor
quarkus.cxf.endpoint."/greeting-service".out-interceptors=org.acme.Test1Interceptor
quarkus.cxf.endpoint."/greeting-service".in-fault-interceptors=org.acme.Test2Interceptor,org.acme.Test3Intercetpor
quarkus.cxf.endpoint."/greeting-service".out-fault-interceptors=org.acme.Test1Intercetpor
Both feature and interceptor classes are loaded via CDI first. They can be referenced by fully a qualified class name or by a bean name.
If no CDI beans are available, the constructor without parameters will be invoked to instantiate each class.
5.1.9.2. JAX-WS Handlers 링크 복사링크가 클립보드에 복사되었습니다!
As an alternative to the @HandlerChain annotation, JAX-WS Handlers can be added to both your client or server via application.properties:
application.properties
# A web service endpoint with multiple Handler classes quarkus.cxf.endpoint."/greeting-service".handlers=org.acme.MySOAPHandler,org.acme.AnotherSOAPHandler # A web service client with a single Handler quarkus.cxf.client."greeting-client".handlers=org.acme.MySOAPHandler
# A web service endpoint with multiple Handler classes
quarkus.cxf.endpoint."/greeting-service".handlers=org.acme.MySOAPHandler,org.acme.AnotherSOAPHandler
# A web service client with a single Handler
quarkus.cxf.client."greeting-client".handlers=org.acme.MySOAPHandler
Where MySOAPHandler could look like below:
The SOAPHandler classes are loaded via CDI first..
If no CDI beans are available, the constructor without parameters will be invoked to instantiate each class.
5.1.10. Advanced service topics 링크 복사링크가 클립보드에 복사되었습니다!
Check the following chapters for more details about implementing SOAP service endpoints:
5.1.10.1. Service endpoints and paths 링크 복사링크가 클립보드에 복사되었습니다!
Let’s explain how a service endpoint can be exposed under a certain URL path.
5.1.10.1.1. Set the endpoint path via application.properties 링크 복사링크가 클립보드에 복사되었습니다!
In the First SOAP Web service chapter, we explained how to expose a service using application.properties:
application.properties
With this setup in place, the io.quarkiverse.cxf.it.server.HelloServiceImpl will be accessible under http://localhost:8080/soap/hello.
This is the traditional way that worked since the very beginning of Quarkus CXF.
5.1.10.1.2. Set the endpoint path using @CXFEndpoint annotation 링크 복사링크가 클립보드에 복사되었습니다!
Since Quarkus CXF 3.11.0, there is a new way to expose an endpoint under a specific path: the @io.quarkiverse.cxf.annotation.CXFEndpoint annotation. The path is set through its non-optional attribute value and it is relative to quarkus.cxf.path much like when this is done via application.properties.
Let’s have a look at an example.
The sample code snippet shown in this section comes from the Client and server integration test in the source tree of Quarkus CXF. You may want to use it as a runnable example.
PathAnnotationHelloServiceImpl.java
- 1
- If the value of
quarkus.cxf.pathinapplication.propertiesis/soap, then this service will be accessible underhttp://localhost:8080/soap/path-annotation.
@CXFEndpoint("/my-path") annotation on MyServiceImpl type is equivalent to the quarkus.cxf.endpoint."/my-path".implementor = org.acme.MyServiceImpl line in application.properties. Therefore it is enough to use just one of them.
Other options set in application.properties for the /my-path endpoint will combine just fine with @CXFEndpoint("/my-path").
5.1.10.1.2.1. Use the @CXFEndpoint annotation on producer methods 링크 복사링크가 클립보드에 복사되었습니다!
The @CXFEndpoint annotation can also be used on producer methods. This comes in handy especially when testing clients, because the returned implementation can be a mock.
Here is an example:
MockedEndpointTest.java
- 1
- Here we use the
@CXFEndpointannotation on a method that returns a mock of theHelloServiceinterface. The@jakarta.enterprise.inject.Producesannotation is not required, because Quarkus CXF declares@CXFEndpointas a bean defining annotation. - 2
- The client is configured in
application.propertiesto connect tohttp://localhost:8080/soap/helloMock - 3
- The assertion makes sure that the service implementation works as expected.
5.1.10.2. JAX-WS Providers 링크 복사링크가 클립보드에 복사되었습니다!
JAX-WS Providers are fully supported, and can be implemented as shown below.
Given the following sample Provider implementation:
The application.properties can be configured as shown below.
# A web service endpoint with the Provider implementation class quarkus.cxf.endpoint."/stream-source".implementor=org.acme.StreamSourcePayloadProvider
# A web service endpoint with the Provider implementation class
quarkus.cxf.endpoint."/stream-source".implementor=org.acme.StreamSourcePayloadProvider
Provider classes are loaded via CDI first..
If no CDI beans are available, the constructor without parameters will be invoked to instantiate each class.
5.1.10.3. REST and SOAP Endpoints 링크 복사링크가 클립보드에 복사되었습니다!
Sometimes a REST endpoint may be needed in the same project where the Quarkus CXF Extension is used. The REST endpoint path must be different from the SOAP endpoint path (in order to avoid request forwarding conflicts between both protocols).
For example, if a WeatherWebService interface is declared in a WSDL, you can begin by creating the org.acme.cxf.WeatherWebServiceImpl class as follows:
After that, you would need to specify the root context for your CXF web services, as indicated in the configuration documentation to split the REST (with RESTEasy for example) and SOAP routes based on their root context paths.
CXF’s SOAP properties:
quarkus.cxf.path=/soap quarkus.cxf.endpoint."/weather".implementor=org.acme.cxf.WeatherWebServiceImpl
quarkus.cxf.path=/soap
quarkus.cxf.endpoint."/weather".implementor=org.acme.cxf.WeatherWebServiceImpl
Now, imagine the following RESTEasy endpoint:
You can separate your REST endpoint by configuring the REASTEasy path:
quarkus.resteasy.path=/rest
quarkus.resteasy.path=/rest
You should now be able to send requests to both your REST and SOAP endpoints deployed within a single project, at:
- http://localhost:8080/rest/healthcheck for REST
- http://localhost:8080/soap/weather for SOAP
5.1.10.4. Running behind a reverse proxy 링크 복사링크가 클립보드에 복사되었습니다!
SOAP requests aimed towards services running on Quarkus can be routed through proxies that generate additional headers (e.g. X-Forwarded-Host) to keep information from the client-facing side of the proxy servers that is altered or lost when they are involved. In those scenarios, Quarkus can be configured to automatically update information like protocol, host, port and URI reflecting the values in these headers.
Refer to Quarkus HTTP reference for more details.
Quarkus CXF support for various X-Forwarded headers works in line with Quarkus configuration.
Activating this feature leaves the server exposed to several security issues (i.e. information spoofing). Consider activating it only when running behind a reverse proxy.
These are the relevant Quarkus properties and their effect on Quarkus CXF:
quarkus.http.proxy.proxy-address-forwarding- the main switch to enable the rewriting of the request destination parts.- If enabled, the rewriting of the request fields will be effective throughout the whole CXF server stack.
-
If enabled, the values passed via
X-Forwarded-ProtoandX-Forwarded-Portheaders will be used to set the protocol part and the port part of the URL returned byjakarta.servlet.http.HttpServletRequest.getRequestURL()respectively. -
If enabled, the value passed via
X-Forwarded-Forwill be returned byjakarta.servlet.ServletRequest.getRemoteAddr().
-
quarkus.http.proxy.enable-forwarded-host- enable the rewriting of the host part of URL returned byjakarta.servlet.http.HttpServletRequest.getRequestURL(). The actual host name is taken from the header configured viaquarkus.http.proxy.forwarded-host-header(default isX-Forwarded-Host). -
quarkus.http.proxy.enable-forwarded-prefix- enable the rewriting of the path part of the URL returned byjakarta.servlet.http.HttpServletRequest.getRequestURL()and of the URI returned byjakarta.servlet.http.HttpServletRequest.getRequestURI(). The actual path prefix is taken from the header configured viaquarkus.http.proxy.forwarded-prefix-header(default isX-Forwarded-Prefix).
Here is the most common snippet to copy to your application.properties:
quarkus.http.proxy.proxy-address-forwarding = true quarkus.http.proxy.enable-forwarded-host = true quarkus.http.proxy.enable-forwarded-prefix = true
quarkus.http.proxy.proxy-address-forwarding = true
quarkus.http.proxy.enable-forwarded-host = true
quarkus.http.proxy.enable-forwarded-prefix = true
One of the observable effects of these settings is the change of the location value in WSDL served on http://localhost:8080/services/my-service?wsdl. For example, if the request contains the following headers
X-Forwarded-Proto: https X-Forwarded-Host: api.example.com X-Forwarded-Port: 443 X-Forwarded-Prefix: /my-prefix
X-Forwarded-Proto: https
X-Forwarded-Host: api.example.com
X-Forwarded-Port: 443
X-Forwarded-Prefix: /my-prefix
then the WSDL served on http://localhost:8080/services/my-service?wsdl would contain the following location:
... <soap:address location="https://api.example.com:443/my-prefix/services/my-service"/> ...
...
<soap:address location="https://api.example.com:443/my-prefix/services/my-service"/>
...
5.1.11. Advanced SOAP client topics 링크 복사링크가 클립보드에 복사되었습니다!
Check the following chapters for more details about implementing SOAP clients:
5.1.11.1. client-endpoint-url defaults 링크 복사링크가 클립보드에 복사되었습니다!
If you omit the client-endpoint-url property in application.properties, the CXF Quarkus extension will assume that the service is published at http://localhost:8080/{service-path}, where {service-path} is derived from
-
Configuration property
quarkus.cxf.path(if specified); and the - SEI’s class name in lower case
Given quarkus.cxf.path = /ws, the default effective client-endpoint-url of the CalculatorService would be http://localhost:8080/ws/org.jboss.eap.quickstarts.wscalculator.calculator.calculatorservice.
If quarkus.cxf.path is not specified, the client-endpoint-url would be just http://localhost:8080/org.jboss.eap.quickstarts.wscalculator.calculator.calculatorservice.
5.1.11.2. Configure multiple clients 링크 복사링크가 클립보드에 복사되었습니다!
In the example above, we configured just a single client called myCalculator. Of course, you can configure multiple clients pointing at different URLs and/or implementing different SEIs using multiple identifiers:
application.properties
5.1.11.3. CDI scope of clients injected via @CXFClient 링크 복사링크가 클립보드에 복사되었습니다!
Quarkus CXF produces all clients injected via @io.quarkiverse.cxf.annotation.CXFClient in the default @Dependent scope. Due to that, the real scope of the injected instance depends on the CDI scope of the bean into which the client is injected.
Therefore, if the client is injected into an @ApplicationScoped bean, then the client instance also becomes @ApplicationScoped. If the client is injected into an @RequestScoped bean, then the client instance also becomes @RequestScoped.
This behavior comes in handy if you need to configure clients dynamically after the application was started.
5.1.11.4. Programmatic client configuration at startup 링크 복사링크가 클립보드에 복사되었습니다!
To configure all clients at application startup, you can implement an HTTPConduitConfigurer and set it on the CXF Bus in an StartupEvent observer method.
In the example snippet below, we configure some aspects of the HTTPClientPolicy. The same approach can be leveraged to customize also AuthorizationPolicy, ProxyAuthorizationPolicy or even TLSClientParameters of your clients.
5.1.11.5. 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.
5.1.11.5.1. 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.
5.1.11.6. Pure client applications 링크 복사링크가 클립보드에 복사되었습니다!
Quarkus batch (e.g. periodically scheduled), or command line applications, may do without an HTTP server. Use the property below to prevent launching the HTTP server at startup:
quarkus.http.host-enabled = false
quarkus.http.host-enabled = false
5.1.11.7. Prevent resource leaks 링크 복사링크가 클립보드에 복사되었습니다!
CXF client proxies implement java.io.Closeable. Therefore, it is important to call ((Closeable) proxy).close() once the client is not needed anymore to free all associated system resources, such as threads.
Quarkus CXF takes care for closing the clients injected via @io.quarkiverse.cxf.annotation.CXFClient automatically as soon as they are disposed by the CDI container.
For client proxies created manually, it is up to you to call ((Closeable) proxy).close():
5.1.12. Camel Integration 링크 복사링크가 클립보드에 복사되었습니다!
Camel Quarkus supports CXF since its version 2.12.0. Under the hood, the implementation is based on Quarkus CXF. Therefore, all functionality available in Quarkus CXF is also available in Camel Quarkus.
Refer to Camel Quarkus CXF SOAP extension documentation for further details.
5.1.13. Examples 링크 복사링크가 클립보드에 복사되었습니다!
The integration-tests folder of the codebase provides various examples that demonstrate how to use this extension extensively.