Fairly simple XSD generating ObjectFactory wrapping root element class in JAXBElement - java

I'm struggling to understand why XJC is generating an ObjectFactory that wraps instances of the class corresponding to the root element in a JAXBElement wrapper.
The root element does not use an anonymous complex type. (You have to be a little careful when reviewing this schema because there are pairs of complexType names that at first glance look the same, but one is plural and the other singular -- e.g. optionalParametersType and optionalParameterType)
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc"
xmlns:jaxb="http://java.sun.com/xml/ns/jaxb"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns="urn:com-mbm-parameters"
targetNamespace="urn:com-mbm-parameters"
elementFormDefault="qualified"
jaxb:version="2.0">
<xs:element name="parameters" type="parametersType" />
<xs:complexType name="parametersType">
<xs:sequence>
<xs:element name="option-parameters" type="optionParametersType" minOccurs="0" maxOccurs="1"/>
<xs:element name="positional-parameters" type="positionalParametersType" minOccurs="0" maxOccurs="1"/>
<xs:element name="mutually-exclusive-parameters" type="mutuallyExclusiveParametersType" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute name="properties-file" type="xs:string" use="optional"/>
</xs:complexType>
<!--
-->
<xs:complexType name="optionParametersType">
<xs:sequence>
<xs:element name="option-parameter" type="optionParameterType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--
-->
<xs:complexType name="optionParameterType">
<xs:sequence>
<xs:element name="description" type="descriptionType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="name" type="xs:string" use="required"/>
<xs:attribute name="command-line-name" type="xs:string" use="optional"/>
<xs:attribute name="default-value" type="xs:string" use="optional"/>
</xs:complexType>
<!--
-->
<xs:complexType name="positionalParametersType">
<xs:sequence>
<xs:element name="positional-parameter" type="positionalParameterType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--
-->
<xs:complexType name="positionalParameterType">
<xs:sequence>
<xs:element name="description" type="descriptionType" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="type" type="xs:string" use="required"/>
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="name" type="xs:string" use="required"/>
</xs:complexType>
<!--
-->
<xs:complexType name="descriptionType">
<xs:attribute name="forValue" type="xs:string" use="required"/>
</xs:complexType>
<!--
-->
<xs:complexType name="mutuallyExclusiveParametersType">
<xs:sequence>
<xs:element name="mutually-exclusive-parameter-set" type="mutuallyExclusiveParameterSetType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--
-->
<xs:complexType name="mutuallyExclusiveParameterSetType">
<xs:sequence>
<xs:element name="mutually-exclusive-parameter" type="mutuallyExclusiveParameterType" minOccurs="1" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<!--
-->
<xs:complexType name="mutuallyExclusiveParameterType">
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="value" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>
Here's the snippet of ObjectFactory that returns instances of the ParametersType class:
/**
* Create an instance of {#link JAXBElement }{#code <}{#link ParametersType }{#code >}}
*
*/
#XmlElementDecl(namespace = "urn:com-mbm-parameters", name = "parameters")
public JAXBElement<ParametersType> createParameters(ParametersType value) {
return new JAXBElement<ParametersType>(_Parameters_QNAME, ParametersType.class, null, value);
}
This is the only place the JAXBElement is used within the entire ObjectFactory, so it's not there to disambiguate two or more possible elements.
Any idea why this is happening and how to remove the need to use the wrapper?

You get JAXBElement for top-level elements, which, in this case, is your parameters element.
The rationale is to separate types and elements (which you can see as instances of types). So it is, actually, to disambiguate two or more possible elements - you may have another schema which has a different element of the same parametersType. Global elements are sometimes references via <xs:element ref="..."/>, they can have substitution groups etc., so in general always have JAXBElements for global elements is not completely unreasonable. I'm not saying it is the best design decision, I'm just saying there is some rationale in it.
To get rid of the wrapper, try using xjc:simple or adding #XmlRootElement annotation on your own:
https://stackoverflow.com/a/39778670/303810
JAXB xjc:simple binding does not generate #XmlRootElement for base class
But better don't fight it, embrace it.

Related

Can't generate Java code with the bundled Jaxb for Intellij

