ORVE WS (Dynamic) (1). Analising the WSDL and creating classes

1. Introduction


Our target is building a WS Client for ORVE

There is an introductory manual for this.

Let's create the client in a dynamic way, as the previous post

Java 10 will be used. Take care from java versions newer than 1.8 as they do not include XML libraries in the jvm.

To use these WS from ORVE, we need a user and a password. For security reasons, my user and password is not public so a generic user and password will be displayed in this post

2. The WSDL

The WDSL URL is:

https://ssweb.seap.minhap.es/demoorve/WSExportacion.wsdl

The WDSL response is:


  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
<wsdl:definitions xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:tns="https://ssweb.seap.minhap.es/demoorve/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" name="WSExportacion" targetNamespace="https://ssweb.seap.minhap.es/demoorve/">
<wsdl:types xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="https://ssweb.seap.minhap.es/demoorve/">
<xsd:complexType name="Security">
<xsd:sequence>
<xsd:element name="username" type="xsd:string"/>
<xsd:element name="password" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="SecurityElement" type="tns:Security"/>
<xsd:complexType name="FiltrosIdentificadores">
<xsd:sequence>
<xsd:element name="estado" type="xsd:string"/>
<xsd:element name="oficina" type="xsd:string"/>
<xsd:element name="unidad" type="xsd:string"/>
<xsd:element name="numeroRegistro" type="xsd:string"/>
<xsd:element name="fechaInicio" type="xsd:string"/>
<xsd:element name="fechaFin" type="xsd:string"/>
<xsd:element name="historico" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="FiltrosIdentificadoresElement" type="tns:FiltrosIdentificadores"/>
<xsd:complexType name="obtenerIdentificaoresRespuestaWS">
<xsd:sequence>
<xsd:element name="codigo" type="xsd:string"/>
<xsd:element name="descripcion" type="xsd:string"/>
<xsd:element name="identificadores" type="tns:AnyTypeArray"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="obtenerIdentificaoresRespuestaWSElement" type="tns:obtenerIdentificaoresRespuestaWS"/>
<xsd:complexType name="AnyTypeArray">
<xsd:sequence>
<xsd:element name="item" type="xsd:anyType" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="AnyTypeArrayElement" type="tns:AnyTypeArray"/>
<xsd:complexType name="obtenerRegistroRespuestaWS">
<xsd:sequence>
<xsd:element name="codigo" type="xsd:string"/>
<xsd:element name="descripcion" type="xsd:string"/>
<xsd:element name="registro" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
<xsd:element xmlns:xsd="http://www.w3.org/2001/XMLSchema" name="obtenerRegistroRespuestaWSElement" type="tns:obtenerRegistroRespuestaWS"/>
</xsd:schema>
</wsdl:types>
<wsdl:portType name="WSExportacionPortType">
<wsdl:operation name="obtenerIdentificadores" parameterOrder="Security filtros">
<wsdl:input message="tns:obtenerIdentificadoresRequest"/>
<wsdl:output message="tns:obtenerIdentificadoresResponse"/>
</wsdl:operation>
<wsdl:operation name="obtenerRegistro" parameterOrder="Security identificador">
<wsdl:input message="tns:obtenerRegistroRequest"/>
<wsdl:output message="tns:obtenerRegistroResponse"/>
</wsdl:operation>
</wsdl:portType>
<wsdl:binding xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="WSExportacionBinding" type="tns:WSExportacionPortType">
<soap:binding xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>
<wsdl:operation xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="obtenerIdentificadores">
<soap:operation xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" soapAction="https://ssweb.seap.minhap.es/demoorve/obtenerIdentificadores" style="rpc"/>
<wsdl:input xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<soap:body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" parts="filtros" use="literal" namespace="https://ssweb.seap.minhap.es/demoorve/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<soap:header xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" message="tns:obtenerIdentificadoresRequest" part="Security" use="literal" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</wsdl:input>
<wsdl:output xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<soap:body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" parts="resultado" use="literal" namespace="https://ssweb.seap.minhap.es/demoorve/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<soap:header xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" message="tns:obtenerIdentificadoresResponse" part="Security" use="literal" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="obtenerRegistro">
<soap:operation xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" soapAction="https://ssweb.seap.minhap.es/demoorve/obtenerRegistro" style="rpc"/>
<wsdl:input xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<soap:body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" parts="identificador" use="literal" namespace="https://ssweb.seap.minhap.es/demoorve/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<soap:header xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" message="tns:obtenerRegistroRequest" part="Security" use="literal" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</wsdl:input>
<wsdl:output xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/">
<soap:body xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" parts="resultado" use="literal" namespace="https://ssweb.seap.minhap.es/demoorve/" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
<soap:header xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" message="tns:obtenerRegistroResponse" part="Security" use="literal" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
<wsdl:message name="obtenerIdentificadoresRequest">
<wsdl:part name="Security" element="tns:SecurityElement"/>
<wsdl:part name="filtros" type="tns:FiltrosIdentificadores"/>
</wsdl:message>
<wsdl:message name="obtenerIdentificadoresResponse">
<wsdl:part name="Security" element="tns:SecurityElement"/>
<wsdl:part name="resultado" type="tns:obtenerIdentificaoresRespuestaWS"/>
</wsdl:message>
<wsdl:message name="obtenerRegistroRequest">
<wsdl:part name="Security" element="tns:SecurityElement"/>
<wsdl:part name="identificador" type="xsd:int"/>
</wsdl:message>
<wsdl:message name="obtenerRegistroResponse">
<wsdl:part name="Security" element="tns:SecurityElement"/>
<wsdl:part name="resultado" type="tns:obtenerRegistroRespuestaWS"/>
</wsdl:message>
<wsdl:service xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="WSExportacionService">
<wsdl:port xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" name="WSExportacionPort" binding="tns:WSExportacionBinding">
<soap:address xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" location="https://ssweb.seap.minhap.es/demoorve/WSExportacion.php"/>
</wsdl:port>
</wsdl:service>
</wsdl:definitions>


