CXF
1. Introduction
Apache CXF FAQ
https://cxf.apache.org/faq.html
2. Compatibility matrix
2.1. JDK 1.5
CXF 2.6.x and older can run w/ JDK 5
3. JAX-WS w/ CXF quick reference
Parameter of type Long, nullable
With other types, eg: Integer, CXF accepts null if declared required = false
But with type Long, it throws exception message "javax.xml.ws.soap.SOAPFaultException: Unmarshalling Error: For input string: """
The solution is to explicitly indicate that the parameter is nillable, eg:
@WebMethod(operationName = "myOperation")
@WSDLDocumentation("It is my operation")
/*Nullable*/
ProgresExpedientVO getProgresEstudiantCertificat(//
@WebParam(name = "academicRecordCode") @XmlElement(
required = false, nillable = true) /*@Nullable*/ Long academicRecordCode, //
@WebParam(name = "anIntegerParam") @XmlElement(
required = false, nillable = true) /*@Nullable*/ Integer anIntegerParam)//
throws AppException;
4. cxf-codegen-plugin (WSDL to Java)
https://cxf.apache.org/docs/maven-cxf-codegen-plugin-wsdl-to-ava.html
https://cxf.apache.org/xjc-utils.html
4.1. Binding file
The goal is avoid generation of the JAXBElement types.
File: src\main\resources\jaxws\wsdl_bindings.xjb
<?xml version="1.0" encoding="UTF-8"?>
<jaxb:bindings version="2.0" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://java.sun.com/xml/ns/jaxws"
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
jaxb:extensionBindingPrefixes="xjc">
<jaxb:bindings>
<jaxb:globalBindings generateElementProperty="false" underscoreBinding="asCharInWord">
<xjc:serializable uid="27"/>
</jaxb:globalBindings>
</jaxb:bindings>
</jaxb:bindings>
4.2. Properties (pom.xml)
<build-helper-maven-plugin.version>1.12</build-helper-maven-plugin.version>
<cxf.version>2.6.15</cxf.version>
4.3. Using JDK 1.5
Example using JDK 1.5 w/ maven dependencies:
https://developer.neoncrm.com/api/code-examples/java/
<!-- @WebService and other annotations -->
<dependency>
<groupId>javax.jws</groupId>
<artifactId>javax.jws-api</artifactId>
<version>1.1</version>
</dependency>
<!--
versions after 2.2.4 requires jdk6, please refer
to https://java.net/jira/browse/JAXB-890
-->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.4</version>
</dependency>
<!-- cxf-bundle 2.6.17 includes jaxb-impl 2.2.5.1
<dependency>
<groupId>com.sun.xml.bind</groupId>
<artifactId>jaxb-impl</artifactId>
<version>2.2.4-1</version>
</dependency>
-->
<dependency>
<groupId>javax.xml.soap</groupId>
<artifactId>saaj-api</artifactId>
<version>1.3.3</version>
</dependency>
.
<plugin>
<!-- adding generated source (it adds a new build_class_path to the project) -->
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<version>${build-helper-maven-plugin.version}</version>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/cxf</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-codegen-plugin</artifactId>
<version>${cxf.version}</version>
<executions>
<execution>
<id>generate-sources</id>
<phase>generate-sources</phase>
<configuration>
<sourceRoot>${project.build.directory}/generated-sources/cxf</sourceRoot>
<defaultOptions>
<bindingFiles>
<bindingFile>${project.basedir}/src/main/resources/jaxws/wsdl_bindings.xjb</bindingFile>
</bindingFiles>
<noAddressBinding>true</noAddressBinding>
</defaultOptions>
<wsdlOptions>
<wsdlOption>
<wsdl>${project.basedir}/src/main/resources/wsdls/GatConfigService.wsdl</wsdl>
<extraargs>
<extraarg>-p</extraarg>
<extraarg>http://exceptions.serveis.uoc.edu=generated.edu.uoc.serveis.exceptions</extraarg>
</extraargs>
</wsdlOption>
<wsdlOption>
<wsdl>${project.basedir}/src/main/resources/wsdls/servadm.wsdl</wsdl>
</wsdlOption>
</wsdlOptions>
</configuration>
<goals>
<goal>wsdl2java</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics</artifactId>
<version>0.6.3</version>
</dependency>
<dependency>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-basics-annotate</artifactId>
<version>1.0.4</version>
</dependency>
<dependency>-->
<groupId>org.apache.cxf.xjcplugins</groupId>
<artifactId>cxf-xjc-boolean</artifactId>
<version>2.6.0</version>
</dependency>-->
</dependencies>
</plugin>
5. Port client initialization (example)
Notice that it requires "?wsdl" at the end of the wsdl location url.
5.2. Evaluation (example)
private AvaluacioServicePortType avaluacioPort;
-
/**
* Auxiliary method for initializing the SOAP port binding provider.<br>
* No authentication.<br>
* Oracle JDK CONNECT_TIMEOUT<br>
* Oracle JDK REQUEST_TIMEOUT<br>
*
* @param bindingProvider -
* @param endPointUrl -
*/
private void initializeBindingProvider(final BindingProvider bindingProvider,
final String endPointUrl) {
// Context that is used to initialize the message context for request messages
final Map<String, Object> requestContext = bindingProvider.getRequestContext();
// url endpoint
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endPointUrl);
// [com.sun.xml.ws.client.BindingProviderProperties.CONNECT_TIMEOUT]
requestContext.put("com.sun.xml.ws.connect.timeout", 1024);
// [com.sun.xml.ws.client.BindingProviderProperties.REQUEST_TIMEOUT]
requestContext.put("com.sun.xml.ws.request.timeout", 120000 + 200);
/*
* Needed for avoiding authPort.getContextByModule(module, s) error:
* "Unexpected element appIdTrain in response"
*/
requestContext.put("set-jaxb-validation-event-handler", "false");
}
/**
* Avaluacio WS port.
*
* @return Port
* @throws IOException
*/
public AvaluacioServicePortType getAvaluacioPort() throws IOException {
if (this.gatAvaluacioPort == null) {
final URL wsdlUrlTmp = (new ClassPathResource("wsdls/AvaluacioService.wsdl")).getURL();
final URL wsdlUrl = new URL(wsdlUrlTmp.toString() + "?wsdl");
final AvaluacioService service = new AvaluacioService(wsdlUrl);
// URL endpoint
String endpointUrlBase = System.getProperty("host");
String endpointPath = "/avaluacio-ws/services/AvaluacioService";
final String urlWsService = endpointUrlBase + endpointPath;
// Soap port initialization
final AvaluacioServicePortType port = service.getAvaluacioServiceHttpPort();
this.initializeBindingProvider((BindingProvider) port, urlWsService);
//
this.gatAvaluacioPort = port;
}
//
return this.avaluacioPort;
}
5.2. gestorDocum (example)
GestorDocumService gestorDocumPort;
final URL wsdlUrlTmp = (new ClassPathResource("wsdls/GestorDocumService.wsdl")).getURL();
final URL wsdlUrl = new URL(wsdlUrlTmp.toString() + "?wsdl");
final GestorDocumServiceImplService service = new GestorDocumServiceImplService(wsdlUrl);
// URL endpoint
String endpointUrlBase = System.getProperty("host");
String gestorDocumUrlEndpoint = "/gestordocum-ws/GestorDocumService";
final String urlWsService = endpointUrlBase + gestorDocumUrlEndpoint;
// Soap port initialization
final GestorDocumService port = service.getGestorDocumServiceImplPort();
this.initializeBindingProvider((BindingProvider) port, urlWsService);
//
gestorDocumPort = port;
6. Unit & integration tests
6.1. JUnit 4 (example)
@RunWith(MockitoJUnitRunner.class)
public class ResumenActaActionTest {
static {
// Set environment variables
System.setProperty("host", "http://api-gateway.cou.edu");
}
...
}