How do I convert the following xml into java objects using JAXB - 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

Related

XSD not validating - udemy in28minutes

When I change the ID value to alpha characters - it doesn't tell me the values are invalid...
course-details.xsd
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://in28minutes.com/courses"
xmlns:tns="http://in28minutes.com/courses" elementFormDefault="qualified">
<element name="GetCourseDetailsRequest">
<complexType>
<sequence>
<element name= "id" type="integer"></element>
</sequence>
</complexType>
</element>
</schema>
Request.xml I expect an error to show on the <id> line...
<?xml version="1.0" encoding="UTF-8"?>
<GetCourseDetailsRequest xmlns="http://in28minutes.com/courses"
xsi:schemaLocation="http://in28minutes.com/courses course-details.xsd"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<id>abc</id> <!-- numbers -->
</GetCourseDetailsRequest>
The files are in the same folder - so not sure why this doesn't work:
You likely don't have the Validation builder on the project, or aren't letting the project build (which would automatically validate your XML files).
Open the project's Properties dialog and go to the Validation page. The option to add it should be there.
EDIT: You should also be able to right-click on the file and manually Validate it.

Jaxb POJOs generation with Inheritance

I want to generate the POJOs using the xml-binding with a different hierarchy that I have right now.
Now I have an xsd like this one:
<?xml version="1.0" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://manueldoncel.com" xmlns:tns="http://manueldoncel.com" elementFormDefault="qualified">
<!-- Base element that any element uses / extends -->
<complexType name="baseElement" abstract="true">
<sequence>
<element name="attributes" type="anyType" minOccurs="0" />
</sequence>
<attribute name="id" type="string" />
</complexType>
<complexType name="Square">
<complexContent><extension base="tns:baseElement" /></complexContent>
</complexType>
<complexType name="Triangle">
<complexContent><extension base="tns:baseElement" /></complexContent>
</complexType>
</schema>
An a xjb like this;
<?xml version="1.0"?>
<jxb:bindings version="1.0" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" jxb:extensionBindingPrefixes="xjc" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<jxb:bindings schemaLocation="figures.xsd" node="/xs:schema">
<jxb:globalBindings>
<xjc:simple />
<xjc:superClass name="org.manuel.metadata.Figure"/>
</jxb:globalBindings>
</jxb:bindings>
</jxb:bindings>
But, I would like to have a better hierarchy with this approach
public abstract class Figure {
// some methods for all the figures
}
public abstract class ThreeSideFigure extends Figure {
.... // some methods for only the Three side Figures
}
So, the Triangle POJO generated from the XSD should extend from ThreeSideFigure rather than from Figure.
In this particular xsd I only put 2 figures, but I can have much more. I would like to be able to specify in the xjb that all the complexType should extends from Figure but only a few of them, should extends from ThreeSideFigure.
Do you know how the xjb should look like?
I don't think the Metro JAXB RI extensions will let you do that.
From the 2.2.7 documentation:
3.1.3. Extending a Common Super Class
The <xjc:superClass> customization allows you to specify the fully
qualified name of the Java class that is to be used as the super class
of all the generated implementation classes. The <xjc:superClass>
customization can only occur within your <jaxb:globalBindings>
customization on the <xs:schema> element
That said, the answer to XJC superinterface and superclass only for all classes? suggests that you may be able to do it with 3rd party extensions. There are some details about plugins in the documentation.

JAXB : how to read the xsi:type value when unmarshalling

