Apache CXF : Un Open-Source Services Framework

Apache CXF et Eclipse

CXF : Générer le code source java depuis un WSDL avec Eclipse Helios (3.6.x) ou supérieur, afin de créer un client WebService (WS) qui consommera ce service web CXF

Commencer par téléchargez Apache CXF (actuellement c'est la version 2.3.2), que vous décompresser ou bon vous semble (F:\apache-cxf-2.3.2\ chez nous).

Ensuite consulter : Windows -> Preferences -> Web Services -> CXF 2.x Preferences

01-cxf-not-loaded.gif

On constate qu'il manque la librairie CXF, que nous allons ajouter dans l'onglet CXF Runtime -> Add :

02-cxf-add-cxf-runtime.gif

On n'oublie de cocher cette nouvelle CFX Runtime pour s'en servir :

03-cxf-use-cxf-runtime.gif

Puis, on crée un projet pour convertir notre WSDL en Java. Contrairement à Axis, il faut impérativement faire cela sur un projet de type : Dynamic Web Project. Créons ce Dynamic Web Project :

04-cxf-create-dynamic-web-project.gif

Nous nommerons ce Dynamic Web Project : "TestCxf", et comme nous n'avons pas de serveur web ou J2EE, nous laissons le Target runtime vide.

05-cxf-create-dynamic-web-project.gif

Après avoir fait Next, Next, Next ... le projet est créé :

06-cxf-dyn-created.gif

On peut enchainer sur la création du client WS : File -> New -> Other -> Web Services -> Web Service Client

07-cxf-create-ws-client.gif

On colle l'URL contenant le WSDL :

http://cxf.apache.org/docs/defining-contract-first-webservices-with-wsdl-generation-from-java.data/CustomerService.wsdl?version=2&modificationDate=1219340552000

Ce fichier WSDL provient de la page Defining Contract first webservices with wsdl generation from java

08-cxf-create-ws-client.gif

On change la Web Service runtime pour choisir CXF :

09-cxf-create-ws-client-choose-ws-runtime.gif

Et malheureusement on ne pas valider et continuer puisque qu'aucun Server runtime n'est installé. :(

10-add-server.gif

Nous allons choisir Jboss comme serveur, télécharger Jboss (ou un quelconque serveur qui gère CXF en natif). Une fois décompressé (F:\jboss-6.0.0.Final pour nous), on ajoute ce serveur dans la liste des serveurs :

11-add-server-jboss.gif

On rajoute un serveur de type Jboss v5.0 et optionnellement on le renomme "JBoss v5.0 at localhost (jboss-6.0.0.Final)", puis Next, Next Next ...

12-add-server-jboss-path.gif

Ce nouveau serveur Jboss est présent dans la liste des serveur :

13-server-jboss-added.gif

On peut reprendre la création de notre WS Client : File -> New -> Other -> Web Services -> Web Service Client

On recolle l'URL contenant le WSDL :

http://cxf.apache.org/docs/defining-contract-first-webservices-with-wsdl-generation-from-java.data/CustomerService.wsdl?version=2&modificationDate=1219340552000

Et on modifie le "Server runtime" et le "Web service runtime"

14-ws-client-jboss.gif

Mais quelle misère ! Il nous indique que le Jboss v5.0 ne supporte pas le projet client TestCxf :(

On doit activer le Facet de notre projet : Properties -> Project Facets et on active "CXF 2.x Web Services"

15-project-facet-cxf.gif

Et dommage, ce n'est pas suffisant, on a toujours la même erreur.

Nous allons donc créer un projet nommé "TestCxf2" avec l'environnement complet dès le départ :

  • CXF installé
  • Un serveur runtime installé : Jboss

N'oubliez pas de :

  • choisir votre Target Runtime : Jboss v5.0
    • ce qui impactera automatiquement le Dynamic web module version qui passera de 3.0 en 2.5
  • modifier la Configuration de "Default configuration for JBoss v5.0" en "CXF Web Services Project v2.5"

16-new-full-project.gif

Puis Next, Next, Next ...

Une fois ce nouveau projet crée, on recommence la création d'un service web client depuis le WSDL :

http://cxf.apache.org/docs/defining-contract-first-webservices-with-wsdl-generation-from-java.data/CustomerService.wsdl?version=2&modificationDate=1219340552000

Et, enfin ! il n'indique plus d'erreur d'incompatibilité. N'oubliez pas toute fois de changer le Web Service runtime en Apache CXF 2.x

17-change-web-service-runti.gif

18-ws-ready-to-create.gif

19-ws-creating.gif

20-ws-creating.gif

Puis Next, Next, Next ...

Et victoire, vous avez votre code JAVA généré depuis le WSDL.

21-ws-created.gif

Avec comme log, la ligne de commande utilisée :

Loading FrontEnd jaxws ...
Loading DataBinding jaxb ...
wsdl2java -client -d F:\workspaceEclipseJavaHelios\TestCxf2\.cxftmp/src -classdir F:\workspaceEclipseJavaHelios\TestCxf2\build\classes -p http://customerservice.example.com/=com.example.customerservice -impl -validate -exsh false -dns true -dex true -wsdlLocation http://localhost:9090/CustomerServicePort?wsdl -verbose -defaultValues -fe jaxws -db jaxb -wv 1.1 http://cxf.apache.org/docs/defining-contract-first-webservices-with-wsdl-generation-from-java.data/CustomerService.wsdl?version=2&modificationDate=1219340552000
wsdl2java - Apache CXF 2.3.1

log4j:WARN No appenders could be found for logger (org.apache.cxf.common.logging.LogUtils).
log4j:WARN Please initialize the log4j system properly.

Vous pourrez remarquez que malgrès que l'on ai télécharger Apache CXF 2.3.2 il utilise la version 2.3.1 (qui est inclue dans Eclipse)

Ce qui aurait donné en ligne de commandes avec wsdl2java WSDL to Java :

F:\apache-cxf-2.3.2\bin>wsdl2java
ERROR: Set JAVA_HOME to the path where the JDK (5.0 or higher) is installed
 
F:\apache-cxf-2.3.2\bin>wsdl2java
ERROR: Set JAVA_HOME to the path where the JDK (5.0 or higher) is installed
 
F:\apache-cxf-2.3.2\bin>SET JAVA_HOME=C:\Program Files\Java\jre6
 
F:\apache-cxf-2.3.2\bin>wsdl2java
Missing argument: wsdlurl
 
Usage : wsdl2java -fe <front-end-name> -db <data-binding-name> -wv <wsdl-version> -p <[wsdl-namespace =]package-name>* -sn <service-name> -b <binding-file-name>
* -reserveClass <class-name>* -catalog <catalog-file-name> -d <output-directory> -compile -classdir <compile-classes-directory> -impl -server -client -all -auto
NameResolution -allowElementReferences<=true> -defaultValues<=class-name-for-DefaultValueProvider> -ant -nexclude <schema-namespace [= java-package-name]>* -exs
h <(true, false)> -dns <Default value is true> -dex <(true, false)> -validate -keep -wsdlLocation <wsdlLocation> -xjc<xjc-arguments>* -noAddressBinding -useFQCN
ForFaultSerialVersionUID -mark-generated -h -v -verbose -quiet -wsdlList <wsdlurl>
 
 
WSDLToJava Error: org.apache.cxf.tools.common.toolspec.parser.BadUsageException: Missing argument: wsdlurl
 
F:\apache-cxf-2.3.2\bin>wsdl2java -client -d F:\workspaceEclipseJavaHelios\TestCxf2\.cxftmp/src -classdir F:\workspaceEclipseJavaHelios\TestCxf2\build\classes -p http://customerservice.example.com/=com.example.customerservice -impl -validate -exsh false -dns true -dex true -wsdlLocation http://localhost:9090/CustomerServicePort?wsdl -verbose -defaultValues -fe jaxws -db jaxb -wv 1.1 http://cxf.apache.org/docs/defining-contract-first-webservices-with-wsdl-generation-from-java.data/CustomerService.wsdl?version=2&modificationDate=1219340552000
Loading FrontEnd jaxws ...
Loading DataBinding jaxb ...
wsdl2java -client -d F:\workspaceEclipseJavaHelios\TestCxf2\.cxftmp/src -classdir F:\workspaceEclipseJavaHelios\TestCxf2\build\classes -p http://customerservice.example.com/=com.example.customerservice -impl -validate -exsh false -dns true -dex true -wsdlLocation http://localhost:9090/CustomerServicePort?wsdl -verbose-defaultValues -fe jaxws -db jaxb -wv 1.1 http://cxf.apache.org/docs/defining-contract-first-webservices-with-wsdl-generation-from-java.data/CustomerService.wsdl?version=2
wsdl2java - Apache CXF 2.3.2

Et le résumé sans incident par la documentation Eclipse :

Un problème de génération des setter sur les éléments de type tableaux ou liste (multiples/multiplicité)

__La spécification JAXB indique qu'il n'y a pas de setter pour les éléments multiples <List>. La méthode à utiliser, est simplement l'utilisation des méthodes de liste sur l'attribut à travers le getter :__

ObjetDeTypeList obj = new ObjetDeTypeList("monAttributDeObjetTypeList");
monObjet.getAttributDeTypeList().add(obj);

Suivez l'attribut "address" pour voir la problématique !

Initialement avant la création du WSDL on avait la classe suivante :

package com.example.customerservice;
 
@XmlAccessorType( XmlAccessType.FIELD )
public class Customer {
    String name;
    String[] address;
    int numOrders;
    double revenue;
    BigDecimal test;
    Date birthDate;
    CustomerType type;
}

Une fois convertit en WSDL :

<xs:complexType name="customer">
        <xs:sequence>
            <xs:element minOccurs="0" name="name" type="xs:string"/>
            <xs:element maxOccurs="unbounded" minOccurs="0" name="address" nillable="true" type="xs:string"/>
            <xs:element name="numOrders" type="xs:int"/>
            <xs:element name="revenue" type="xs:double"/>
            <xs:element minOccurs="0" name="test" type="xs:decimal"/>
            <xs:element minOccurs="0" name="birthDate" type="xs:dateTime"/>
            <xs:element minOccurs="0" name="type" type="tns:customerType"/>
        </xs:sequence>
    </xs:complexType>

Puis reconvertit en JAVA :

public class Customer {
 
    protected String name;
    @XmlElement(nillable = true)
    protected List<String> address;
    protected int numOrders;
    protected double revenue;
    protected BigDecimal test;
    @XmlSchemaType(name = "dateTime")
    protected XMLGregorianCalendar birthDate;
    protected CustomerType type;

Donc on est passé d'un String[] en List<String>, ok cela nous bouleverse pas trop. Par contre le getter pour address est bien généré : getAddress(), mais le setter est absent ! il n'y à pas de setAdress(List<String> address)

Comment générer automatique ces setter pour les éléments multiples ?...

I follow "Defining Contract first webservices with wsdl generation from java" : http://cxf.apache.org/docs/defining-contract-first-webservices-with-wsdl-generation-from-java.html

When i generate WSDL to Java, attribute "address[]" (List<String> address) is in my class.
The getter is generated.
But the setter is missing ...

<xs:element maxOccurs="unbounded" minOccurs="0" name="address" nillable="true" type="xs:string"/>

Only the setters on maxOccurs="unbounded" are missing.

wsdl2java don't generate attributes[] ? Is a way to generate setters on array attributes ?

===>

That's per the JAXB specification - you don't set the list, rather, you
get the list and then add whatever elements you want to it.

There's a collection setter injector plugin, but the link is presently
broken:  http://java.net/projects/jaxb2-comm... (link 11).
See here for more info on JAXB customizations:  
http://www.jroller.com/gmazza/entry...

===> "cxf Collection setter injector plugin"

Per XSD defaults, minOccurs and maxOccurs are defaulted to 1 if they are not shown. http://www.w3schools.com/Schema/sch...

Defining Contract first webservices with wsdl generation from java

Each element has minOccurs="0" which marks it as optional. This is a good thing as you can add new optional elements and keep compatible. If you do not want this optionality you can use @XmlElement(required=true).

The array of Strings for address is described as maxOccurs="unbounded" so the element may be repeated in the later xml to form the array.

La version d'Eclipse utilisée

  • Eclipse.ini (si vous avez besoin de paramétrer la version Java ou la mémoire disponible pour Eclipse)

Les versions d'Eclipse et CXF (Help -> About Eclipse) :

  • Eclipse;org -> Eclipse Platform
    • Version: 3.6.1.r361_v20100909-9gF78GrkFqw7GrsZnvz0JWNTeb6fue6896L (Helios)
    • Build id: M20100909-0800
    • (c) Copyright Eclipse contributors and others 2000, 2010. All rights reserved.
    • Visit http://www.eclipse.org/platform
  • WTP -> CXF Web Services
    • Version: 1.0.2.v201008232129-7H777DFAKlRiOX8lGdRoz0878J
    • Build id: 20100915173744
    • (c) Copyright Eclipse contributors and others 2008, 2010. All rights reserved.
    • Visit http://www.eclipse.org/webtools/

Ressources sur Apache CXF, les framework de Web Services

Jboss & CXF

Section Maven (Obsolète)

Maven

Créer un projet J2EE dans Eclipse avec Maven : 2ème partie

J’insiste bien sur les 2 lignes (la fusion en une ligne ne fonctionne pas). De même, il faut placer ces 2 lignes avant la ligne -vmargs.

Remplacez C:\java\jdk1.6.0_21\bin par l’adresse du répertoire bin de votre jdk (oui, je sais, je suis sous Windows. Et alors ? )

Il reste à terminer le paramétrage de m2eclipse. Pour cela, sélectionner Window->Preferences->Maven->Installations. Par défaut, m2eclipse utilise une version préliminaire de Maven 3. Rappelons que Maven 3 est encore en développement. Afin d’utiliser la version stable de Maven, il faut installer Apache Maven. Puis indiquez à m2eclipse le chemin où trouver Maven (version 2.2.1 à la date de rédaction de l’article).

-vm 
C:\Program Files (x86)\Java\jdk1.6.0_22\bin
-vmargs

http://wiki.eclipse.org/Eclipse.ini

  • http://maven.apache.org/download.html
  • http://marketplace.eclipse.org/content/maven-integration-eclipse
  • http://m2eclipse.sonatype.org/installing-m2eclipse.html
  • http://maven.apache.org/eclipse-plugin.html
  • http://maven.apache.org/plugins/maven-eclipse-plugin/
  • http://help.eclipse.org/help33/index.jsp?topic=/org.eclipse.platform.doc.user/tasks/running_eclipse.htm

Autres ressources CXF

CXF exemple d'implémentation d'un client WS CXF

Client WS CXF avec changement de l'adresse (endpoint) (méthode 1)

URL wsdlLocation = new URL("http://www.placeoweb.com//ServiceCalculator.wsdl");
						ServiceCalculatorSoapBindingImplService service = new ServiceCalculatorSoapBindingImplService(wsdlLocation);
						ServiceCalculator port = service.getServiceCalculatorSoapBindingImplPort();
						( (BindingProvider) port ).getRequestContext().put( BindingProvider.ENDPOINT_ADDRESS_PROPERTY, "http://www.cxf.service.provider.com/uri" );
						System.out.println("ws.endpoint [" + ((BindingProvider)port).getEndpointReference() + "]");
						ClassResponse reponse = port.add(2,3);

Client WS CXF avec changement de l'adresse (endpoint) (méthode 2)

package com.sample;
 
import org.apache.cxf.interceptor.*;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
 
public class Client {
 
	public static void main(String args[]) throws Exception {
 
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
 
		factory.getInInterceptors().add(new LoggingInInterceptor());
		factory.getOutInterceptors().add(new LoggingOutInterceptor());
		factory.setServiceClass(Math.class);
//		factory.setAddress("http://localhost:8080/Samplews");	// javax.xml.ws.WebServiceException: Could not send Message. Caused by: java.io.IOException: IOException invoking http://localhost:8080/Samplews: HTTP response '404: Introuvable'
		factory.setAddress("http://localhost:8080/MyCxfProject");
		Math client = (Math) factory.create();
 
		System.out.println("Server said: " + client.sum(2000, 11));	// Server said: 2011
//		server log : 23:20:54,462 INFO  [STDOUT] Summing 2000 + 11
 
	}
 
}

Client WS CXF avec changement de l'adresse (endpoint) + authentification HTTP (HTTP Basic Auth) + configuration du timeout

package com.sample;
 
import org.apache.cxf.interceptor.*;
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
 
public class Client {
 
	public static void main(String args[]) throws Exception {
 
		JaxWsProxyFactoryBean factory = new JaxWsProxyFactoryBean();
 
		factory.getInInterceptors().add(new LoggingInInterceptor());
		factory.getOutInterceptors().add(new LoggingOutInterceptor());
		factory.setServiceClass(Math.class);
//		factory.setAddress("http://localhost:8080/Samplews");	// javax.xml.ws.WebServiceException: Could not send Message. Caused by: java.io.IOException: IOException invoking http://localhost:8080/Samplews: HTTP response '404: Introuvable'
		factory.setAddress("http://localhost:8080/MyCxfProject");
		Math client = (Math) factory.create();
 
//		HttpBasicAuthSupplier httpBasicAuthSupplier = new HttpBasicAuthSupplier();
//		httpBasicAuthSupplier.
 
//org.apache.cxf.interceptor.Fault: Could not send Message.
//Caused by: org.apache.cxf.transport.http.HTTPException: HTTP response '401: Non-Autorisé' when communicating with http://localhost:8080/MyCxfProject
 
		String username = "monIdentifiantHttp";
		String password = "monMotDePasseHTTP";
//		HttpBasicAuthSupplier.createUserPass(userid, password);
 
//		HttpBasicAuthSupplier {
//		HttpBasicAuthSupplier.UserPass
 
		Client client = ClientProxy.getClient(clientWs); 
 
		HTTPConduit conduit = (HTTPConduit) client.getConduit();
 
		AuthorizationPolicy auth = conduit.getAuthorization();
		auth.setUserName(username);
		auth.setPassword(password);	
 
		HTTPClientPolicy httpClientPolicy = new HTTPClientPolicy();
		httpClientPolicy.setConnectionTimeout(36000);
		httpClientPolicy.setAllowChunking(false);
		httpClientPolicy.setReceiveTimeout(32000);   
 
		System.out.println("Server said: " + client.sum(2000, 11));	// Server said: 2011
//		server log : 23:20:54,462 INFO  [STDOUT] Summing 2000 + 11
 
	}
 
}

Client CXF avec SSL

Pour activer le SSL sur CXF, c'est dans le même genre il faut modifier le conduit HTTP

Et modifier au besoins les règles quand on a des erreurs du type :

class javax.xml.ws.WebServiceException: javax.xml.ws.WebServiceException: Could not send Message.
java.io.IOException: IOException invoking https://192.168.0.1/servicescxf/Calculator: The https URL hostname does not match the Common Name (CN) on the server certificate.  To disable this check (NOT recommended for production) set the CXF client TLS configuration property "disableCNCheck" to true.
java.io.IOException: The https URL hostname does not match the Common Name (CN) on the server certificate.  To disable this check (NOT recommended for production) set the CXF client TLS configuration property "disableCNCheck" to true.

Lire les paramètres côté servlet

// HTTP Transport > Servlet Transport : http://cxf.apache.org/docs/servlet-transport.html
// Accessing the MessageContext and/or HTTP Request and Response
 
// First, declare a private field for the WebServiceContext in your service implementation, and annotate it as a resource:
//@Resource
//private WebServiceContext context;
 
    	MessageContext ctx = context.getMessageContext();
    	HttpServletRequest request = (HttpServletRequest) ctx.get(AbstractHTTPDestination.HTTP_REQUEST);
    	HttpServletResponse response = (HttpServletResponse) ctx.get(AbstractHTTPDestination.HTTP_RESPONSE);
    	LOG.info("Parameter(\"test\"):" + request.getParameter("test"));

Ressources :

Tracer les logs des échanges (appel et réponse) CXF entre le client et le serveur,

Apache CXF > Debugging and LoggingDebugging and Logging : Logging Messages

Tracer les demandes et réponses depuis le serveur
import org.apache.cxf.feature.Features;
 
@javax.jws.WebService(portName = "MyWebServicePort", serviceName = "MyWebService", ...)
@Features(features = "org.apache.cxf.feature.LoggingFeature")        // permet de tracer les échanges CXF
public class MyWebServicePortTypeImpl implements MyWebServicePortType {

ou

import org.apache.cxf.interceptor.InInterceptors;
import org.apache.cxf.interceptor.OutInterceptors;
 
@javax.jws.WebService(portName = "WebServicePort", serviceName = "WebServiceService", ...)
@InInterceptors(interceptors = "org.apache.cxf.interceptor.LoggingInInterceptor")        // permet de tracer les échanges CXF entrants
@OutInterceptors(interceptors = "org.apache.cxf.interceptor.LoggingOutInterceptor")        // permet de tracer les échanges CXF sortants
public class WebServicePortTypeImpl implements WebServicePortType {
Tracer les demandes et réponses depuis le client
import org.apache.cxf.endpoint.Client;
import org.apache.cxf.frontend.ClientProxy;
import org.apache.cxf.interceptor.LoggingInInterceptor;
import org.apache.cxf.interceptor.LoggingOutInterceptor;
 
public class WSClient {
    public static void main (String[] args) {
        MyService ws = new MyService();
        MyPortType port = ws.getPort();
 
        Client client = ClientProxy.getClient(port);
        client.getInInterceptors().add(new LoggingInInterceptor());        // permet de tracer les échanges CXF entrants
        client.getOutInterceptors().add(new LoggingOutInterceptor());        // permet de tracer les échanges CXF sortants
 
        // make WS calls...
Voir aussi

cxf serializable

<?xml version="1.0" encoding="UTF-8"?>
<jaxws:bindings wsdlLocation="YOUR_WSDL_LOCATION"
        xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
        <jaxws:bindings
                node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='YOUR_TARGET_NAMESPACE']">
                <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
                        xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
                        <jxb:serializable/>
                </jxb:globalBindings>
        </jaxws:bindings>
</jaxws:bindings>

Tel qu'Eclipse, en modifiant les options :

  • -fe jaxws => -fe jaxws21 //This constructor requires JAX-WS API 2.2. You will need to endorse the 2.2 //API jar or re-run wsdl2java with "-frontend jaxws21" to generate JAX-WS 2.1 //compliant code instead.
  • rajout d'un binding : -b http://w.placeoweb.com/wsdl/modif/TestSerializable.xml
wsdl2java ^
-client ^
-d C:\workspaceEclipse37Indigo\WsCxf\src ^
-classdir C:\workspaceEclipse37Indigo\WsCxf\build\classes ^
-p http://validation.placeoweb.com/=com.placeoweb.jaxws21 ^
-impl ^
-validate ^
-exsh false ^
-dns true ^
-dex true ^
-wsdlLocation http://localhost:9090/ServiceValiderSoapBindingImplPort?wsdl ^
-verbose ^
-defaultValues ^
-fe jaxws21 ^
-db jaxb ^
-wv 1.1 ^
-b http://w.placeoweb.com/wsdl/modif/TestSerializable.xml ^
http://ws.placeoweb.com/wsdl/modif/ServiceValider.wsdl
 
ERREUR RENCONTREE
org.apache.cxf.tools.common.ToolException: Could not find any node with the XPath expression: //wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='My_TARGET_NAMESPACE']

TestSerializable.xml

<?xml version="1.0" encoding="UTF-8"?>
<jaxws:bindings wsdlLocation="http://ws.placeoweb.com/wsdl/modif/ServiceValider.wsdl"
        xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
        <jaxws:bindings
				node="wsdl:definitions/wsdl:types/xs:schema">
                <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
                        xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
                        <jxb:serializable/>
                </jxb:globalBindings>
        </jaxws:bindings>
</jaxws:bindings>
<!--
 
        <jaxws:bindings
                node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace='YOUR_TARGET_NAMESPACE']">
                node="wsdl:definitions/wsdl:types/xs:schema[@targetNamespace=http://validation.placeoweb.com/]">
				node="wsdl:definitions/wsdl:types/xs:schema">	OK !!!
 
[Fatal Error] :8:1: Le type d'ÚlÚment "jaxws:bindings" doit Ûtre suivi des spÚcifications d'attribut, ">" ou "/>".
 
WSDLToJava Error: The binding file: http://ws.placeoweb.com/wsdl/modif/TestSerializable.xml references a not well-formed xml document
 
-->

ou encore plus simplement avec Eclipse et votre fichier xml à bindé (dans Binding Files: CxfSerializable.xml) prêt à l'emploi :

<?xml version="1.0" encoding="UTF-8"?>
<!-- CxfSerializable.xml -->
<jaxws:bindings
        xmlns:jaxws="http://java.sun.com/xml/ns/jaxws"
        xmlns:xs="http://www.w3.org/2001/XMLSchema"
        xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
        xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/">
        <jaxws:bindings
				node="wsdl:definitions/wsdl:types/xs:schema">
                <jxb:globalBindings xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
                        xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
                        <jxb:serializable/>
                </jxb:globalBindings>
        </jaxws:bindings>
</jaxws:bindings>
Loading FrontEnd jaxws ...
Loading DataBinding jaxb ...
wsdl2java -client -d D:\workspaceEclipse37Indigo\myProject\.cxftmp/src -classdir D:\workspaceEclipse37Indigo\myProject\build\classes -p http://validation.placeoweb.com/=com.placeoweb.jaxws21 -b D:\WS-CXF-Serializable\CxfSerializable.xml -impl -validate -exsh false -dns true -dex true -wsdlLocation http://localhost:9090/ServiceValiderSoapBindingImplPort?wsd -verbose -defaultValues -fe jaxws -db jaxb -wv 1.1 http://ws.placeoweb.com/wsdl/modif/ServiceValider.wsdl
wsdl2java - Apache CXF 2.5.1
// du coup les classes Java sont sérialisables :
 
import java.io.Serializable;
 
public class MyObject
    implements Serializable
{
// ...

cxf supprimer les Holder de WebParam.Mode.OUT

Pour comprendre le contexte : @WebService OUT params via javax.xml.ws.Holder

Utiliser @WebParam and javax.xml.ws.Holder : L'annotation @WebParam nous permet de déclarer les paramètres porteurs (Holders) en tant que WebParam.Mode.OUT de sortie.

Selon vos clients de web services (par exemple sous Android), il faudra simplifier en supprimant ces Holders (ce qui rajoutera un autre objet intermédiaire), tel que l'illustre jax-ws generation: @WebMethod vs. @ResponseWrapper :

Comme précédemment, on bind wsdl2java avec le fichier en paramètre (sous Eclipse, ou manuellement) :

-b D:\workspaceEclipse\WsMobile\jaxws-custom.xml
<!-- jaxws-custom.xml -->
<!--JAX-WD Customization: disable wrapper style rules
  see also: http://docs.oracle.com/cd/E17802_01/webservices/webservices/docs/2.0/jaxws/customizations.html#2.2_Wrapper_Style
-->
<jaxws:bindings wsdlLocation="v1.0/dxpInsurerServiceV1.0.wsdl" xmlns:jaxws="http://java.sun.com/xml/ns/jaxws">
   <jaxws:enableWrapperStyle>false</jaxws:enableWrapperStyle>
</jaxws:bindings>