I have xsd schema below describe the
<xs:element name="ReqStartTest">
<xs:complexType>
<xs:sequence>
<xs:element name="Version" >
<xs:simpleType>
<xs:restriction base="xs:string" />
</xs:simpleType>
</xs:element>
<xs:element name="Time" >
<xs:simpleType>
<xs:restriction base="xs:string" />
</xs:simpleType>
</xs:element>
<xs:element ref="tns:StartTestRequest" minOccurs="1" maxOccurs="1"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="StartTestRequest">
<xs:complexType>
<xs:sequence>
<xs:element name="Name" >
<xs:simpleType>
<xs:restriction base="xs:string" />
</xs:simpleType>
</xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>
After i generate java classes from xsd file, and recieve *.wsdl file. After i testing *.wsdl file in SOAPUI, I see just "StartTestRequest" request. My question, why/where my input data ("Version","Time") in request?
Thanks in advance.
Spring only generates request/response for the elements that has the postfixes "request" and "response". In this case, you are referencing "StartTestRequest" from "ReqStartTest". So, you will only see "StartTestRequest" which only has the name field in it. You should extend or reference "ReqStartTest" in your "StartTestRequest"
Following should work fine.
<complexType name="ReqStartTest">
<sequence>
<element name="Version" type="string"/>
<element name="Time" type="string"/>
</sequence>
</complexType>
<element name="StartTestRequest">
<complexType>
<complexContent>
<extension base="tns:ReqStartTest">
<sequence>
<element name="Name" type="string"/>
</sequence>
</extension>
</complexContent>
</complexType>
</element>
Update:
Spring requires predefined suffixes to identify elements that are requests or responses of a web service. Default suffixes are "Request" and "Response". You can change it in the configuration. This thread might help you: Spring-ws: How to create Wsdl from an xsd with no "Request" element
Also this is the closest you will get without changing suffixes:
<element name="ReqStartTestRequest">
<complexType>
<sequence>
<element name="version" type="string"/>
<element name="time" type="string"/>
<element name="startTestRequest" type="tns:StartTestRequest"/>
</sequence>
</complexType>
</element>
<complexType name="StartTestRequest">
<sequence>
<element name="name" type="string"/>
</sequence>
</complexType>
I highly advise you to follow naming conventions. For example, first letter of a variable or non constant field should be lower case (camelcase notation).
Related
I am working with JAXB generated classes from schema and got stuck with following problem. I am trying to handle both null and empty string values with single element.
What I want to achieve is to be able to marshal both null and empty string values and receive the same while unmarshaling.
Element("key1", "value1") -> <element key="key1">value1</element>
Element("key2", "") -> <element key="key2"/>
Element("key3", null) -> <element key="key3" xsi:nil="true"/>
Schema xsd:
<xs:element name="element" nillable="true">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute name="key" type="xs:string" use="required"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
So far I get the following results, if value is null or "" I get the same xml:
Element("key1", null) -> <element key="key1"/> -> Element("key1", "")
Element("key2", "") -> <element key="key2"/> -> Element("key2", "")
Any idea if it is even possible with this xml structure? The only idea I have is to change structure to something like this, but it will generate more useless classes to deal with.
<element>
<key>key1</key>
<value>value1</value>
</element>
Edit
With given schema change it works as expected. The question if it is possible with original structure is still open.
<xs:element name="element">
<xs:complexType>
<xs:sequence>
<xs:element name="key" type="xs:string"/>
<xs:element name="value" type="xs:string" nillable="true"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<element>
<key>key1</key>
<value xsi:nil="true" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/>
</element>
<element>
<key>key2</key>
<value/>
</element>
So, I have an object which can contain a list of Objects of that type. I wrote an XSD which looks something like this:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="myNamespace" elementFormDefault="qualified">
<complexType name="BinModel">
<sequence>
<element type="string" name="min" />
<element type="string" name="max" />
<element type="string" name="fieldname" />
<element type="int" name="defaultValue" />
<element xmlns:ref="BinModel" name="innerBins" maxOccurs="unbounded" minOccurs="0" />
</sequence>
</complexType>
<element name="AllBins">
<complexType>
<sequence>
<element type="string" name="fieldnames" maxOccurs="unbounded" minOccurs="0"/>
<element type="int" name="defaultValue"/>
<element xmlns:type="BinModel" name="outerBins" maxOccurs="unbounded" minOccurs="0" />
</sequence>
</complexType>
</element>
</schema>
It produces two java classes, BinModel and AllBins respectively, but in each of those classes, even though I specify that they contain a list of type BinModel, it produces a List of type Object.
How do I generate a class which has a List of BinModels?
So I realized something was wrong when it took me adding xmlns before type and ref in order to not show errors in the editor. I looked at another xsd for a recursively defined Object somewhere else in my stupidly huge codebase to try and find a solution and discovered two things.
1. We were defining our own namespace
2. We referenced our own objects within that namespace.
So the corrected code looks something like this:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:myProject="projectNamespace" targetNamespace="myNamespace" elementFormDefault="qualified">
<complexType name="BinModel">
<sequence>
<element type="string" name="min" />
<element type="string" name="max" />
<element type="string" name="fieldname" />
<element type="int" name="defaultValue" />
<element type="myProject:BinModel" name="innerBins" maxOccurs="unbounded" minOccurs="0" />
</sequence>
</complexType>
<element name="AllBins">
<complexType>
<sequence>
<element type="string" name="fieldnames" maxOccurs="unbounded" minOccurs="0"/>
<element type="int" name="defaultValue"/>
<element type="myProject:BinModel" name="outerBins" maxOccurs="unbounded" minOccurs="0" />
</sequence>
</complexType>
</element>
</schema>
I am having a method where I am receiving XmlObject as an argument in the method and now I want to convert it into the java corresponding java object , that I have to pass in other webservice.
I have tried all the possible ways but not able to get it.
Code :
public static boolean updateAddress_V2(XmlObject xmlObject) throws XmlException{
AlarsDataService dataService=new AlarsDataService();
CustomerV2 customerV2=CustomerV2.Factory.parse(xmlObject.toString());
com.alars.osb.java.customer.CustomerV2.Customer customerXML=customerV2.getCustomer();
}
but when I am checking customerXML is coming as null.
Here is the XMLObject string value :
<Customer_V2 xmlns="http://www.alars.com/osb/java/Customer">
<Customer>
<customerId>4</customerId>
<driverLicense>XBRT245</driverLicense>
<firstName>ALEX</firstName>
<lastName>CINTRA</lastName>
<dob>21-11-1986</dob>
<addressLine1>10 Florence St</addressLine1>
<city>BOSTON</city>
<zipCode>02148</zipCode>
</Customer>
</Customer_V2>
Customer XSD :
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.alars.com/osb/java/Customer"
xmlns:tns="http://www.alars.com/osb/java/Citation" elementFormDefault="qualified">
<complexType name="Customer">
<sequence>
<element name="customerId" type="long"></element>
<element name="driverLicense" type="string"></element>
<element name="firstName" type="string"></element>
<element name="lastName" type="string"></element>
<element name="dob" type="date"></element>
<element name="addressLine1" type="string"></element>
<element name="city" type="string"></element>
<element name="zipCode" type="string"></element>
</sequence>
</complexType>
<complexType name="Customer_V2">
<sequence>
<element name="Customer">
<complexType>
<sequence>
<element name="customerId" type="long"></element>
<element name="driverLicense" type="string"></element>
<element name="firstName" type="string"></element>
<element name="lastName" type="string"></element>
<element name="dob" type="date"></element>
<element name="addressLine1" type="string"></element>
<element name="city" type="string"></element>
<element name="zipCode" type="string"></element>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</schema>
Any advise folks.. how to achieve this ??
You change the schema type of XmlObject to required CustomerV2 as follows since we do not know the type ahead.
CustomerV2 customerV2 = (CustomerV2)
xmlObject.changeType(CustomerV2.type);
To check the schema type against the required CustomerV2 schema type, you can do the following.
xmlObject.schemaType().isAssignableFrom(CustomerV2 .type);
The XML does not match to the XSD. Especially, the XSD is missing the top element entries. Use following Schema instead and re-generate your XMLBeans classes:
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" targetNamespace="http://www.alars.com/osb/java/Customer" xmlns:customer="http://www.alars.com/osb/java/Customer">
<xs:element name="CustomerParent">
<xs:complexType>
<xs:sequence>
<xs:element ref="customer:Customer"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="Customer">
<xs:complexType>
<xs:sequence>
<xs:element ref="customer:customerId"/>
<xs:element ref="customer:driverLicense"/>
<xs:element ref="customer:firstName"/>
<xs:element ref="customer:lastName"/>
<xs:element ref="customer:dob"/>
<xs:element ref="customer:addressLine1"/>
<xs:element ref="customer:city"/>
<xs:element ref="customer:zipCode"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="customerId" type="xs:integer"/>
<xs:element name="driverLicense" type="xs:NCName"/>
<xs:element name="firstName" type="xs:NCName"/>
<xs:element name="lastName" type="xs:NCName"/>
<xs:element name="dob" type="xs:NMTOKEN"/>
<xs:element name="addressLine1" type="xs:string"/>
<xs:element name="city" type="xs:NCName"/>
<xs:element name="zipCode" type="xs:integer"/>
</xs:schema>
Parse your XML as follows:
final CustomerParentDocument customerParentV1 = CustomerParentDocument.Factory.parse(file);
I have an XML string, and I could not use the supplied XSD to unmarshal the object in java. So I tried to use an online tool (www.freeformatter.com/xsd-generator.html) to generate a valid xsd and got the same error. I don't understand what I'm seeing.
Here's the XML:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Message xmlns:ns1="http://www.domain.com/ws" xmlns="http://www.domain.com/ws/protocol">
<HeaderMessage>
<MSGTYPE>reply</MSGTYPE>
<ORIGINATOR>XXXX</ORIGINATOR>
<SENDER>XXXX</SENDER>
<TIMESTAMP>2013-12-12 17:48:09.649</TIMESTAMP>
<IDPROCESS>2013-12-12 17:48:09.649</IDPROCESS>
<IDMESSAGE>AN-1386866889649</IDMESSAGE>
<IDREQUEST>AN-1386866889649</IDREQUEST>
<SERVICENAME>RESULT</SERVICENAME>
<ERRORFLAG>OK</ERRORFLAG>
<ERRORCODE>300</ERRORCODE>
<ERRORMSG>Success</ERRORMSG>
</HeaderMessage>
<BodyMessage>
<ns1:ServiceResultObject isin="XX0000000000">
<ns1:ResultObject value="true" codIsin="XX0000000000" />
</ns1:ServiceResultObject>
</BodyMessage>
</Message>
And here's the XSD I got from the tool:
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" targetNamespace="http://www.domain.com/ws" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ServiceResultObject">
<xs:complexType>
<xs:sequence>
<xs:element name="ResultObject">
<xs:complexType>
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="value"/>
<xs:attribute type="xs:string" name="codIsin"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute type="xs:string" name="isin"/>
</xs:complexType>
</xs:element>
</xs:schema>
After I generate the classes, I get the error
javax.xml.bind.UnmarshalException: unexpected element (uri:"http://www.domain.com/ws/protocol", local:"Message"). Expected elements are <{http://www.domain.com/ws}ServiceResultObject>
Why do I lose all this header information? Why does the XSD not result in a schema that actually unmarshals the object? The XSD supplied by the service guys here also only defined the inner object.
Since your XML document has 2 namespaces (http://www.domain.com/ws/protocol & http://www.domain.com/ws) you are going to need 2 XML schemas to represent it. One schema can reference another with an import element.
XML Schemas
Below I have started the XML Schemas that you will need for your XML.
ws.xsd (for http://www.domain.com/ws namespace)
This is part of the XML schema for the http://www.domain.com/ws. The whole one is what you have already generated.
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.domain.com/ws"
xmlns:tns="http://www.domain.com/ws"
elementFormDefault="qualified">
<element name="ServiceResultObject">
<complexType>
<sequence/>
<attribute name="isin" type="string"/>
</complexType>
</element>
</schema>
ws_protocol.xsd (for http://www.domain.com/ws/protocol namespace)
Here is a partial version of the schema that you are missing for the http://www.domain.com/ws/protocol namespace. Note the import element that references the other XML Schema, and <element ref="ws:ServiceResultObject"/> which references an element from the other XML Schema.
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.domain.com/ws/protocol"
xmlns:tns="http://www.domain.com/ws/protocol"
xmlns:ws="http://www.domain.com/ws"
elementFormDefault="qualified">
<import namespace="http://www.domain.com/ws" schemaLocation="ws.xsd"/>
<element name="Message">
<complexType>
<sequence>
<element name="HeaderMessage">
<complexType>
<sequence>
<element name="MSGTYPE" type="string"/>
</sequence>
</complexType>
</element>
<element name="BodyMessage">
<complexType>
<sequence>
<element ref="ws:ServiceResultObject"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
Creating the JAXBContext
Once you have the two XML Schemas the classes will generate to 2 different packages. Below is an example of how to bootstrap the JAXBContext. Note that the package names are delimited by the : character.
JAXBContext jc = JAXBContext.newInstance("com.domain.ws:com.domain.ws.protocol");
I have a remote system that returns an XML similar to the one below.
<BalanceResponse xmlns="http://example.com/balance">
<BalanceResult>
<Balance xmlns="">
<amount>10</amount>
<Balance>
</BalanceResult>
</BalanceResponse>
I created an xsd to match it
<s:schema elementFormDefault="qualified" targetNamespace="http://example.com/balance">
<s:element name="BalanceResponse">
<s:complexType>
<s:element minOccurs="0" maxOccurs="1" name="BalanceResult">
<s:complexType>
<s:element minOccurs="0" maxOccurs="1" name="Balance">
<s:complexType>
<s:element minOccurs="0" maxOccurs="1" name="amount" type="s:decimal" />
</s:complexType>
</s:element>
</s:complexType>
</s:element>
</s:complexType>
</s:schema>
I use JAXB to generate the stub classes. However, I know that my (un/)marshaller cannot bind the Balance element because the namespace is different.
Question is, how can i declare a different (blank)namespace for my element Balance?
You could do something like the following. Since elementFormDefault is unqualified all global elements (BalanceResponse and BalanceResult will be namespace qualified and all local elements (Balance and amount) won't be.
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://example.com/balance"
xmlns:tns="http://example.com/balance"
elementFormDefault="unqualified">
<element name="BalanceResponse">
<complexType>
<sequence>
<element ref="tns:BalanceResult"/>
</sequence>
</complexType>
</element>
<element name="BalanceResult">
<complexType>
<sequence>
<element name="Balance">
<complexType>
<sequence>
<element name="amount" type="int"/>
</sequence>
</complexType>
</element>
</sequence>
</complexType>
</element>
</schema>
If as in the XML Schema in your question put elementFormDefault as qualified then it would expect all of the XML elements to be namespace qualified.