Usando Java para manejar Tipos de Datos WSDL Personalizados
¿Qué sucede cuando ni el sistema de tipos WSDL ni el encoding default reúne las necesidades de tu aplicación? No te preocupes, puedes utilizar tipos de datos personalizados y formatos de encoding junto con Java para resolver el problema.
by Jeff Hanson
La envestida de la mensajería de los servicios web y transferencia de datos basados en XML ha llevado a la necesidad de expresar estos intercambios de mensajes en algunas formas estructuradas. El Web Services Description Language (WSDL) trata con esta necesidad de definir una gramática XML para exponer servicios como conjuntos de endpoints para intercambiar mensajes relacionados. Los documentos WSDL (pronouniado "wizduel") proporcionan un significado estándar para describir servicios esbozando los tipos de datos consumidos por los servicios, la URL para comunicarse con el servicio, y los nombres por los cuales son conocidos los servicios.
Los documentos WSDL están rápidamente llegando a ser la clave de éxito para la interoperabilidad B2B. Un documento WSDL proporciona una descripción genérica del servicio Web sin tener en cuenta el lenguaje de programación específico en el cual será escritos los servicios. Los desarrolladores pueden usar documentos WSDL para generar código cliente que pueda comunicarse con los servicios Web correspondientes. Esta forma genérica de descripción del servicio/componente se ha intentado en el pasado por varias formas binarias de lenguajes de descripción de interfaces (IDLs), pero nunca se había visto un uso tan extensivo como con WSDL y Web services.
Una razón para el éxito de la descripción de servicios basados en WSDL es el uso persuasivo de XML y su habilidad para definir virtualmente cualquier tipo de datos para cualquier lenguaje de programación en una forma genérica. Este artículo discute como manejar tipos de datos WSDL personalizados en el lenguaje de programación Java.
Introducción a WSDL
Los documentos WSDL son documentos XML que describen servicios como un conjunto de endpoints abstractos orientados a procedimientos o permitidos por el mensaje. Estas operaciones y/o mensajes y sus tipos de datos asociados son descritos conceptualmente, y luego son ligados concretamente a un protocolo de red, formato de mensaje, y lenguaje de programación como sea necesario.
Un documento WSDL define los siguientes elementos para describir servicios:
Los documentos WSDL están rápidamente llegando a ser la clave de éxito para la interoperabilidad B2B. Un documento WSDL proporciona una descripción genérica del servicio Web sin tener en cuenta el lenguaje de programación específico en el cual será escritos los servicios. Los desarrolladores pueden usar documentos WSDL para generar código cliente que pueda comunicarse con los servicios Web correspondientes. Esta forma genérica de descripción del servicio/componente se ha intentado en el pasado por varias formas binarias de lenguajes de descripción de interfaces (IDLs), pero nunca se había visto un uso tan extensivo como con WSDL y Web services.
Una razón para el éxito de la descripción de servicios basados en WSDL es el uso persuasivo de XML y su habilidad para definir virtualmente cualquier tipo de datos para cualquier lenguaje de programación en una forma genérica. Este artículo discute como manejar tipos de datos WSDL personalizados en el lenguaje de programación Java.
Introducción a WSDL
Los documentos WSDL son documentos XML que describen servicios como un conjunto de endpoints abstractos orientados a procedimientos o permitidos por el mensaje. Estas operaciones y/o mensajes y sus tipos de datos asociados son descritos conceptualmente, y luego son ligados concretamente a un protocolo de red, formato de mensaje, y lenguaje de programación como sea necesario.
Un documento WSDL define los siguientes elementos para describir servicios:
- Types— Definiciones de tipos de datos
- Message— Una definición abstracta de de los datos que van a ser transferidos
- Operation— Una descripción abstracta de un procedimiento de servicio
- Port Type— Un conjunto abstracto de operaciones soportadas por uno o más endpoints
- Binding— Un protocolo completo y formato de datos para un port type dado
- Port— Un simple endpoint definido como un enlazamiento y una dirección de red
- Service— Una colección de endpoints relacionados o puertos
WSDL y Tipos de Datos
Es retante para los proveedores de servicios web exponer un sistema de tipos de datos que pueda ser comprendido por el amplio rango de consumidores de servicios web,aunque debe haber lugar para la comprensión entre consumidores de servicios Web y proveedores,para comunicarse de forma efectiva. Debido a que diferentes lenguajes de programación tienen su propio conjunto de idiosincrasias, es de primordial importancia crear un sistema de tipos de datos común.
En contraste a los anteriores intentos a un lenguaje de definición de interfaces genérico (IDL) y un sistema de tipos de datos comunes, como COM, DCOM, y CORBA, WSDL resuelve el problema de tipos de datos comunes pretendiendo la máxima flexibilidad más que el intento de crear un estándar de escritura de datos todo-incluido. Asi, WSDL no está ligado a un sistema de tipo de datos. Sin embargo, WSDL recomienda la especificación de esquema XML de la W3C como el sistema de tipos canónico, de este modo, tratar de usar intrínsecamente el sistema de tipo de datos más ampliamente utilizado como el default.
Es retante para los proveedores de servicios web exponer un sistema de tipos de datos que pueda ser comprendido por el amplio rango de consumidores de servicios web,aunque debe haber lugar para la comprensión entre consumidores de servicios Web y proveedores,para comunicarse de forma efectiva. Debido a que diferentes lenguajes de programación tienen su propio conjunto de idiosincrasias, es de primordial importancia crear un sistema de tipos de datos común.
En contraste a los anteriores intentos a un lenguaje de definición de interfaces genérico (IDL) y un sistema de tipos de datos comunes, como COM, DCOM, y CORBA, WSDL resuelve el problema de tipos de datos comunes pretendiendo la máxima flexibilidad más que el intento de crear un estándar de escritura de datos todo-incluido. Asi, WSDL no está ligado a un sistema de tipo de datos. Sin embargo, WSDL recomienda la especificación de esquema XML de la W3C como el sistema de tipos canónico, de este modo, tratar de usar intrínsecamente el sistema de tipo de datos más ampliamente utilizado como el default.
WSDL y la Especificación XML Schema
Aunque puedes usar cualquier formato de encoding para definiciones de tipo WSDL, la especificación WSDL sugiere utilizar XML Schema Definitions (XSD). XSD o XML Schema es un estándar W3C que busca sustituir el estándar de definición de definición de tipos de documentos (DTD) para definir la estructura en un documento XML. XML Schema define un conjunto comprensivo de tipos de datos simples/primitivos, independientes del lenguaje de programación, como dobles, strings, y enteros, así como un mencanismo para crear tipos complejos usando los tipos simples predefinidos (vease la Tabla 1).Tabla 1. Tipos Simple de XML Schema: La tabla muestra una lista de los tipos simples predefinidos en XSD.
Tipo Simple
|
Ejemplos
|
string
|
Esta es una cadena
|
normalizedString
|
Esta es una cadena normalizada
|
token
|
Este es un token
|
base64Binary
|
GpM7
|
hexBinary
|
0FB7
|
integer
|
-1, 0, 103
|
positiveInteger
|
1, 2, 215
|
negativeInteger
|
-563, -2, -1
|
nonNegativeInteger
|
0, 1, 2, 672
|
nonPositiveInteger
|
37 -2, -1, 0
|
long
|
-9223372036854775808, ... -1, 0, 1, ... 9223372036854775807
|
unsignedLong
|
0, 1, ... 18446744073709551615
|
int
|
-2147483648, ... -1, 0, 1, ... 2147483647
|
unsignedInt
|
0, 1, ...4294967295
|
short
|
-32768, ... -1, 0, 1, ... 32767
|
unsignedShort
|
0, 1, ... 65535
|
byte
|
-128, ...-1, 0, 1, ... 127
|
unsignedByte
|
0, 1, ... 255
|
decimal
|
-1.23, 0, 123.4, 1000.00
|
float
|
-INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN
|
double
|
-INF, -1E4, -0, 0, 12.78E-2, 12, INF, NaN
|
boolean
|
true, false, 1, 0
|
duration
|
P1Y2M3DT10H30M12.3S
|
dateTime
|
1999-05-31T13:20:00.000-05:00
|
date
|
1999-05-31
|
time
|
13:20:00.000, 13:20:00.000-05:00
|
gYear
|
1999
|
gYearMonth
|
1999-02
|
gMonth
|
—05
|
gMonthDay
|
—05-31
|
gDay
|
—-31
|
Name
|
shipTo
|
QName
|
po:USAddress
|
NCName
|
USAddress
|
anyURI
|
http://www.example.com/,http://www.example.com/doc.html#ID5
|
language
|
en-GB, en-US, fr
|
El elemento
XML (WSDL)
|
Listing 1: Simple WSDL Document with Defined Types:
|
Aunque no se requiere incluir el elemento
|
<?xml version="1.0" encoding="UTF-8"? >
<wsdl:definitions xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns="http://schemas.xmlsoap.org/wsdl/">
<wsdl:types>
<import namespace="http://schemas.xmlsoap.org/soap/encoding/"/>
<complexType name="HelloWorld">
<sequence>
<element name="message" type="string" minOccurs="1"/>
</sequence>
</complexType>
</schema>
</wsdl:types>
<wsdl:message name="HelloWorldResponse">
<wsdl:part name="return" type="HelloWorld"/>
</wsdl:message>
<wsdl:message name="HelloWorldRequest"<>/wsdl:message>
<wsdl:portType name="HelloWorldService">
<wsdl:binding name="AxisServletSoapBinding" type="intf:HelloWorldService">
<wsdl:service name="HelloWorldService">
<wsdl:operation name="HelloWorld">
<wsdl:input name="HelloWorldRequest" message="intf:HelloWorldRequest"/>
<wsdl:output name="HelloWorldResponse" message="intf:HelloWorldResponse"/>
</wsdl:operation>
</wsdl:portType><wsdl:binding name="AxisServletSoapBinding" type="intf:HelloWorldService">
<wsdlsoap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation name="HelloWorld">
<wsdlsoap:operation soapAction=""/>
<wsdl:input name="HelloWorldRequest">
<wsdlsoap:body use="encoded"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:helloworld"/ >
</wsdl:input>
<wsdl:output name="HelloWorldResponse">
<wsdlsoap:body use="encoded"
encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
namespace="urn:helloworld"/ >
</wsdl:output>
</wsdl:operation>
</wsdl:binding><wsdl:service name="HelloWorldService">
<wsdl:port name="HelloWorldServlet" binding="intf:AxisServletSoapBinding">
<wsdlsoap:address location="http://127.0.0.1/services/HelloWorld"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>
Declarar Nuevos Tipos de Datos en un Documento WSDL
La especificación XML Schema proporciona una característica para definir tipos de datos personalizados. Siempre que un servicio requiera datos que pueden ser representados de forma más conveniente con abstracciones más allá del alcance de los tipos de datos XML simples, estas abstracciones pueden ser declaradas como nuevos tipos de datos en el elemento del WSDL. El ejemplo en la Lista 1 definió el tipo de datos personalizado mostrado a continuación:
La especificación XML Schema proporciona una característica para definir tipos de datos personalizados. Siempre que un servicio requiera datos que pueden ser representados de forma más conveniente con abstracciones más allá del alcance de los tipos de datos XML simples, estas abstracciones pueden ser declaradas como nuevos tipos de datos en el elemento
La definición representa el tipo de datos mensaje como una cadena simple, y la nueva definición de tipo agrega una restricción al tipo de dato —se requiere que el elemento aparezca debido a que el valor del atributo minOccurs es mayor a cero.
Un uso más sofisticado del tipo de datos podría incluir información del contacto para un usuario como el siguiente:
Un uso más sofisticado del tipo de datos podría incluir información del contacto para un usuario como el siguiente:
En el ejemplo anterior, define un tipo de datos personalizado que encapsula información del contacto usuario. Nota que el elemento elemento está definido como una simple string, permitiendo virtualmente que cualquier contenido de cualquier tamaño ocurra en el elemento. Un método más robusto restringiría el elemento estado a una abreviación de dos letras, definiendo un tipo de datos personalizado “estado de dos letras" y luego referenciar ese en el tipo de datos . Aquí hay un tipo de datos string personalizado restringido a una longitd de dos:
Es relativamente fácil ver la relación entre las definiciones de tipos de datos en XSD schema y definiciones de objetos en Java (u otros lenguajes) expresados en código. Puedes hacer explícita esta relación usando software de mapeo.
Tipos de Dato XSD y Tipos de Dato Java
El lenguaje de programación Java proporciona tipos de datos que pueden ser mapeados para representar la mayoría de tipos de datos XSD estándar. La tabla 2 contiene una lista de mapeos de los tipos de datos XSD a tipos de datos Java:
Tabla 2. Mapeos XSD-a-Java: La tabla muestra como puedes mapear una lista de tipos de datos XSD a sus equivalentes en Java.
Tipos de Dato XSD y Tipos de Dato Java
El lenguaje de programación Java proporciona tipos de datos que pueden ser mapeados para representar la mayoría de tipos de datos XSD estándar. La tabla 2 contiene una lista de mapeos de los tipos de datos XSD a tipos de datos Java:
Tabla 2. Mapeos XSD-a-Java: La tabla muestra como puedes mapear una lista de tipos de datos XSD a sus equivalentes en Java.
Tipo XSD
|
Tipo Java
|
base64Binary
|
byte[]
|
hexBinary
|
byte[]
|
boolean
|
Boolean
|
byte
|
Byte
|
dateTime
|
java.util.Calendar
|
date
|
java.util.Calendar
|
time
|
java.util.Calendar
|
decimal
|
java.math.BigDecimal
|
double
|
Double
|
float
|
Float
|
hexBinary
|
byte[]
|
int
|
Int
|
unsignedShort
|
Int
|
integer
|
java.math.BigInteger
|
long
|
Long
|
unsignedInt
|
Long
|
QName
|
javax.xml.namespace.QName
|
short
|
Short
|
unsignedByte
|
Short
|
string
|
java.lang.String
|
anySimpleType
|
java.lang.String
|
El mapeo en la Tabla 2 ilustra una lista comprensiva de mapeos de tipos de datos simple; sin embargo, de forma que necesites abstracciones más complejas y necesites extender los tipos XSD con declaraciones d tipos personalizados,también llega a ser más complejo mapear tales tipos a Java. El mapeo de declaraciones de tipos personalizados es el foco de este artículo. Primero, aunque, hay una breve introducción de las herramientas XML que necesitarás para implementar las operaciones de mapeo.
Streaming API for XML (StAX)
XSD y WSDL son gramáticas basadas en XML que puedes procesar usando técnicas de procesamiento XML estándar. El procesamiento XML en Java se ha involucrado en dos enfoques:
- La Simple API for XML processing (SAX)
- El Modelo de Objetos de Documento (DOM)
SAX expone una API de parseo estilo callback, mientras que DOM provee una estructura como árbol accesible aleatoriamente.
La especificación Streaming API for XML (StAX) define una nueva y altamente eficiente API para parseo y streaming XML. La especificación StAX defines una bidireccional para lectura y escritura de XML. StAX permite a los desarrolladores mantener el control del parseo exponiendo una API simple basada en iterador, con métodos intuitivos como next() y hasNext(), así como un flujo subyacente de eventos. Esta API basada en iterador te permite "jalar" el siguiente evento más que manejar el evento en una callback. La API cursor facilita el control de procesamiento aún más permitiéndote detener el procesamiento, evita hacia adelante las secciones de un documento, y retoma subsecciones de un documento.
Introducción a XMLBeans
Apache XMLBeans es una herramienta de bnding XML-Java open source, basada en la especificación StAX. Puedes usar XMLBeans para generar clases Java e interfaces desde un XML schema, subsecuentemente usando esas clases Java generadas para parsear o generar documentos XML que conforman el esquema.
BEA originó XMLBeans y luego lo donó a la Apache Software Foundation. XMLBeans proporciona tres APIs más amplias para accesar a XML y schema:
La especificación Streaming API for XML (StAX) define una nueva y altamente eficiente API para parseo y streaming XML. La especificación StAX defines una bidireccional para lectura y escritura de XML. StAX permite a los desarrolladores mantener el control del parseo exponiendo una API simple basada en iterador, con métodos intuitivos como next() y hasNext(), así como un flujo subyacente de eventos. Esta API basada en iterador te permite "jalar" el siguiente evento más que manejar el evento en una callback. La API cursor facilita el control de procesamiento aún más permitiéndote detener el procesamiento, evita hacia adelante las secciones de un documento, y retoma subsecciones de un documento.
Introducción a XMLBeans
Apache XMLBeans es una herramienta de bnding XML-Java open source, basada en la especificación StAX. Puedes usar XMLBeans para generar clases Java e interfaces desde un XML schema, subsecuentemente usando esas clases Java generadas para parsear o generar documentos XML que conforman el esquema.
BEA originó XMLBeans y luego lo donó a la Apache Software Foundation. XMLBeans proporciona tres APIs más amplias para accesar a XML y schema:
- Acceso fuertemente tipeado—XMLBeans puede compilar un esquema XML para generar clases Java e interfaces. Las clases e interfaces generadas extienden una clase base común y proporcionan getters y setters fuertemente tipeados para cada uno de los elementos encontrados en el esquema.
- Acceso estilo cursor— Desde cualquier clase clase generada puedes obtener una instancia de un objeto cursor posicional que permite acceso de bajo nivel a la información XML.
- Acceso estilo Schema—XMLBeans proporcionan un modelo de objetos esquema que puedes usar para reflejar en el XML schema.
Instalando XMLBeans
Para instalar XMLBeans, descarga la distribución binaria de XMLBeans, y extrae el archivo en el directorio de tu elección. A continuación, define una variable de entorno XMLBEANS_HOME con un valor asignado al directorio donde extrajiste los archivos de la distribución binaria. Finalmente, agrega los archivos .jar y .zip contenidos en la distribución XMLBeans a tu proyecto.
El resto de este artículo demuestra cómo implementar un intérprete WSDL-a-Java simple usando el framework XMLBeans y las APIs. Es importante comprender como los proveedores de Web service adoptan cada vez más WSDL como la doctrina de intercambio para integración con sus sistemas vía servicios accesibles públicamente, los clientes de servicios deben tener la habilidad de procesar dinámicamente WSDL para entregar esos servicios. Esto es porque el documento WSDL frecuentemente puede ser el punto de acceso a la información del servicio. Afortunadamente, cuando se prepara de forma adecuada, el documento WSDL es todo lo que los clientes necesitan.
El framework XMLBeans facilita la habilidad para compilar un archivo WSDL en objetos Java. Con esta facilidad, los desarrolladores pueden generar dinámicamente clientes de Web service desde documentos WSDL, usando las clases Java resultantes e interfaces asociadas con los tipos de datos y métodos del Web service. Interpretar dinámicamente WSDL ofrece un grado de poder más grande que el parseo de XML estático estándar y las técnicas de procesamiento.
Para instalar XMLBeans, descarga la distribución binaria de XMLBeans, y extrae el archivo en el directorio de tu elección. A continuación, define una variable de entorno XMLBEANS_HOME con un valor asignado al directorio donde extrajiste los archivos de la distribución binaria. Finalmente, agrega los archivos .jar y .zip contenidos en la distribución XMLBeans a tu proyecto.
El resto de este artículo demuestra cómo implementar un intérprete WSDL-a-Java simple usando el framework XMLBeans y las APIs. Es importante comprender como los proveedores de Web service adoptan cada vez más WSDL como la doctrina de intercambio para integración con sus sistemas vía servicios accesibles públicamente, los clientes de servicios deben tener la habilidad de procesar dinámicamente WSDL para entregar esos servicios. Esto es porque el documento WSDL frecuentemente puede ser el punto de acceso a la información del servicio. Afortunadamente, cuando se prepara de forma adecuada, el documento WSDL es todo lo que los clientes necesitan.
El framework XMLBeans facilita la habilidad para compilar un archivo WSDL en objetos Java. Con esta facilidad, los desarrolladores pueden generar dinámicamente clientes de Web service desde documentos WSDL, usando las clases Java resultantes e interfaces asociadas con los tipos de datos y métodos del Web service. Interpretar dinámicamente WSDL ofrece un grado de poder más grande que el parseo de XML estático estándar y las técnicas de procesamiento.
Construyendo Intérpretes WSDL Personalizados con XMLBeans
La clase WSDL2Java siguiente es un ejemplo de un intérprete WSDL-to-Java simple que usa XMLBeans. Puedes descargar todo el código fuente de este artículo para continuar comprendiendo.
package com.jeffhanson.clienttier;
import org.apache.xmlbeans.*;
import org.apache.xmlbeans.impl.xb.xsdschema.*;
import org.apache.xmlbeans.impl.xb.xsdschema.impl.*;
import org.apache.xmlbeans.impl.xb.substwsdl.*;
import org.apache.xmlbeans.impl.util.FilerImpl;
import org.apache.xmlbeans.impl.schema.SchemaTypeSystemCompiler;
import org.apache.xmlbeans.impl.schema.SchemaTypeLoaderImpl;
import org.apache.xmlbeans.impl.schema.StscState;
import org.apache.xmlbeans.impl.common.XmlErrorWatcher;
import org.apache.xmlbeans.impl.common.IOUtil;
import java.util.*;
import java.io.File;
import repackage.Repackager;
public class WSDL2Java {
private static class MyResolver implements org.xml.sax.EntityResolver{
public org.xml.sax.InputSource resolveEntity(
String publicId,
String systemId){
System.out.println("System ID: " + systemId);
return null;
}
}
...
El método generado mostrado en la Lista 2 parsea un archivo WSDL dado y genera código Java que representa los tipos de dato esncontrados en la sección del documento WSDL.
Lista 2. El método generate:
|
Este método parsea un archivo WSDL y genera código Java representando los tipos de datos encontrados en la sección
|
...
public List generate(String schemaFilesDir, String schemaClassesDir,
String schemaSrcDir, String wsdlFileName){
boolean doNotValidateContents = false;
XmlObject wsdlDoc = null;
MyResolver entityResolver = new MyResolver();
ArrayList outerErrorListener = new ArrayList();
XmlErrorWatcher errorListener = new XmlErrorWatcher(outerErrorListener);
ArrayList scontentlist = new ArrayList();
try{
SchemaTypeLoader loader = XmlBeans.typeLoaderForClassLoader(
SchemaDocument.class.getClassLoader());
XmlOptions options = new XmlOptions();
options.setLoadLineNumbers();
options.setLoadSubstituteNamespaces(Collections.singletonMap(
"http://schemas.xmlsoap.org/wsdl/",
"http://www.apache.org/internal/xmlbeans/wsdlsubst"));
options.setEntityResolver(entityResolver);
System.out.println("Parsing WSDL: " + wsdlFileName + "...");
wsdlDoc = loader.parse(new File(wsdlFileName), null, options);
if (!(wsdlDoc instanceof DefinitionsDocument)){
// Create new definitions doc
DefinitionsDocument.Definitions definitions = DefinitionsDocument.
Definitions.Factory.newInstance();
// Set types array
definitions.setTypesArray(
wsdlDoc.selectPath("wsdl:types"));
DefinitionsDocument defDoc =
DefinitionsDocument.Factory.newInstance();
defDoc.setDefinitions(definitions);
// Adding constructed schema
addWsdlSchemas(wsdlFileName,
defDoc, errorListener,
doNotValidateContents, scontentlist);
}
else
{
addWsdlSchemas(wsdlFileName,
(DefinitionsDocument)wsdlDoc, errorListener,
doNotValidateContents, scontentlist);
}
}
catch (XmlException e)
{
errorListener.add(e.getError());
}
catch (Exception e)
{
StscState.addError(errorListener,
XmlErrorCodes.CANNOT_LOAD_FILE,
new Object[] {
"wsdl", wsdlFileName,
e.getMessage() },wsdlDoc);
}
SchemaTypeSystem sts =
compileSchemas(schemaFilesDir,
scontentlist, entityResolver,
errorListener);
return generateJavaSource(schemaClassesDir,
schemaSrcDir, sts);
}
...
|
El método compileSchemas crea los archivos de esquema específicos de XMLBeans (.xsb's) y los guarda al disco.
private SchemaTypeSystem compileSchemas(
String schemaFilesDir, ArrayList scontentlist,
MyResolver entityResolver,
XmlErrorWatcher errorListener){
SchemaDocument.Schema[] sdocs =
(SchemaDocument.Schema[])scontentlist.toArray(
new SchemaDocument.Schema[scontentlist.size()]);
ResourceLoader cpResourceLoader = null;
SchemaTypeLoader linkTo = SchemaTypeLoaderImpl.build(null,cpResourceLoader, null);
File baseDir = new File(System.getProperty("user.dir"));
java.net.URI baseURI = baseDir.toURI();
XmlOptions opts = new XmlOptions();
opts.setCompileNoValidation();
opts.setEntityResolver(entityResolver);
Map sourcesToCopyMap = new HashMap();
File schemasDir = IOUtil.createDir(new File("."), schemaFilesDir);
// create parameters for the main compile function
SchemaTypeSystemCompiler.Parameters params = new
SchemaTypeSystemCompiler.Parameters();
params.setName(null);
params.setSchemas(sdocs);
params.setLinkTo(linkTo);
params.setOptions(opts);
params.setErrorListener(errorListener);
params.setJavaize(true);
params.setBaseURI(baseURI);
params.setSourcesToCopyMap(sourcesToCopyMap);
params.setSchemasDir(schemasDir);
System.out.println("Compiling schemas...");
try{
// create schema files (.xsb's)
SchemaTypeSystem sts = SchemaTypeSystemCompiler.compile(params);
// now save .xsb's to disk
sts.saveToDirectory(schemasDir);
System.out.println("Schema compilation succeeded");
return sts;
}
catch (Exception e){
e.printStackTrace();
}
return null;
}
El método generateJavaSource genera archivos fuente Java para los tipos de datos WSDL que han sido previamente agregados a un sistema de tipos dado.
private List generateJavaSource(String schemaClassesDir,
String schemaSrcDir, SchemaTypeSystem sts){
File classesDir = new File(schemaClassesDir);
File srcDir = IOUtil.createDir(new File("."),schemaSrcDir);
// now, generate the source files
XmlOptions options = new XmlOptions();
boolean verbose = false;
boolean incrSrcGen = false;
Repackager repackager = null;
FilerImpl filer = new FilerImpl(classesDir,
srcDir, repackager, verbose, incrSrcGen);
System.out.println("Generating Java source...");
if (SchemaTypeSystemCompiler.generateTypes(sts,filer, options)){
System.out.println("Java source generation succeeded");
return filer.getSourceFiles();
}else{
System.out.println("Java source generation failed");
}
return null;
}
El método addWsdlSchemas mostrado en la Lista 3 extrae el array desde un documento de definición WSDL y agrega los esquemas que representan cada tipo a la lista de contenido.
Lista 3: El método addWsdlSchemas:
| |
Este método extrae el array
| |
private void addWsdlSchemas(String wsdlFileName,
DefinitionsDocument definitionsDocument,
XmlErrorWatcher errorListener,
boolean doNotValidateContents,
ArrayList scontentlist){
XmlOptions opts = new XmlOptions().setErrorListener(errorListener);
if (doNotValidateContents){
opts.setValidateTreatLaxAsSkip();
}
XmlObject[] types = definitionsDocument.getDefinitions().getTypesArray();
for (int j = 0; j < types.length; j++){
XmlObject[] schemas = types[j].selectPath("declare namespace"
+ " xs=\"http://www.w3.org/2001/XMLSchema\""
+ " xs:schema");
if (schemas.length == 0){
StscState.addWarning(errorListener, "The WSDL " + wsdlFileName
+ " has no schema documents in namespace "
+ "'http://www.w3.org/2001/XMLSchema'",
XmlErrorCodes.GENERIC_ERROR, definitionsDocument);
continue;
}
for (int k = 0; k < schemas.length; k++){
if (schemas[k] instanceof SchemaDocument.Schema){
SchemaDocumentImpl.SchemaImpl schemaImpl = (SchemaDocumentImpl.SchemaImpl)schemas[k];
System.out.println("Validating schema...");
if (schemaImpl.validate(opts)){
System.out.println("Schema passed validation");
scontentlist.add(schemas[k]);
}else{
System.out.println("Schema failed validation");
scontentlist.add(schemas[k]);
}
}
}
}
}
|
La clase JavaSourceCompiler usa utilidades de la API XMLBeans para compilar archivos fuente Java generados anteriormente:
package com.jeffhanson.clienttier;
import org.apache.xmlbeans.impl.tool.CodeGenUtil;
import org.apache.xmlbeans.impl.common.IOUtil;
import java.io.File;
import java.util.List;
public class JavaSourceCompiler{
public JavaSourceCompiler(){}
public void generate(String schemasDirName,List sourceFiles,String classesDirName){
File classesDir = new File(classesDirName);
File schemasDir = IOUtil.createDir(new File("."), schemasDirName);
boolean verbose = false;
// now, compile source files
String compiler = "/tools/VMs/j2sdk1.4.2_04/bin/javac.exe";
File[] tempClasspath = CodeGenUtil.systemClasspath();
File[] classpath = new File[tempClasspath.length + 1];
System.arraycopy(tempClasspath, 0, classpath, 0, tempClasspath.length);
classpath[tempClasspath.length] = schemasDir;
boolean debug = false;
String javasource = null;
String memoryInitialSize = CodeGenUtil.DEFAULT_MEM_START;
String memoryMaximumSize = CodeGenUtil.DEFAULT_MEM_MAX;
boolean quiet = true;
System.out.println("Compiling Java source files...");
if (CodeGenUtil.externalCompile( sourceFiles, classesDir,
classpath, debug, compiler, javasource,
memoryInitialSize, memoryMaximumSize,
quiet, verbose)){
System.out.println("Source compile succeeded");
}else{
System.out.println("Source compile failed");
}
}
}
Les insto a descargar el código fuente para este artículo y experimentar con ello por ti mismo. La mensajería de Web y la transferencia de datos basados en XML ha creado una necesidad para expresar de una forma estructurada el intercambio de mensajes. El Web services Description Language (WSDL) trata con esta necesidad definiendo una descripción de servicio basada en XML y un sistema de tipos de datos genéricos para cualquier lenguaje de programación.
El sistema de tipo de datos WSDL define tipos de datos que pueden ser intercambiados entre consumidores y proveedores de servicios. WSDL te permite usar los tipos simples de XML-Schema incorporados, o puedes definir tuspropios tipos personalizados.
La especificación de la API de Streaming API para XML (StAX) defines una nueva API que usa una API bidireccional bidireccional para parsing y streaming XML. StAX te permite mantener el control del parsing exponiendo una API simple basada en iterador, así como una API de cursor. La API basada en iterator te permite “jalar” eventos como sea necesario. La API cursor facilitates el control del procesamiento aún más permitiéndote detener el procesamiento, salta hacia adelante las secciones de un documento, y retoma las subsecciones de un documento.
Apache XMLBeans (originado por BEA y luego donado a Apache) es una herramienta de binding Java-XML open source, basada en la especificación StAX que puede utilizarse para generar clases Java e interfaces desde un esquema XML. Estas clases e interfaces pueden utilizarse para parsear o generar documentos XML que conforman el esquema.
La combinacion de StAX y el framework XMLBeans fle permite a los desarrolladores para interpretar dinámicamente y operar sobre documentos WSDL y los tipos de datos declarados adentro con un grado más grande de poder y flexibilidad que el parseo XML estático estándar y técnicas de procesamiento.
El sistema de tipo de datos WSDL define tipos de datos que pueden ser intercambiados entre consumidores y proveedores de servicios. WSDL te permite usar los tipos simples de XML-Schema incorporados, o puedes definir tuspropios tipos personalizados.
La especificación de la API de Streaming API para XML (StAX) defines una nueva API que usa una API bidireccional bidireccional para parsing y streaming XML. StAX te permite mantener el control del parsing exponiendo una API simple basada en iterador, así como una API de cursor. La API basada en iterator te permite “jalar” eventos como sea necesario. La API cursor facilitates el control del procesamiento aún más permitiéndote detener el procesamiento, salta hacia adelante las secciones de un documento, y retoma las subsecciones de un documento.
Apache XMLBeans (originado por BEA y luego donado a Apache) es una herramienta de binding Java-XML open source, basada en la especificación StAX que puede utilizarse para generar clases Java e interfaces desde un esquema XML. Estas clases e interfaces pueden utilizarse para parsear o generar documentos XML que conforman el esquema.
La combinacion de StAX y el framework XMLBeans fle permite a los desarrolladores para interpretar dinámicamente y operar sobre documentos WSDL y los tipos de datos declarados adentro con un grado más grande de poder y flexibilidad que el parseo XML estático estándar y técnicas de procesamiento.
Jeff Hanson tiene más de 18 años de experiencia en la industria del softwar. Él ha trabajado como Sr Ingeniero para el Windows OpenDoc port and as lead architect for the Route 66 framework at Novell. He is currently Chief Architect for eReinsure, which specializes in providing frameworks and platforms for J2EE-based reinsurance systems. Jeff has also authored numerous articles and books.