I am using JAXB in the XSD / XML to Java direction. My XSD contains derived types and the XML I have to unmarshall contain xsi:type attributes. Looking at the code JAXB (the default Sun implementation) has generated (for the unmarshalling) there seems to appear no methods to get these attributes.
Is it because I can always do a getClass() on the unmarshalled Java object and find the actual class?
Still, would it not be the case that depending on the packages or classes I provide to the JAXBContext.newInstance some base class may be instantiated instead? (one that is a superclass of the class corresponding to the actual value of the xsi:type attribute). In such a case being able to read the value of the actual attribute as it appears in the XML instance could be needed.
The JAXB (JSR-222) implementation will take care of everything for you. JAXB considers that each class corresponds to a complex type. It has an algorithm for figuring out the type name, but you can override this using the #XmlType annotation. When an element is unmarshalled if it contains an xsi:type attribute then JAXB will look to see if there is a class associated with that type. If there is it will instantiate a class of that type, if not it will instantiate the type that corresponds to that element based on the mapping metadata supplied via annotations.
For More Information
http://blog.bdoughan.com/2010/11/jaxb-and-inheritance-using-xsitype.html
UPDATE
Below is an example that may help:
schema.xsd
In the XML schema below the complex type canadianAddress extends the complexType address.
<?xml version="1.0" encoding="UTF-8"?>
<schema
xmlns="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/customer"
xmlns:tns="http://www.example.org/customer"
elementFormDefault="qualified">
<element name="customer">
<complexType>
<sequence>
<element name="address" type="tns:address"/>
</sequence>
</complexType>
</element>
<complexType name="address">
<sequence>
<element name="street" type="string"/>
</sequence>
</complexType>
<complexType name="canadianAddress">
<complexContent>
<extension base="tns:address">
<sequence>
<element name="postalCode" type="string"/>
</sequence>
</extension>
</complexContent>
</complexType>
</schema>
Demo
In the demo code below the XML will be converted to the JAXB model generated from the above XML schema, and then converted back to XML.
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance("org.example.customer");
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/org/example/customer/input.xml");
Customer customer = (Customer) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(customer, System.out);
}
}
input.xml/Output
Below is the XML. The address element is qualified with xsi:type to indicate that it holds an instance of canadianAddress instead of just an address.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<customer xmlns="http://www.example.org/customer">
<address xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="canadianAddress">
<street>1 A Street</street>
<postalCode>Ontario</postalCode>
</address>
</customer>

How to generate xsd file using java code?

<complexType name="spThread">
<sequence>
<element name="SPThreadID" type="int" />
<element name="durtime" minOccurs="0" default="0">
<simpleType>
<restriction base="int">
<minInclusive value="0" />
</restriction>
</simpleType>
</element>
<element name="minexecutions" minOccurs="0" default="0">
<simpleType>
<restriction base="int">
<minInclusive value="0" />
</restriction>
</simpleType>
</element>
<element name="numThreads" type="int" />
<element name="procedures" type="spm:procedure" minOccurs="1"
maxOccurs="unbounded" />
</sequence>
</complexType>
i want to generate this type of .xsd file using java code..? How can i do that.?
Specially how to generate Simple type elements and put restrictions on it ?
Instead of creating your own simple type to represent integers starting with 0, you could leverage the existing xs:nonNegativeInteger type. I'll demonstrate with an example.
SpThread
You can use the #XmlSchemaType annotation to specify what type should be generated in the XML schema for a field/property.
package forum11667335;
import javax.xml.bind.annotation.XmlSchemaType;
public class SpThread {
private int durTime;
#XmlSchemaType(name="nonNegativeInteger")
public int getDurTime() {
return durTime;
}
public void setDurTime(int durTime) {
this.durTime = durTime;
}
}
Demo
You can use the generateSchema method on JAXBContext to generate an XML schema:
package forum11667335;
import java.io.IOException;
import javax.xml.bind.*;
import javax.xml.transform.Result;
import javax.xml.transform.stream.StreamResult;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(SpThread.class);
jc.generateSchema(new SchemaOutputResolver() {
#Override
public Result createOutput(String namespaceUri, String suggestedFileName) throws IOException {
StreamResult result = new StreamResult(System.out);
result.setSystemId(suggestedFileName);
return result;
}
});
}
}
Output
Below is the XML schema that was generated.
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<xs:schema version="1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="spThread">
<xs:sequence>
<xs:element name="durTime" type="xs:nonNegativeInteger"/>
</xs:sequence>
</xs:complexType>
</xs:schema>
You can use any XML-handling API to achieve this. JDOM is one of them. If you'd like an API specific to building XML Schemas which you then serialize into XML, you might want to check out Eclipse MDT API.
You can use Java2Schema tool for generating schema from java classes, and also you can try JaxB 2.0
I recommend you JAXB to any XML jobs you do. But normally XSD files are generated manually and then XML files are generated programatically using the XSD files. What are you trying to develop?

webservice Cannot assign object of type System.Xml.XmlNode[] to an object of type System.String

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.

Categories

Resources