JAXB Generation nillable=true - java

Using JAXB 2.2.4 I am generating Java code with the following binding file:
<bindings xmlns="http://java.sun.com/xml/ns/jaxb" version="2.0"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<globalBindings generateElementProperty="false">
</globalBindings>
Unfortunately, the generated code has a nillable = true annotation. See the following example:
#XmlElement(name = "ArtID", nillable = true)
protected STEBeitrag artID;
This is the definition of STEBeitrag:
<xsd:complexType name="CT_Beitrag">
<xsd:complexContent>
<xsd:extension base="allgemein:CT_Objekt">
<xsd:sequence>
<xsd:element name="ArtID" type="daten:STE_Beitrag" minOccurs="0" maxOccurs="1" nillable="true"/></xsd:element>
</xsd:sequence>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
<xsd:complexType name="STE_Beitrag" abstract="true">
<xsd:simpleContent>
<xsd:extension base="xsd:string"/>
</xsd:simpleContent>
</xsd:complexType>
If I do not set the ArtID in the generated CT_Beitrag object then the unmarshaller produces an output like
<ns:ArtID xsi:nil="true"/>
The element ArtID has an abstract type and therefore this XML output is invalid.
How can I generate code with JAXB that omits the nillable=true in the XmlElement annotation?
By the way, the schema canĀ“t be changed.

I have no solution, but this problem is addressed in bug
http://java.net/jira/browse/JAXB-890
I hope this problem wil be solved.

I don't how to do what you're asking and I'd be surprised if what you're asking is worth the effort.
There are 2 options that jump to my mind:
Change the schema (I know you said you can't but perhaps you can take a local copy of the schema if you can't change it due to it being hosted on a server outside of your control)
Change the generated code... simply change nillable=true to nillable=false

Related

generate client wsimport miss link between two object