3.The name of the package


The package of the class is located in line 3 with the tag

<xsd:schema ... targetNamespace="https://ssweb.seap.minhap.es/demoorve/">

And changing:

  "://"  with "."
  "," with "_"
  "/" with "."

The package is :

https.ssweb_seap_minhap_es.demoorve


4. Classes to use

There are 4 main classes

4.1 Class "Security"

WDSL Line 4
Purpose: Defines the login properties used in the HEAD of the WS
Attributes:
  • username (String)
  • password (String)

4.2 Class "FiltrosIdentificadores"

WDSL Line 11
Purpose: To narrow down the query results 
Attributes:
  • estado (String) The phase of the record to retrieve
  • oficina (String) The DIR3 office
  • unidad (String) The DIR3 unit
  • numeroRegistro (String) Record number
  • fechaInicio (String) Begining data
  • fechaFin (String) End date
  • historico (String) History

4.3 Class "ObtenerIdentificaoresRespuestaWS" 

WDSL Line 23
Purpose: Returns the ids of the records. It is the response of a request 
Attributes:
  • codigo (String) If "00" then no error reported, else an error is reported
  • descripcion (String) Describes a resume of the response.
  • identificadores (AnyTypeArray) An array or list of the ids

4.4 Class "ObtenerRegistroRespuestaWS"

WDSL Line 37
Purpose: Returns the record that matches a provided id. It is the response of a request 
Attributes:
  • codigo (String) If "00" then no error reported, else an error is reported
  • descripcion (String) Describes a resume of the response.
  • registro (String) A complex element that defines the record


5. Services to use (Requests)

2 services will be used:

5.1 Service "obtenerIdentificadores"

WDSL Line 48
Purpose: Gets the ids of the records to retrieve
Input parameter: obteneridentificadoresRequest  (line 49) that consists of
  • Security line 83
  • Filtrosidentificadores line 84
Output parameter: obtenerIdentificadoresResponse  (line 50) that consists of
  • Security line 87
  • ObtenerIdentificaoresRespuestaWS line 88

5.2 Service "obtenerRegistro"

WDSL Line 52
Purpose: Gets the record of a supplied ids
Input parameter: obtenerRegistroRequest  (line 53) that consists of
  • Security line 91
  • Identificator (int) line 92
Output parameter: obtenerRegistroResponse  (line 54) that consists of
  • Security line 95
  • ObtenerRegistroRespuestaWS line 96

6. Creating classes with wsdl2java

Although the dynamic way is preferred, many problems have arisen in this project, so it is not a bad idea to create the classes with the wsdl2tava command and inspect the generated code. 

6.1 Select java 1.8 version (Now There is compatibility with Java 13)


First, the Java 1.8 version (or older) is needed for compatibility use of wsdl2java command. 

