XMLBeans nested complex element instantiation failure - java

I'm using XMLBeans to generate java objects from a XSD schema.
The Schema is in the following structure :
<schema targetNamespace="" xmlns="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<element name="Father">
<complexType>
<all>
<element name="Son">
<complexType>
<all>
<element name="Target" type="string" />
</all>
</complexType>
</element>
</all>
</complexType>
</element>
</schema>
The schema is compiled allright and I'm able to instantiate the Father by:
Father father = Father.Factory.newInstance();
But when I try to perform :
father.getSon().setTarget("Some String");
I get a null pointer exception. When debugging it, I saw that Son is null (hence the exception).
All I need is to set the "Target" value, but I couldn't figure a way to do it....
Is there a way to auto-build all the XSD structure? Alternatively, can I instantiate the "Son" manually and then access its "Target"?
Thanks a lot!
O.J

getSon() method allows you to get the existing child called Son. If you're trying to generate a new xml, you have to start with an empty document. Then you should add your elements as you wish before accessing them.
Try this code:
FatherDocument fatherDocument = FatherDocument.Factory.newInstance();
Father father = fatherDocument.addNewFather();
Son son = father.addNewSon();
son.setTarget("Some string");
StringWriter writer = new StringWriter();
fatherDocument.save(writer);
System.out.println(writer.toString());
I've generated this xml:
<Father><Son><Target>Some string</Target></Son></Father>

Related

Jaxb implClass specification ignored for rootElement

I'm trying to specify a implementation class for an XSD-Type.
Here's a minimal example schema:
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="rd.test"
xmlns:tns="rd.test" elementFormDefault="qualified"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
<complexType name="DocumentType">
<annotation>
<appinfo>
<jaxb:class implClass="rd.DocumentEx" />
</appinfo>
</annotation>
<sequence>
<element name="element" type="tns:DocumentType" />
</sequence>
<attribute name="title" type="string" />
</complexType>
<element name="document" type="tns:DocumentType"/>
</schema>
I'm using the standard xjc-tool from the Java JDK (1.7) for now (but I've also tested with maven-jaxb2-plugin, with the same results).
For a short test I used the following XML-document:
<?xml version='1.0' standalone='yes' ?>
<document title="testDocument">
<element title="testElement" />
</document>
When I run the following test program, the results differ for the top-level document element (testDocument) and the contained child element (testElement). The root is of type "DocumentType", i.e. ignoring the specified implClass-directive, whereas the element is of type "DocumentEx", which is the expected result.
In the generated ObjectFactory the appropriate instantiation seems correct, but it seems to be not used for the rootElement:
public DocumentType createDocumentType() {
return new DocumentEx();
}
Here is the test program:
InputStream inp=new FileInputStream(new File("test.xml"));
JAXBContext jaxbContext = JAXBContext.newInstance("test.rd");
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
JAXBElement el = (JAXBElement)unmarshaller.unmarshal(inp);
Object obj = el.getValue();
System.out.println("doc: " + obj);
// result: "doc: test.rd.DocumentType#d1c5bb0"
DocumentType doc = (DocumentType)obj;
Object obj2=doc.getElement();
System.out.println("obj2: " + obj2);
// result: "obj2: rd.DocumentEx#d1c5bb0"
I get the same result, if I specify the implClass for the element instead of for the complexType.
Why is the implClass ignored for the root-element?
Any ideas and hints are appreciated!
Extension to clarify my intention:
I don't want to reference an existing, jaxb-annotated class, but use the auto-generated DocumentType-Class as base class for extionsion with additional attributes and methods. For a later direct marshalling back to XML, I have to keep the relation to the XSD-Type. Therefore the implClass-directive actually is the appropriate (as far as I know) way to instrument the jaxb-generation of the type-classes.
And it's working perfectly for the inner elements (the 'element' with title 'testElement' inside the document-tag)!! Unfortunately the unmarshaller does NOT use the implClass-specified class for instantiating the root-element correctly. See the result-comments in the program excerpt above (doc vs. obj2).
For the behaviour you are looking for I believe you want to specify ref and not impl:
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="rd.test"
xmlns:tns="rd.test" elementFormDefault="qualified"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.0">
<complexType name="DocumentType">
<annotation>
<appinfo>
<jaxb:class ref="rd.DocumentEx" />
</appinfo>
</annotation>
<sequence>
<element name="element" type="tns:DocumentType" />
</sequence>
<attribute name="title" type="string" />
</complexType>
<element name="document" type="tns:DocumentType"/>
</schema>
This tells JAXB to use the rd.DocumentEx class for the DocumentType complex type. Now a DocumentType class is not created, and the createDocument method on the ObjectFactory looks like this:
#XmlElementDecl(namespace = "rd.test", name = "document")
public JAXBElement<DocumentEx> createDocument(DocumentEx value) {
return new JAXBElement<DocumentEx>(_Document_QNAME, DocumentEx.class, null, value);
}
From section 7.7.1 of the JAXB 2.2 specification:
• implClass if specified, is the name of the implementation class for
className and must include the complete package name. Note that this
customization only impacts the return value for className’s factory
method. This customization is ignored when new is used to create
instances of a schema-derived Value class.
• ref if specified, is the
name of the value class that is provided outside the schema compiler.
This customization causes a schema compiler to refer to this external
class, as opposed to generate a definition. It must include the
complete package name. This attribute is mutually exclusive with the
className attribute and the implClass attribute.

