JAXB Unmarshalling Fails - jaxb

Getting following error while unmarshalling a response String(in xml format). Initially it was complaining about the and ,so I removed the soap part from the response.Now it comes up with this error.
Classes are created from provided WSDL using JAXB 2
**javax.xml.bind.UnmarshalException: unexpected element (uri:"http://ws.taxwareenterprise.com", local:"calculateDocumentResponse"). Expected elements are (none)
at com.sun.xml.bind.v2.runtime.unmarshaller.UnmarshallingContext.handleEvent(UnmarshallingContext.java:662)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:258)
at com.sun.xml.bind.v2.runtime.unmarshaller.Loader.reportError(Loader.java:253)**
Here is my response string (part of it)
**<calculateDocumentResponse xmlns="http://ws.taxwareenterprise.com">
<txDocRslt>
<jurSumRslts>
<jurSumRslt>
<xmptAmt>5.0</xmptAmt>
<txableAmt>15.0</txableAmt>
<txAmt>0.04</txAmt>
<txJurUID>...**
Here goes my xsd for "CalculationResponse"(part of it)
<xs:complexType name="CalculationResponse">
<xs:sequence>
<xs:element name="txDocRslt" type="tns:TxDocRslt"/>
</xs:sequence>
</xs:complexType>
and this is my code for unmarshalling:
**final JAXBContext context = JAXBContext.newInstance(CalculationResponse.class);
final Unmarshaller unmarshaller = context.createUnmarshaller();
response = processResponse(response);//for removing soap headers
responseObj = (CalculationResponse) unmarshaller.unmarshal(new StringReader(response));//Fails here...
final TxDocRslt txDocRslt = responseObj.getTxDocRslt();**

Related

creating any object with python zeep