In Ubuntu, it is required to change java and javac. For java:


sudo update-alternatives --config java

and select the java version


  Selection   Path                                             Priority   State
------------------------------------------------------------
  0            /usr/lib/jvm/java-10-oracle/bin/java               1091      mode automàtic
  1            /home/eduard/ProgramesMeus/jdk-10.0.1/bin/java     1         mode manual
* 2            /home/eduard/ProgramesMeus/jdk1.8.0_181/bin/java   1         mode manual
  3            /usr/lib/jvm/java-10-openjdk-amd64/bin/java        1         mode manual
  4            /usr/lib/jvm/java-10-oracle/bin/java               1091      mode manual
  5            /usr/lib/jvm/java-8-openjdk-amd64/jre/bin/java     1081      mode manual
  6            /usr/lib/jvm/java-9-openjdk-amd64/bin/java         1091      mode manual
  7            /usr/lib/jvm/java-9-oracle/bin/java                1091      mode manual

Press return for default option[*], or input a selection number: 

For javac (compiler), it is similar

sudo update-alternatives --config javac

and select the javac version as the previous step.

It is important to test our java version trying these commands


java  -version
javac -version

6.2 Generate the classes 

 Download Apache CXF if you have not yet downloaded it and extract it into a folder.

Open a terminal, go into the generated "bin" folder and execute

UPDATE: As you can use with java 13, you need now this environment variables to be set 
$JAVA_HOME
$CXF_HOME
In my case :
export JAVA_HOME=/usr/java/jdk-13.0.2
export CXF_HOME=/home/eduard/MyPrograms/apache-cxf-3.3.5



wsdl2java -ant -client -d ClientDir https://ssweb.seap.minhap.es/demoorve/WSExportacion.wsdl

where ClientDir is the name of the folder where Java code will be generated and the blue code identifies the WSDL URL.

A package named https.ssweb_seap_minhap_es.demoorve has been created

6.3 Important class

The most important class is the one that ends with "_Client.java", that is a skeleton of how to use all the operations provided in the web service. This class is

WSExportacionPortType_WSExportacionPort_Client.java

6.4 Problematic class

Maybe due to changes in Java versions and XML libraries, the class "AnyTypeArray.java" is very problematic as internally it uses the ElementNSImpl class that is referenced in 2 different packages. To solve this problem, simply change "<Object>" by "<Integer>", as in this particular case only integers will be used. Here is the code. the changes are reflected in lines 36,36,60 and 61.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
package https.ssweb_seap_minhap_es.demoorve;

import java.util.ArrayList;
import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlType;


/**
 * <p>Java class for AnyTypeArray complex type.
 * 
 * <p>The following schema fragment specifies the expected content contained within this class.
 * 
 * <pre>
 * &lt;complexType name="AnyTypeArray"&gt;
 *   &lt;complexContent&gt;
 *     &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType"&gt;
 *       &lt;sequence&gt;
 *         &lt;element name="item" type="{http://www.w3.org/2001/XMLSchema}anyType" maxOccurs="unbounded" minOccurs="0"/&gt;
 *       &lt;/sequence&gt;
 *     &lt;/restriction&gt;
 *   &lt;/complexContent&gt;
 * &lt;/complexType&gt;
 * </pre>
 * 
 * 
 */
@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AnyTypeArray", propOrder = {
    "item"
})
public class AnyTypeArray {

    //protected List<Object> item;
 protected List<Integer> item;

    /**
     * Gets the value of the item property.
     * 
     * <p>
     * This accessor method returns a reference to the live list,
     * not a snapshot. Therefore any modification you make to the
     * returned list will be present inside the JAXB object.
     * This is why there is not a <CODE>set</CODE> method for the item property.
     * 
     * <p>
     * For example, to add a new item, do as follows:
     * <pre>
     *    getItem().add(newItem);
     * </pre>
     * 
     * 
     * <p>
     * Objects of the following type(s) are allowed in the list
     * {@link Object }
     * 
     * 
     */
    //public List<Object> getItem() {
 public List<Integer> getItem() {
        if (item == null) {
            //item = new ArrayList<Object>();
         item = new ArrayList<Integer>();
        }
        return this.item;
    }

}





Comments

Popular posts from this blog

ORVE WS (Dynamic) (4) Jackson XML mapper

AutoFirma ins and outs (4). Errors in tests in afirma-core, jmulticard-jse

Creating a WS Client consumer