We have a very old axis web service that we need to use with a client made with jaxws. One of the methods of this web services returns a type apachesoap:Document, where apachesoap schema is http://xml.apache.org/xml-soap.
The response XML looks like this:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<ns1:consultaXMLResponse xmlns:ns1="http://webservices.imagapp.app" soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/">
<consultaXMLReturn href="#id0"/>
</ns1:consultaXMLResponse>
<multiRef xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:ns2="http://xml.apache.org/xml-soap" id="id0" soapenc:root="0"
soapenv:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"
xsi:type="ns2:Document">
<DatosConsultaWS>
<Registro>2974161</Registro>
</DatosConsultaWS>
</multiRef>
</soapenv:Body>
</soapenv:Envelope>
My adapted wsdl schema looks like this (I show only the response element, the rest I don't think is relevant because works fine).
<element name="consultaXMLResponse">
<complexType>
<sequence>
<element name="consultaXMLReturn">
<complexType>
<sequence>
<element name="DatosConsultaWS">
<complexType>
<sequence>
<element name="Registro" type="xsd:string"/>
</sequence>
</complexType>
</element>
</sequence>
<attribute name="href" type="xsd:anyURI"/>
<attribute name="id" type="xsd:ID"/>
<anyAttribute namespace="##other" processContents="strict"/>
</complexType>
</element>
</sequence>
</complexType>
</element>
However with this element, when I call that method, my client returns null (not even a ConsultaXMLReturn with null value inside).
I don't really know if what I'm trying to do is even posible.
Ideas? thanks.
Related
I've been tasked to integrate with a 3rd party web service. In their WSDL, they declare arrays as follows:
<?xml version="1.0"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:xs="http://www.w3.org/2001/XMLSchema" name="ITransEazSvcservice" targetNamespace="http://tempuri.org/" xmlns:tns="http://tempuri.org/" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:mime="http://schemas.xmlsoap.org/wsdl/mime/" xmlns:ns1="urn:LandairSvcIntf">
<types>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:LandairSvcIntf">
...
<complexType name="CustomItemArray">
<complexContent>
<restriction base="soapenc:Array">
<sequence/>
<attribute xmlns:n1="http://schemas.xmlsoap.org/wsdl/" ref="soapenc:arrayType" n1:arrayType="ns1:CustomItemRecord[]"/>
</restriction>
</complexContent>
</complexType>
...
When I run xjc to generate code to integrate with the web service, I get the following error message:
[ERROR] undefined simple or complex type 'soapenc:Array'
and
[ERROR] undefined attribute 'soapenc:arrayType'
What do I need to do in order to generate the the proper code to integrate with their service? We use Java.
What is the best way to convert this XML into Java objects?
<entity>
<customers id=2 other="data">
<customer name="john">testData1</customer>
<customer name="jenny">testData2</customer>
<customer name="joe">testData3</customer>
<customer name="joanna">testData4</customer>
</customers>
</entity>
Is it best to use a custom XMLAdapter with a HashMap to convert multiple xml rows of <customer>? I'm not sure if the XMLAdapter is the proper use case for this scenario. Any ideas would be appreciated.
Since the nesting isn't very deep, you could just have Entity, Customer classes and then use these annotations for the mapping in the entity class:
#XmlElementWrapper(name="customers")
#XmlElement(name="customer")
public void setCustomers(List<Customer> customers) {
this.customers= customers;
}
References:
XmlElementWrapper
Best approach, in my opinion, would be to write an xsd file to validate against your xml. You can use that to generate your java classes using xjc which comes bundled with Java. This should get you there.
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:NameOfNamespace="http://enter.your.namespace.here"
targetNamespace="http://enter.your.namespace.here"
attributeFormDefault="unqualified"
elementFormDefault="qualified">
<complexType name="customer">
<simpleContent>
<extension base="string">
<attribute name="name"/>
</extension>
</simpleContent>
</complexType>
<complexType name="customers">
<sequence>
<element name="customer" type="NameOfNamespace:customer"/>
</sequence>
<attribute name="id" type="positiveInteger"/>
<attribute name="other"/>
</complexType>
<complexType name="entity" >
<sequence>
<element name="customers" type="NameOfNamespace:customers" minOccurs="1" maxOccurs="1"/>
</sequence>
</complexType>
<element name="entity" type="NameOfNamespace:entity"/>
</schema>
Open a command prompt to the folder where you put your xsd file, and then generate java code you'll just need to type:
$ xjc nameOfSchemaFile.xsd
assuming your java 'bin' folder is in your path. The classes generated will be created in folder with the same name as your targetNamespace.
Using these you can follow the instructions in Naimish's example JAXB Hello World Example
My provider must have an array of object as input parameter, according to the WSDL:
<element name="classifica" type="Q4:Titolario" maxOccurs="unbounded" minOccurs="0"/>
This is the generated method:
public void protoModificaProtocollo(...,...,...,Titolario[] classifica,....) {
How to get the input values of this array (always returns null).
EDIT
This is the xsd schema of the method to provide:
<import schemaLocation="TipoVerso.xsd" namespace="http://regione.toscana.it/rfc205/interpro.TipoVerso"/>
<import schemaLocation="Anagrafica.xsd" namespace="http://regione.toscana.it/rfc205/interpro.Anagrafica"/>
<import schemaLocation="Titolario.xsd" namespace="http://regione.toscana.it/rfc205/interpro.Titolario"/>
<element name="protoModificaProtocolloElement" type="tns:protoModificaProtocollo"/>
<complexType name="protoModificaProtocollo">
<sequence>
<element name="numero" type="int" maxOccurs="1" minOccurs="1"/>
<element name="anno" type="int" maxOccurs="1" minOccurs="1"/>
<element name="verso" type="Q1:TipoVerso" maxOccurs="1" minOccurs="1"/>
<element name="oggetto" type="string" maxOccurs="1" minOccurs="0"/>
<element name="classifica" type="Q4:Titolario" maxOccurs="unbounded" minOccurs="0"/>
<element name="ufficio" type="Q2:Anagrafica" maxOccurs="unbounded" minOccurs="0"/>
</sequence>
</complexType>
and this is the xsd schema of Titolario
<?xml version="1.0" encoding="UTF-8"?>
<schema targetNamespace="http://regione.toscana.it/rfc205/interpro.Titolario"
elementFormDefault="qualified" xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:tns="http://regione.toscana.it/rfc205/interpro.Titolario">
<complexType name="Titolario">
<sequence>
<element name="codice" type="string" maxOccurs="1" minOccurs="1"></element>
<element name="descrizione" type="string" maxOccurs="1" minOccurs="0">
</element>
</sequence>
</complexType>
</schema>
Here the SOAP message sent:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:int="http://regione.toscana.it/rfc205/interpro"
xmlns:int1="http://regione.toscana.it/rfc205/interpro.protoModificaProtocollo"
xmlns:int2="http://regione.toscana.it/rfc205/interpro.Titolario"
xmlns:int3="http://regione.toscana.it/rfc205/interpro.Anagrafica">
<soapenv:Header/>
<soapenv:Body>
<int:protoModificaProtocollo>
<int1:numero>140</int1:numero>
<int1:anno>2014</int1:anno>
<int1:verso>P</int1:verso>
<!--Optional:-->
<int1:oggetto>test</int1:oggetto>
<!--Zero or more repetitions:-->
<int1:classifica>
<int2:codice>34</int2:codice>
<!--Optional:-->
<int2:descrizione>test description</int2:descrizione>
</int1:classifica>
</int:protoModificaProtocollo>
</soapenv:Body>
</soapenv:Envelope>
In the provider, this is the method:
public void protoModificaProtocollo(int numero, int anno, TipoVerso verso,
String oggetto, Titolario[] classificazione, Anagrafica[] ufficio,
ResponseProtocolloHolder protocollo_resp, ResponseErrorHolder response_msg_err) {
... some stuff here ...
System.out.println("getCodice():" + classificazione[0].getCodice()); <-- THIS LINE ALWAYS RETURNS NULL
Notice that, in input parameters, if I change
Titolario[] classificazione
with
Titolario classificazione
my debug line prints:
34
UPDATE 2
TIA Simon, here pastebin you can find the full WSDL. And here Titolario.java the class for Titolario. I've noticed that when consumer call provider, Titolario constructor i call N times, depending of number of Titolario occurrences in SOAP request. As you can see, the constructor is an empty constructor.
In this moment, my protocol is RPC/encoded, just becouse i've must understand the problem reported here Literal vs Encoded (if you please can take a look also at this...:-))
I've found some references about the problem, for example this article, maybe related to mine.
Anyway, i would like to know if there is a Java workaround to manage this. Thanks again!
Found the problem!
The fact was that i've used the same given WSDL both to generate the provider and to create the SoapUI project.
Basically the trick was:
generate the provider in Domino using the given WSDL
set RPC/Literal, according to the <soap:body use="literal"/> directive
export the Domino WSDL of the provider
create the SoapUI project with it
use it to call services provided
That's it! ... a very stupid mistake! :-(
Without a full WSDL I can't say with 100% this is the issue.
Based on what you have so far.
1. There are known issues where the "xsd:string" is wrapped with custom string handler. I have see references before where "string" would just sit on top of "xsd:string". So I would start with changing that back to "xsd:string" and see if it helps.
2. As your web service provider has the following:
Titolario[] classifica
Normally your WSDL should create an xxxArray Object which your consumer sends, and not the array object itself. (Tested on Doc/Literal + RPC/Literal, as "minoccurs" only shows up on Literal).
For example:
public String TestProtoModificaProtocollo (Titolario x[]) { ...
Converts to:
<complexType name="Titolario">
<sequence>
<element name="codice" nillable="true" type="xsd:string"/>
<element maxOccurs="unbounded" minOccurs="0" name="descrizione" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
<complexType name="TitolarioArray">
<sequence>
<element maxOccurs="unbounded" minOccurs="0" name="item" type="impl:Titolario"/>
</sequence>
</complexType>
<element name="x" type="impl:TitolarioArray"/>
<element name="TestProtoModificaProtocolloReturn" type="xsd:string"/>
So your consumer would translate to:
public java.lang.String testProtoModificaProtocollo(TitolarioArray x) throws java.rmi.RemoteException;
I auto-generated a solution from a WSDL file for a project I'm working on, but for some reason the solution does not seem to correctly handle the input specified by the WSDL. Does anyone know what I can do to fix it?
Given the following operation:
<wsdl:operation name="createBin">
<wsdl:input message="impl:createBinRequest" name="createBinRequest"/>
<wsdl:output message="impl:createBinResponse" name="createBinResponse"/>
</wsdl:operation>
<wsdl:message name="createBinRequest">
<wsdl:part element="impl:createBin" name="parameters"/>
</wsdl:message>
<element name="createBin">
<complexType>
<sequence>
<element name="request" type="impl:Bin"/>
</sequence>
</complexType>
</element>
<complexType name="Bin">
<sequence>
<element name="FulfillerID" type="xsd:positiveInteger"/>
<element name="BinID" nillable="true" type="xsd:positiveInteger"/>
<element name="ExternalLocationID" type="xsd:string"/>
<element name="BinType" type="xsd:string"/>
<element name="BinStatus" type="xsd:string"/>
<element name="Name" nillable="true" type="xsd:string"/>
</sequence>
</complexType>
Implemented with this code (auto-generated by eclipse):
public PositiveInteger createBin(Bin request) throws RemoteException {
throw new UnsupportedOperationException();
}
When sending this message:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://my.api.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<q0:createBin>
<q0:request>
<q0:FulfillerID>1234</q0:FulfillerID>
<q0:BinID>1234</q0:BinID>
<q0:ExternalLocationID>1234</q0:ExternalLocationID>
<q0:BinType>Good</q0:BinType>
<q0:BinStatus>Bad</q0:BinStatus>
<q0:Name>Ugly</q0:Name>
</q0:request>
</q0:createBin>
</soapenv:Body>
</soapenv:Envelope>
I get the following error:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<soapenv:Fault>
<faultcode>soapenv:Server.userException</faultcode>
<faultstring>org.xml.sax.SAXException: Invalid element in com.api.my.Bin - request</faultstring>
<detail>
<ns1:hostname xmlns:ns1="http://xml.apache.org/axis/">localhost</ns1:hostname>
</detail>
</soapenv:Fault>
</soapenv:Body>
</soapenv:Envelope>
I'm 100% sure that the SOAP message is the correct format, so my server must be choking on something. When I remove the parameter, everything works swimmingly for some reason.
I can however, get the expected behavior by removing the element like so:
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:q0="http://my.api.com" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<q0:createBin>
<q0:FulfillerID>1234</q0:FulfillerID>
<q0:BinID>1234</q0:BinID>
<q0:ExternalLocationID>1234</q0:ExternalLocationID>
<q0:BinType>Good</q0:BinType>
<q0:BinStatus>Bad</q0:BinStatus>
<q0:Name>Ugly</q0:Name>
</q0:createBin>
</soapenv:Body>
</soapenv:Envelope>
I'm searching my brain to remember where I saw this before, but I'm certain I've seen some seemingly 'invalid SOAP requests' which turned out to be invalid because the response was invalid.
In this light: could you change the generated createBin(Bin request) code to return a PositiveInteger rather than -3? Maybe if we can make te response valid, your server will stop complaining.
Good Luck!
It turns out the SAX parser is not interpreting the request that it looks like it should. Even though the parameter to the method is request, it ignores that and expects to parse an element that has a request field of type com.api.my.Bin. The problem was fixed by changing .
public PositiveInteger createBin(Bin request) throws RemoteException {
throw new UnsupportedOperationException();
}
With
public PositiveInteger createBin(CreateBin request) throws RemoteException {
throw new UnsupportedOperationException();
}
Where
public class CreateBin {
public Bin request;
/* ... */
}
Though, to be transparent, I did have to do a lot of tweaking to the CoreServiceSoapBindingStub and CoreServiceSoapBindingSkeleton that eclipse generated in order to get the whole thing not to blow up because of invalid something-or-other.
I am trying to consume a Java Webservice using Visual Basic.net. I am getting an error on deserialization "Cannot assign object of type System.Xml.XmlNode[] to an object of type System.String".
What I have been reading is that the wsdl specification may not conform to the WS-I BP 1.1 specification. Link Here
The other solution talked about here is to change the response xml to conform to a .net datatype. I have tried to do this for other reasons a couple of years back and it proved to be unstable.
A snippet of the wsdl is this:
<?xml version="1.0" encoding="UTF-8"?>
<wsdl:definitions targetNamespace="http://ws.interfaces.sessions.APILink.amdocs"
xmlns:apachesoap="http://xml.apache.org/xml-soap"
xmlns:impl="http://ws.interfaces.sessions.APILink.amdocs"
xmlns:intf="http://ws.interfaces.sessions.APILink.amdocs"
xmlns:soapenc="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:tns2="http://io.datainfo.APILink.amdocs"
xmlns:tns3="http://datainfo.APILink.amdocs"
xmlns:tns4="http://awsi.amdocs.com"
xmlns:tns5="http://exceptions.APILink.amdocs"
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
xmlns:wsdlsoap="http://schemas.xmlsoap.org/wsdl/soap/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<complexType name="InPersonInfo">
<complexContent>
<extension base="tns2:BaseInputOutputInfo">
<sequence>
<element maxOccurs="1" minOccurs="0" name="mItem1" type="xsd:int"/>
<element maxOccurs="1" minOccurs="0" name="mID" nillable="true" type="xsd:string"/>
<element maxOccurs="1" minOccurs="0" name="mPersonType" type="tns4:char"/>
</sequence>
</extension>
</complexContent>
</complexType>
The other pieces from the WSDL I am seeing is just the message and operation sections.
EDIT 2011-04-21: This question mentions what I am going through.
I am not familiar with java what I know is that it is being created/consumed with AXIS or SOAPUI and somehow it is not creating the WSDL according to standard and there is my problem. If I find an answer to solve it I will post it here.