JAXB always marshalls extension - unable to get elements of a super type only

I'm stuck on a problem with JAXB / Spring Web Services. Below is the detailed description. I appreciate any suggestion that could help me to solve it. I can provide more if details if needed.
I am writing a web service that returns list of some entities. Spring WS is contract-first framework, so I started with the XSD similar to:
<element name="GetEntitiesRequest" type="Something"/>
<element name="GetEntitiesResponse" type="Entities"/>
<complexType name="Entities">
<sequence>
<element name="Entity" type="Entity" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="Entity">
<sequence>
(...)
</sequence>
</complexType>
It was working well. However, the "Entity" type begin to grow (there a lot of elements) which caused performance issues (there are many Entities in the response). So I decided to split "Entity" into two parts
Some general information that will be returned within the group response - Entity
More detailed information that will be returned in an another web service operation, specific for the entity - EntityDetails
So after the change the schema is as follows (EntityDetails inherits from Entity):
<element name="GetEntitiesRequest" type="Something"/>
<element name="GetEntitiesResponse" type="Entities"/>
<complexType name="Entities">
<sequence>
<element name="Entity" type="Entity" minOccurs="0" maxOccurs="unbounded"/>
</sequence>
</complexType>
<complexType name="Entity">
<sequence>
(...)
</sequence>
</complexType>
<element name="GetEntityDetailsRequest" type="SomethingMore"/>
<element name="GetEntityDetailsResponse" type="EntityDetails"/>
<complexType name="EntityDetails">
<complexContent>
<extension base="Entity">
<sequence>
(...)
</sequence>
</extension>
</complexContent>
</complexType>
JAXB (precisely: hyperjaxb3) generates classes for Entity (inheritance strategy = JOINED), EntityDetails, and Entities. Also, it creates the ObjectFactory with "createGetEntitiesResponse" method. I am using this method to marshall List retrieved through Hibernate from the Entity table.
Theoretically, I should get list of "Entity" when sending "GetEntitiesRequest". However, I get list of "EntityDetails" instead.
If you read this form the beginning, you can imagine, that this what I wanted to avoid.
If you need more details, persistence.xml is as follows:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<persistence (...)>
<persistence-unit name="org.package">
<class>org.package.Entity</class>
<class>org.package.EntityDetails</class>
<class>org.package.Entities</class>
</persistence-unit>
</persistence>
I use Gradle for the build automation, and its jaxb plugin for the class generation:
jaxb
{
xsdDir = "src/main/webapp/schemas/messages"
bindingsDir = "src/main/webapp/schemas/bindings"
bindings = ["bindings.xjb"]
xjc
{
extension = true
taskClassname = "com.sun.tools.xjc.XJC2Task"
generatePackage = "org.package"
args = ["-Xannotate", "-Xhyperjaxb3-jpa2", "-Xequals", "-XhashCode", "-XtoString"]
}
}
currently, the bindings.xjb, beyond header, contains only:
<jaxb:globalBindings localScoping="toplevel">
<xjc:serializable/>
</jaxb:globalBindings>
First of all, make sure that you get instances Entity from the database, NOT EntityDetails.
Try to create an isolated scenario, without the database. Just instantiate your Entity, fill it with something create the response and marshal it. See what happens.
You'll isolate the problem - either you're getting wrong instances from the database or the marshalling does not work as expected. Both is a bit hard to diagnose without seeing your code. Try to reduce your problem to one of the two I mentioned above.
Diclaimer: I'm the author of Hyperjaxb3.

XSD: constrain attribute value of element to a substring of parent attribute