I would like to generate client stubs from a wsdl with wsimport maven plugin , this is works well but with one issue : i have two object that should be linked togerther but afetr the generation is donne , it's not perfect
<types>
<xsd:schema elementFormDefault="qualified" targetNamespace="http://www.hello.com/ns/xsd/boba/restitution-restituerCarriereAvecValo.xsd">
<xsd:import namespace="http://www.hello.com/holla/infosRetour.xsd" schemaLocation="xsd/infosRetour.xsd"/>
<xsd:import namespace="http://www.hello.com/ns/wsdl/boba/messageRetourModuleValorisation.xsd" schemaLocation="xsd/messageRetourModuleValorisation.xsd"/>
<xsd:element name="messageIn" type="xsd:anyType"/>
<xsd:element name="messageOut">
<xsd:complexType>
<xsd:complexContent>
<xsd:extension base="ir:infosRetour">
<xsd:choice>
<xsd:element name="messageRetour" type="xsd:anyType"/>
<xsd:element name="rejetControleSyntaxiqueSemantique" type="xsd:anyType"/>
<xsd:element name="rejetControleIdentification" type="xsd:anyType"/>
</xsd:choice>
</xsd:extension>
</xsd:complexContent>
</xsd:complexType>
</xsd:element>
</xsd:schema>
</types>
here my object messageOut sould have a field messageRetour of type messageRetour class, but when i see my class messageOut this field is set as Object and not the montioned class.
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "", propOrder = {
"messageRetour",
"rejetControleSyntaxiqueSemantique",
"rejetControleIdentification"
})
#XmlRootElement(name = "messageOut")
public class MessageOut
extends InfosRetour
{
protected Object messageRetour;
protected Object rejetControleSyntaxiqueSemantique;
protected Object rejetControleIdentification;
as you can see here here is the sub class generated , you can see that there is a class named messageRetour
HOW CAN I CHANGE THIS TYPE TO BE SET AS A CLASS AND NOT AS OBJECT ?
even when i chnage this line <xsd:element name="messageRetour" type="xsd:anyType"/> to <xsd:element name="messageRetour"/> i got the same issue always Object and not a class
You get Object because of xsd:anyType as type.
You should change the type of <xsd:element name="messageRetour" type="xsd:anyType"/> to the messageRetour type.
This type is probably provided by one of the schemas you import. I'm not sure about the specific name, will be probably MessageRetour or messageRetour or message-retour, something like that. So it will probably be something like:
<xsd:element name="messageRetour" type="ir:messageRetour"/>
If the type is provided by the other imported schema, you may need to declare a namespace prefix first (like xmlns:mrmv="http://www.hello.com/ns/wsdl/boba/messageRetourModuleValorisation.xsd") and then use mrmv:messageRetour as type.

generate java classes from xsd with mutlitlevel imports

I am trying to generate java classes from xsd using JAXB plugin but not able to get the effect as I want.
My use case is :
a.xsd has some elements.
b.xsd has some elements.
composite.xsd needs to have some elements from "a.xsd" and "b.xsd" as well as it's own elements.
I have tried many options so far. I can import the xsds ( a and b ) into "composite" but that would only enable me to use the elements from "a" and "b" into "composite" xsd but when I generate the classes using jaxb, it won't automatically bring all contents from "a and b".
For example :
a.xsd -> has "name" element.
b.xsd -> has "phone" element.
composite.xsd -> imports a and b and has "nickname" element.
So if I don't explicitly use "name" and "phone" in composite.xsd, generated java class won't generate those. Also there could be multilevel imports ( kind of inheritance like composite.xsd includes "b.xsd" and "b.xsd" includes "a.xsd ).
So I want composite to have all elements from "a" and "b" in generated class without explicitly repeating a.xsd and b.xsd's elements in composite.xsd.
DESIRED OUTPUT:
composite.class
name, phone, nickname.
Please advise.
Here are some more details with xsd details:
( field names are different that what I put in the original question but will give a gist of it. ).
**a.xsd**
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="Customer">
<xsd:sequence>
<xsd:element name="name" type="xsd:string" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
**b.xsd**
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema version="1.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="Payments">
<xsd:sequence>
<xsd:element name="amount" type="xsd:float" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
**composite.xsd**
<xsd:include schemaLocation="x.xsd" />
<xsd:include schemaLocation="y.xsd" />
<xsd:complexType name="CustomerPayments">
<xsd:sequence>
<xsd:element name="customer" type="Customer" />
<xsd:element name="payments" type="Payments" />
</xsd:sequence>
</xsd:complexType>
</xsd:schema>
WITH above xsds, what I want to achieve is to have a composite java class (generated by JAXB maven plugin ) to automatically have fields like "name" and "amount" from imported/included xsds.
The generated CustomerPayments class will not contain propertiesname or amount, this is not how XJC works.
But it will contain field customer and payments of types Customer and Payments which will contain properties name and amount respectively. So you can do customerPayments.getCustomer().getName() at the end.

SOAP via jax-ws: entity classes missing in schema

So, I have a soap server-side project. Annotations - #WebService over interface and implementation, #WebMethod over interface' methods, #XmlRootElement over entity-classes that are in return and arguments in web-methods, and #XmlElement over their fields(over getters actually). Tried also partially and fully swap #XmlRootElement with #XmlType, and #XmlElement with #XmlAttribute.
Project is launched via publisher class or via Tomcat(WSServletContextListener), everything's working after weeks of trial and error. In WSDL schema, for instance:
<xsd:element name="Sell_i">
<xsd:complexType>
<xsd:sequence>
<xsd:element minOccurs="0" name="session" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="terminal" nillable="true" type="xsd:string"/>
<xsd:element minOccurs="0" name="info" nillable="true" type="tns:TransactionSellInfo"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
Represents the Sell_i method. TransactionSellInfo is an input argument here, and tns points to this namespace aka this wsdl. So, it should be described here. It of course has all the annonations. But, it's just missing, as well as every other class. What's the solution?
Worth noting: schema type is RPC(tho changing to Document doesn't cause classes to appear in wsdl). Also, on the same machine wsimport from wsdl creates classes for those missing entities, which is very wierd(didn't test wsimport on other machines tho). But soapUI won't work with that wsdl and rightfully says that it's malformed.
Maybe it's something quite basic that I'm missing, but google gives nothing useful on all my tries. Any help is appreciated!

Sax: XMLReader: Streaming and converting CSV to Xml and validating the result at the same time

I have to transform some CSV files (each > 600 MB) to XML while validating the end result with an XSD on the fly.
Because of the size of each file I'm using InputStreams to read the content and OutpuStreams to stream the result back to my clients as XML.
Let's start then with the easy part... (pseudocode)
void transform(final InputStream CSVCustomerStream, final OutputStream outputStream) {
outputStream.write("<customers>")
foreach csvCustomerRow in CSVCustomerStream {
String xmlCustomerRow = csvCustomerRow.toXML();
outputStream.write(xmlCustomerRow.getBytes();
}
outputStream.write("</customers>")
**MISSING_XMLVALIDATOR.parse(outputStream);**
}
So far, each row of my source CSV file is transformed to xml and then written to the outputstream.
Easy enough.
The part though, where the xml is actually validated is still missing.
For this I looked into XMLReader's parse() method. The only problem with that, is the fact that parse() only accepts InputSources, while at the same time I'm streaming the content I'd like to be validated to an OutputStream.
Of course, after reading the whole CSV content, I could turn the OutputStream into an InputStream via
new ByteArrayInputStream((outputstream).toByteArray())
but that would immediately bring 600 MB worth of XML back into memory, defying the whole purpose of streaming.
PS: I have no control over the exact implementation of the OutputStream since my code runs as a REST-webservice
return Response.ok(new StreamingOutput() {
#Override
public void write(OutputStream output) throws Exception {
.... loading and transforming csv ...
}
}).build();
Building on your comment, let me put forward the "worst" possible scenario, one where the XSD is authored as a Russian Doll (i.e. except for a document root, all other element and types are defined locally). Because of this style, there is no way to validate the xmlCustomerRow against the XSD, since there is no global element declaration which would match your tag (assume customer).
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" xmlns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="customers">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="customer" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Still, the solution is not that complicated. Take a look at this modified XSD:
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" xmlns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="customers">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="customer" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="customer">
<xsd:complexType>
</xsd:complexType>
</xsd:element>
</xsd:schema>
For this setup, you only need to open the original XSD as an XML, clone the customer element, remove its minOccurs/maxOccurs attribute, and then insert it as a child of the schema (it would be the document element in the XML). The idea here is that you could do a refactoring on the fly, or manually, etc.
There's always a possibility that you wouldn't have to do anything i.e. if the customer element is already global, something like this:
<?xml version="1.0" encoding="utf-8" ?>
<!-- XML Schema generated by QTAssistant/XSD Module (http://www.paschidev.com) -->
<xsd:schema targetNamespace="http://tempuri.org/XMLSchema.xsd" xmlns="http://tempuri.org/XMLSchema.xsd" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="customers">
<xsd:complexType>
<xsd:sequence>
<xsd:element ref="customer" minOccurs="0" maxOccurs="unbounded"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="customer">
<xsd:complexType>
</xsd:complexType>
</xsd:element>
</xsd:schema>
Other complications may arise, depending on how your XSD really looks like, but I can assure you that there could be nothing in there which would stop you from doing whatever refactoring you may need to achieve exactly what you want.
I am rather of the opinion that having the ability to validate each record independently beats anything else. More so, for a massive file running on a multi-core/CPU machine, you could parallelize your validation, which would make more efficient use of resources to achieve increased throughput.
It might be that tests will be sufficient to assure that your conversion produces XML that validates with the given XSD, or that (as Petru Gardea said in a comment) you can validate piecemeal using temporary strings.
But assuming that you actually have to validate on the fly, there are some tricks you can try, basically by manipulating streams.
You are producing an OutputStream that presumably you want to send to your client, and you have a process that you know how to do that needs an InputStream (actually the Reader interfaces might make some of this easier, but the fixes are parallel).
This means that you have to "tee" the OutputStream, i.e., duplicate it on-the-fly so you can send one stream to the client and use the copy for validation parsing. And you need to get an InputStream from your copied OutputStream.
For the "tee" process, you should consider Apache Commons TeeOutputStream, and for conversion from output to input, you should probably look at PipedInputStream and PipedOutputStream.

marshall with xjc created nested classes

<ProductInformation Context="GL">
<Assets>
<Asset ID="assetID" UserTypeID="ID">
<Name>name</Name>
<Reference ClassificationID="id"/>
<Values>
<Value AttributeID="ID">Value1</Value>
<Value AttributeID="ID">Value2</Value>
<MultiValue AttributeID="attributeID">
<Value>value3a</Value>
<Value>value3b</Value>
</MultiValue>
</Values>
</Asset>
</Assets>
<Products>....</Products>
</ProductInformation>
I used this xml->xsd and xjc to create classes from it.
Now I want to create my ProductInformation object,and marshall it.
My problem is xjc create 3 classes and a objectfactory, and some nested classes inside ProductInformation. When I look at the avaliable methods I mostly see getters instead of setters.
"Asset" class has no such methods like;
asset.setValues(List<Value> values)
Also I ended up writing funny code like this;
ProductInformation.Assets.Asset.Values.MultiValue multivalue=new ProductInformation.Assets.Asset.Values.MultiValue();
Is this normal with Jaxb?
The answer given by Ian Roberts is the correct one. I am giving this one to provide some additional information for those people interested in not having inner classes.
XML Schema (schema.xsd)
If JAXB classes are generated from the following XML schema, both the resulting Customer and Employee classes will contain a static nested class called Address (because each contains their own definition of an address). This is in fact why static nested classes are used to avoid name conflict problems.
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema
targetNamespace="http://www.example.org/company"
xmlns="http://www.example.org/company"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified">
<xsd:element name="customer">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="address">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="street" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
<xsd:element name="employee">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="address">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="road" type="xsd:string"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:schema>
JAXB Binding File (binding.xml)
A bindings file is used to customize the schema to Java generation. You can specify that everything should be a top level class with localScoping="top-level". When you do this you must make sure to resolve any potential name conflicts.
<jaxb:bindings
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="company.xsd">
<jaxb:bindings node="//xsd:element[#name='employee']/xsd:complexType/xsd:sequence/xsd:element[#name='address']/xsd:complexType">
<jaxb:class name="EmployeeAddress"/>
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>
XJC Call
Below is an example of specifying a bindings file when using the XJC command to generate Java classes from an XML schema.
xjc -b binding.xml schema.xsd
For More Information
http://blog.bdoughan.com/2011/07/jaxb-xjc-and-nested-classes.html
The way JAXB normally handles multi valued properties is to provide just a getter and no setter for the List<Whatever>, which returns a mutable list - you're supposed to call the getter to retrieve an initially-empty list and then create the member objects for this list using new in the normal way and add them directly to the list. You can new a static nested class in exactly the same way as a top-level one.
Single-valued properties (not lists) should have been generated with both getter and setter.
This is actually just a comment to Blaise Doughan's answer but I want to post the xml.
If you work with a more complex xsd and the path in the node attribute is getting too long, you can:
<jaxb:bindings xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" version="2.1">
<jaxb:globalBindings localScoping="toplevel"/>
<jaxb:bindings schemaLocation="company.xsd">
<jaxb:bindings node="//xsd:element[#name='employee']">
....
<jaxb:bindings node=".//xsd:element[#name='address']/xsd:complexType">
<jaxb:class name="EmployeeAddress"/>
</jaxb:bindings>
....
</jaxb:bindings>
</jaxb:bindings>
</jaxb:bindings>

Categories