I have to modify a project using XSD validation. I had got an XML, I transformed it to XSD via Intellij and then generated the associated code with the JAXB tool. All was fine.
But for the project needs, I had to modify the entire structure of my XML, I did it. I generate the XSD as well. But, When I tried to generate the Java code via the jaxb tools, it was impossible.
When I click in this jaxb tool, it just generated another XSD.
How can I do to generate, once again, the code ?
Thank you !
There is my XSD.
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="PurgeConfigurationRacine" type="PurgeConfigurationRacineType"/>
<xs:complexType name="BusinessBaseType">
<xs:sequence>
<xs:element type="ArchiveDataOperationType" name="ArchiveDataOperation"/>
<xs:element type="PurgeDataOperationType" name="PurgeDataOperation"/>
<xs:element type="DeleteArchivedDataOperationType" name="DeleteArchivedDataOperation"/>
</xs:sequence>
<xs:attribute type="xs:string" name="dataSourceRef"/>
</xs:complexType>
<xs:complexType name="SqlQueryType">
<xs:simpleContent>
<xs:extension base="xs:string">
<xs:attribute type="xs:string" name="name" use="optional"/>
<xs:attribute type="xs:string" name="step" use="optional"/>
<xs:attribute type="xs:string" name="multi" use="optional"/>
<xs:attribute type="xs:string" name="param" use="optional"/>
<xs:attribute type="xs:string" name="value" use="optional"/>
</xs:extension>
</xs:simpleContent>
</xs:complexType>
<xs:complexType name="ArchiveDataOperationType">
<xs:sequence>
<xs:element type="SqlQueryType" name="SqlQuery" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PurgeDataOperationType">
<xs:sequence>
<xs:element type="SqlQueryType" name="SqlQuery" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PurgeConfigurationRacineType">
<xs:sequence>
<xs:element type="BusinessBaseType" name="BusinessBase"/>
<xs:element type="DataBaseType" name="DataBase"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="DeleteArchivedDataOperationType">
<xs:sequence>
<xs:element type="SqlQueryType" name="SqlQuery" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="DataBaseType">
<xs:sequence>
<xs:element type="ArchiveDataOperationType" name="ArchiveDataOperation"/>
<xs:element type="PurgeDataOperationType" name="PurgeDataOperation"/>
</xs:sequence>
<xs:attribute type="xs:string" name="dataSourceRef"/>
</xs:complexType>
</xs:schema>
The problem that you are facing is a known issue, it is due to the fact that you have an attribute called value which is a protected name, such that you need to specify to xjc that it has to use a different name, it can be done by adding some meta information in your XSD file as next:
<xs:attribute type="xs:string" name="value" use="optional">
<xs:annotation>
<xs:appinfo>
<jaxb:property name="sqlQueryTypeValue"/>
</xs:appinfo>
</xs:annotation>
</xs:attribute>
You will also need to add the corresponding namespace declaration and the jaxb version to use, for example:
<xs:schema ... xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" jaxb:version="2.1">
More information about how to customize JAXB binding

Don't display the element in xml if its id attribute is null

I have a xsd where there are 2 complextype elements under <Customer> complextype. One is <NormalCustomer> and <PrivilegedCustomer>. In my xml, I want either Normal or Privileged customer to be present under <Customer> tag based on the id attribute of Normal/Privileged customers.
below is my xsd
<xs:choice>
<xs:element name="normalCustomer" type="tns:normalCustomer" minOccurs="0" nillable="true"/>
<xs:element name="privilegedcustomer" type="tns:privilegedcustomer" minOccurs="0" nillable="true"/>
</xs:choice>
Complextype NormalCustomer
<xs:complexType name="normalCustomer">
<xs:sequence>
<xs:element name="id" type="xs:long"/>
<xs:element name="customerName" type="xs:string" minOccurs="1"/>
<xs:element name="customerType" type="xs:string" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
Complextype PrivilegedCustomer
<xs:complexType name="privilegedCustomer">
<xs:sequence>
<xs:element name="id" type="xs:long"/>
<xs:element name="customerName" type="xs:string" minOccurs="1"/>
<xs:element name="customerType" type="xs:string" minOccurs="1"/>
</xs:sequence>
</xs:complexType>
Note: Am using JAXB for processing
Please suggest me how can I modify the tag to achieve my requirement.
Remove minOccurs="0" nillable="true" from both elements. The <xs:choice> enforces that exactly one of the elements are present. If none present are allowed, add minOccurs="0" to <xs:choice>.

Jaxb generate one get method for all elements

Part of my xsd file looks like this:
<xs:complexType name="group">
<xs:sequence maxOccurs="unbounded" minOccurs="1">
<xs:element name="title" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="module" type="module" nillable="true" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute name="name" type="xs:string" />
</xs:complexType>
When I generate my classes using Jaxb in Eclipse. The "Group" class generates a method called:
public List<JAXBElement<?>> getTitleAndDescriptionAndModule();
How do I change the xsd so that I get getter for each of the elements?

How to properly declare an extension within a schema?