Consider this piece of XML
<Parent id="MyParent1">
<Child id="MyParent1.MyChild1"/>
</Parent>
<Parent id="MyParent2">
<Child id="MyParent2.MyChild1"/>
<Child id="MySillyIncorrectPrefix.MyChild2"/>
</Parent>
How can I validate (possibly with XSD) Child elements whose id contains the Parent element id as a prefix, so that:
<Child id="MyParent2.MyChild1"/> <!-- is valid -->
<Child id="MySillyIncorrectPrefix.MyChild2"/> <!-- is not valid -->
I'm not bound to XSD version 1.0, so I could try with XSD 1.1 (and features like assertions), but I would like to know:
how to express the above constraint with an xs:assertion or more suitable XSD 1.1
feature.
if it's possible to build a validator in Java leveraging on
that xsd? "Xerces-J" is a feasible solution ?
In my limited knowledge of XSD 1.1 I came up with this attempt:
<xs:element name="Child">
<xs:complexType>
<xs:attribute name="type" type="xs:String" />
<xs:assert test="starts-with(#type,../#type)"/>
</xs:complexType>
</xs:element>
Is this correct? Is there a tool where I could test it?
Being more general: is there a tool to assist the build&test of such XSD 1.1 featured schemas? (afaik Eclipse supports only XSD 1.0)
What you describe is not feasible in XSD 1.0.
In XSD 1.1 you can use assertions on the type of the parent to require each child's id attribute to begin with the value of the parent's id attribute.
This schema should validate the example (use an xsd 1.1 assertion)
<?xml version="1.1" encoding="UTF-8"?>
<schema xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="http://www.example.org/stackoverflow" xmlns:tns="http://www.example.org/stackoverflow" elementFormDefault="qualified">
<complexType name="ParentType">
<sequence>
<element name="Child" type="tns:ChildType"
maxOccurs="unbounded" minOccurs="0">
</element>
</sequence>
<attribute name="id" type="string"></attribute>
</complexType>
<element name="Parent" type="tns:ParentType"></element>
<complexType name="ChildType">
<attribute name="id" type="string"></attribute>
<assert test="starts-with(#id,../#id)"/>
</complexType>
</schema>

Parsing XML schema java

I need to parse XML schema (source can be wsdl file or xsd ) and extract all the complex types and their constituent elements with their types.. I have used JAXB (xjc)but it does not return me a list of all complexTypes . Which alternative (XSOM) should I use? I would prefer some built-in library in jdk6.
`
<element name="BankLoanProcessRequest">
<complexType>
<sequence>
<element name="ClientId" type="int"/>
<element name="LoanAmount" type="double"/>
</sequence>
</complexType>
</element>`
you can use JDOM or DOM4j-
here are the link -
http://www.jdom.org/
http://dom4j.sourceforge.net/

generation of java classes from xsd using jaxb

Currently working on a project in which the xsd's have been provided for data exchange. The xsd's are available isotc211. As can be seen there are a couple of them and i am interested in generation of classes for /gmd/metadataEntity.xsd which in turn has dependencies on other xsds and so on.
The problem is that there is a lot of repetition of names for elements and attributes and it would be a really long job to get rid of them and at the end i am not even sure if it will work. i have this till now ..
<jxb:bindings version="2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb" >
<jxb:bindings schemaLocation="geometryPrimitives.xsd" node="/xsd:schema">
<jxb:schemaBindings>
<jxb:package name="net.opengis.gml"/>
<jxb:nameXmlTransform>
<jxb:elementName suffix="Element"/>
</jxb:nameXmlTransform>
</jxb:schemaBindings>
<jxb:bindings
node="//xsd:group[#name='PointGrid']/xsd:sequence/xsd:element[#name='rows']">
<jxb:property name="rowsElement"/>
</jxb:bindings>
</jxb:bindings>
</jxb:bindings>`
the namexml transform was supposed to help to take care of the element and attributes naming but i still have a lot of similary naming across the xsd's. is there a way of getting around this ?
For instance elements are now generated using the suffix. so i get net.open.gml.SecondDefiningParameterElement is already in use.
when something like this exists in one of the xsd's
<element name="secondDefiningParameter"><complexType>
<sequence>
<element ref="gml:SecondDefiningParameter"/>
</sequence>
</complexType>
</element>
and in the same xsd
<element name="SecondDefiningParameter">
<complexType>
<choice>
<element name="inverseFlattening" type="gml:MeasureType"/>
<element name="semiMinorAxis" type="gml:LengthType"/>
<element name="isSphere">
<simpleType>
<restriction base="string">
<enumeration value="sphere"/>
</restriction>
</simpleType>
</element>
</choice>
</complexType>
</element>

Categories