i am pretty new to zeep, and soap. i`am trying to make client request to soap ws function. wsdl of function:
-<s:element name="GetRetailTransactions">
-<s:complexType>
-<s:sequence>
-<s:element name="parameters" maxOccurs="1" minOccurs="0">
-<s:complexType mixed="true">
-<s:sequence>
<s:any/>
</s:sequence>
</s:complexType>
</s:element>
</s:sequence>
</s:complexType>
</s:element>
i dont fully understand how to create object with type any in zeep.
i have tried :
wsdl = 'http://domain/app.asmx?WSDL'
client = Client(wsdl=wsdl)
params = {
'RetailTransactionsParameters': {
'GetNotExportedOnly': '0',
'GetNotRetrunsOnly': '0',
'FromDate': '20170518',
'ToDate': '20170518',
'TransactionTypeFilter': {
'TransactionType': '2'
},
},
}
parameters = client.get_element('ns0:GetRetailTransactions')
param = xsd.AnyObject(parameters, parameters(params))
result = client.service.GetRetailTransactions(param)
but i get error:
File "/home/user/lib/python3.6/site-packages/zeep/xsd/elements/indicators.py", line 227, in render
if name in value:
TypeError: argument of type 'AnyObject' is not iterable
on soapui i can make request and successfully get answer with :
<Envelope xmlns="http://schemas.xmlsoap.org/soap/envelope/">
<Body>
<GetRetailTransactions xmlns="example.com/">
<parameters>
<RetailTransactionsParameters>
<GetNotExportedOnly>0</GetNotExportedOnly>
<GetNotRetrunsOnly>0</GetNotRetrunsOnly>
<FromDate>20170518</FromDate>
<ToDate>20170518</ToDate>
<TransactionTypeFilter>
<TransactionType>2</TransactionType>
</TransactionTypeFilter>
</RetailTransactionsParameters>
</parameters>
</GetRetailTransactions>
</Body>
</Envelope>
maybe someone can guide me how to correctly make such a request with zeep..
thanks in advance
I had the same problem today. The get_element method returns the type. To create the object you need to instantiate it. You can either do:
parameters = client.get_element('ns0:GetRetailTransactions')(params)
or you can explicitly set each property:
parameters = client.get_element('ns0:GetRetailTransactions')()
parameters.GetNotExportedOnly = 0
parameters.GetNotRetrunsOnly = 0
...
or you can pass the dict object and zeep does the conversion to the type
http://docs.python-zeep.org/en/master/datastructures.html#creating-objects

JAXB mark field as required in generated wsdl

I have a JAXB-annotiated class with some required fields:
...
#XmlElement(required = true, nillable = false)
private String credentials = null;
...
Using SoapUI, the generated wsdl is like this:
...
<xs:element name="credentials" type="xs:string"/>
...
Is there any way to get the required-information into the wsdl? If I understood this right, than the wsdl should look like this (maybe that):
...
<xs:element wsdl:required="true" name="credentials" type="xs:string"/>
...
#XmlElement(required=true) corresponds to an element in the XML Schema with the attribute minOccurs="1". Since this the default it is not required to be specified.

cxf does not generate the expected type in WSDL

I have an exception:
public class MyException extends Exception {
public MyException() {
}
public MyException(String message) {
super(message);
}
}
The exception is thrown from a webservice method.
When I generate the Webservice using a regular Jax-ws implementation, the WSDL has:
<xs:complexType name='MyException'>
<xs:sequence>
<xs:element minOccurs='0' name='message' type='xs:string' />
</xs:sequence>
</xs:complexType>
But, when generating the webservice with cxf, I get:
<xs:complexType name='MyException'> <xs:sequence/></xs:complexType>
Which is not ok for me: I expect to get the first variant.
Can you please advise how to force CXF to provide the desired result?
Remark: I cannot alter the code in the exception! The Exception does not have any fields!
Thanks!
This is already reported and fixed in the latest CXF versions:
https://issues.apache.org/jira/browse/CXF-4748

How Do I Use JAXB To Marshal Inherited Classes To XML?

I have been provided with an xsd that I compiled to Java classes using JAXB.
The generated classes create an abstract class called "Event" and several classes that extend it.
e.g. "DerivedEvent"
I am using the following to marshal it to XML.
ObjectFactory objectFactory = new ObjectFactory();
DerivedEvent derivedEvent = objectFactory.createDerivedEvent();
JAXBContext context = JAXBContextImpl.newInstance("com.my.root.namespace");
Marshaller marshaller = context.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
marshaller.setProperty(Marshaller.JAXB_ENCODING, "UTF-8");
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
Class partialClass = Event.class;
QName partNamespace = new QName(Event.class.getSimpleName());
Object element = new JAXBElement(partNamespace, partialClass, derivedEvent);
// Create a stringWriter to hold the XML
StringWriter stringWriter = new StringWriter();
marshaller.marshal(element, stringWriter);
String xml = stringWriter.toString();
This then outputs the wrong root element. i.e.
<Event xsi:type="DerivedEvent" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<DerivedStartPeriod xsi:nil="true"/>
<DerivedEndPeriod xsi:nil="true"/>
</Event>
instead of
<DerivedEvent>
<DerivedStartPeriod xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
<DerivedEndPeriod xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</DerivedEvent>
If I set the partialClass and partNamespace to DerivedEvent it outputs the correct information.
However, I can't really do that as this marshalling is in a flow where the event could be one of 50 different derived events.
I can't really change the xsd to have substitution groups as mentioned here http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-substitution.html as this change is likely to be lost when I am provided with a new version of the xsd.
I need to use the partial class and namespace as the Events are not root elements.
Can I add the events to be XmlRootElements with bindings somehow?
Or is there another way to address this?
I eventually found this page that helped me add the XmlRootElement:
https://codereview.stackexchange.com/questions/1877/jaxb-xjc-code-generation-adding-xmlrootelement-and-joda-datetime
Which I got working (dependencies/build.xml etc) by using the Annotate sample here:
http://confluence.highsource.org/display/J2B/Home
Creating a JAXBElement through generated ObjectFactory, or use proper QName.
This is bad:
QName partNamespace = new QName(Event.class.getSimpleName());
It should be like this
QName partNamespace = new QName("your namespace", "DerivedEvent");
You should find qname like this in ObjectFactory probably as constant...
ObjectFactory probably contains method createDerivedEvent with one argument of type DerivedEvent. It returns JAXBElement which can be marshaled to xml.

Using of Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex with string[]

I'm currently using Zend_Soap_AutoDiscover to generate my WSDL file, the problem is I want this wsdl to handle output of type ArrayOfString ( string[] ). so I changed the complex type strategy to Zend_Soap_Wsdl_Strategy_ArrayOfTypeSequence, it works properly but the problem is that the output isn't really an array of string the output xml is somthing like this :
<xsd:complexType name="ArrayOfString">
<xsd:sequence>
<xsd:element name="item" type="xsd:string" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
But I want output like this :
<xsd:complexType name="ArrayOfstring">
<xsd:complexContent>
<xsd:restriction base="soapenc:Array">
<xsd:attribute ref="soapenc:arrayType" wsdl:arrayType="xsd:string[]"/>
</xsd:restriction>
</xsd:complexContent>
</xsd:complexType>
so ,I used the new strategy , Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex, but the problem is that this strategy does not handle string[].
Finally -> What should I do :D?!
Try creating a response class that has just one attribute, as follows:
class Response
{
/** #var string[] */
public $items;
}
Then define your service class to return an object of type Response, as follows:
class Service
{
/**
* #param string
* #return Response
*/
public function process( $input )
{
$response = new Response();
// Populate $response->items[] object with strings...
return $response;
}
}
Then use the 'Zend_Soap_Wsdl_Strategy_ArrayOfTypeComplex' strategy when using Zend_Soap_Autodiscover to create the WSDL. Although this probably won't produce precisely the output you're after, it should produce something that is semantically closer than what you're currently getting. The key with this approach is to get the PHPDoc right.
If that still doesn't work, post the key bits of your code, as that will help resolve the issue more quickly.

Resources