In my schema file below, I have an element Stat which extends Entity. As far as I am aware, I follow w3's example, but when I go to parse the schema (and the xml that uses the schema) with through java's DocumentBuilderFactory and SchemaFactory I get this exception:
org.xml.sax.SAXParseException; systemId: file:/schema/characterschema.xsd;
src-resolve.4.2: Error resolving component 'cg:Entity'. It was detected that
'cg:Entity' is in namespace 'http://www.schemas.theliraeffect.com/chargen/entity',
but components from this namespace are not referenceable from schema document
'file:/home/andrew/QuasiWorkspace/CharacterGenerator/./schema/characterschema.xsd'.
If this is the incorrect namespace, perhaps the prefix of 'cg:Entity' needs
to be changed. If this is the correct namespace, then an appropriate 'import'
tag should be added to '/schema/characterschema.xsd'.
So, it seems that I cannot see my namespace within my schema. Do I need to import my schema into itself or am I completely misreading this exception? Could it be that I am declaring my schema incorrectly?
This is my schema for reference:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:cg="http://www.schemas.theliraeffect.com/chargen/entity"
elementFormDefault="qualified">
<xs:element name="Entity">
<xs:complexType>
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="description" type="xs:string"/>
</xs:complexType>
</xs:element>
<xs:element name="Stat">
<xs:complexType>
<xs:complexContent>
<xs:extension base="cg:Entity">
<xs:sequence>
<xs:element name="table" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
</xs:element>
</xs:schema>
There are two problems with your schema. First, you don't declare a targetNamespace so the Entity and Stat elements you are defining are not in a namespace. Second, a type can't extend an element, only another type.
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:cg="http://www.schemas.theliraeffect.com/chargen/entity"
targetNamespace="http://www.schemas.theliraeffect.com/chargen/entity"
elementFormDefault="qualified">
<xs:complexType name="EntityType">
<xs:attribute name="id" type="xs:string" use="required"/>
<xs:attribute name="name" type="xs:string"/>
<xs:attribute name="description" type="xs:string"/>
</xs:complexType>
<xs:element name="Entity" type="cg:EntityType" />
<xs:complexType name="StatType">
<xs:complexContent>
<xs:extension base="cg:EntityType">
<xs:sequence>
<xs:element name="table" type="xs:string" minOccurs="0"
maxOccurs="unbounded"/>
</xs:sequence>
</xs:extension>
</xs:complexContent>
</xs:complexType>
<xs:element name="Stat" type="cg:StatType" />
</xs:schema>
Here I'm defining two types, one of which extends the other, and two top level elements of the respective types. All the top-level types and elements are defined into the targetNamespace of the schema, and the nested table element inside StatType is also in this namespace because of the elementFormDefault="qualified" - without this the Entity and Stat elements would be in the http://www.schemas.theliraeffect.com/chargen/entity namespace but the table element would be in no namespace.

ct-props-correct error when parsing schema

I'm using the JAXB xjc tool to generate some Java interface files from xsds. I'm running into a problem where I'm getting a tonne of errors of the form:
org.xml.sax.SAXParseException: ct-props-correct.4: Error for type 'COCT_MT110200CA.PayeeRole'. Duplicate attribute uses with the same name and target namespace are specified. Name of duplicate attribute use is 'nullFlavor'.
The relevant parts of the schema are as follows:
<xs:complexType name="COCT_MT110200CA.Holder">
<xs:sequence>
<xs:group ref="InfrastructureRootElements"/>
<xs:element name="payeeRole" type="COCT_MT110200CA.PayeeRole" minOccurs="1" maxOccurs="1">
</xs:element>
</xs:sequence>
<xs:attributeGroup ref="InfrastructureRootAttributes"/>
<xs:attribute name="nullFlavor" type="NullFlavor" use="optional"/>
<xs:attribute name="typeCode" type="ParticipationType" use="optional" fixed="HLD"/>
</xs:complexType>
Where COCT_MT110200CA.PayeeRole is defined as:
<xs:complexType name="COCT_MT110200CA.PayeeRole">
<xs:sequence>
<xs:group ref="InfrastructureRootElements"/>
<xs:element name="id" type="II" minOccurs="0" maxOccurs="unbounded">
</xs:element>
<xs:choice>
<xs:element name="payeePerson" type="COCT_MT110200CA.PayeePerson" nillable="true"
minOccurs="0"
maxOccurs="1">
</xs:element>
<xs:element name="payeeOrganization" type="COCT_MT110200CA.PayeeOrganization"
nillable="true"
minOccurs="0"
maxOccurs="1">
</xs:element>
</xs:choice>
</xs:sequence>
<xs:attributeGroup ref="InfrastructureRootAttributes"/>
<xs:attribute name="nullFlavor" type="NullFlavor" use="optional"/>
<xs:attribute name="classCode" type="RoleClass" use="optional" fixed="PAYEE"/>
</xs:complexType>
Any thoughts? I don't see anything wrong with this myself...
Oooh, I think I figured this out, there was a pesky attributeGroup (InfrastructureRootAttributes) there, and in that attributeGroup was the nullFlavor duplicate...

Categories