I'm using JAXB 2.1.10 from Sun's JDK 1.6.0_18:
D:\apps\jdk160_18\bin>xjc.exe -version
xjc version "JAXB 2.1.10 in JDK 6"
JavaTM Architecture for XML Binding(JAXB) Reference Implementation, (build JAXB 2.1.10 in JDK 6)
I need to have JAXB's marshaller produce an empty element (e.g. <someStringField></someStringField> or <someStringField/>) when the JAXB object has the value of the empty string (""). However, rather than doing that, JAXB omits the element altogether from its output (as if it where an optional element).
My searches in the Internet indicated that JAXB should normally create this tag, as long as you set the field to the non-null empty string (i.e. myJAXBObject.setSomeStringField(""); ):
How to instantiate an empty element with JAXB
https://jaxb.dev.java.net/tutorial/section_2_2_12_8-No-Value.html#No%20Value
In my XSD, I've tried to indicate (in every way I know) that the element's presence is mandatory even if it is empty:
<xs:element name="outerElement">
<xs:complexType>
<xs:sequence>
<xs:element name="someStringField" type="xs:string" nillable="false" minOccurs="1" />
<xs:element name="someOtherStringField" type="xs:string" />
The generated code looks like this (it's the same for both elements):
#XmlElement(name = "someStringField", required = true)
protected String someStringField;
#XmlElement(name = "someOtherStringField", required = true)
protected String someOtherStringField;
However, when I marshal the following object...
outerElement.setSomeStringField("");
outerElement.setSomeOtherStringField("Value was set");
I get:
<outerElement>
<someOtherStringField>Value was set</someOtherStringField>
</outerElement>
When I was expecting:
<outerElement>
<someStringField></someStringField>
<someOtherStringField>Value was set</someOtherStringField>
</outerElement>
Or:
<outerElement>
<someStringField/>
<someOtherStringField>Value was set</someOtherStringField>
</outerElement>
Can anyone spot what I'm doing wrong?
Thank you for bringing this issue (https://bugs.eclipse.org/319028) to our attention. The bug has been fixed and will be included in the EclipseLink 2.1.1 maintenance release. If you want access to this fix earlier you can pick up the nightly download starting July 8th from:
http://www.eclipse.org/eclipselink/downloads/nightly.php
Apologies. I THOUGHT I was using JAXB from Sun's JDK, but I wasn't. There was a left-over jaxb.properties in my classes/ folder that was created by JDeveloper when I generated the bindings. I was actually using JAXB2.0 from EclipseLink/MOXy.
Removing the properties file allowed JAXB2.1 to be used and fixed my issue.
Related
For elements with multiplicity > 1 (i.e.. where maxOccurs>1 or maxOccurs=unbound), e.g.:
<element name="Name" type="tns:Type" minOccurs="0" maxOccurs="unbound"/>
JAXB generates the following code:
#XmlElement(name = "Name")
protected List<type> name;
Strictly speaking the above schema describes an XML snippet that looks like so:
<Name attr1="a" attr2="x">
<Name attr1="b" attr2="y">
<Name attr1="c" attr2="z">
i.e. a sequence of "Name" elements (and only that!).
When marshalling a Java object to XML the JAXB runtime creates XML, which contains an additional wrapper element around the list, like so:
<Name>
<Name attr1="a" attr2="x">
<Name attr1="b" attr2="y">
<Name attr1="c" attr2="z">
<Name>
By default the wrapping element has the same name as the individual items. Note, that there is no Java class representing that element!
One can overrule the naming to something that makes more sense by manually (!) adding a java-annotation "#XmlElementWrapper" annotation, like so:
#XmlElementWrapper(name = "NameList")
#XmlElement(name = "Name")
protected List<Type> name;
which then yields the following XML:
<NameList>
<Name attr1="a" attr2="x">
<Name attr1="b" attr2="y">
<Name attr1="c" attr2="z">
<NameList>
I agree that such a wrapper element is syntactically nice and makes the XML more readable, BUT there is a severe problem with this: the generated Java code (with or without renaming the wrapper element) generates and expects an XML dialect which - strictly speaking - does not match the original schema anymore! There is no mentioning or any implicit notion of any such wrapper element in the original schema!
The issue only surfaces, if one uses the original schema in different tools (e.g. to create web forms or a different schema-based code generator) and if their result then adheres and/or expects the original XML (i.e. the bare sequence without any wrapper element), while the JAXB-generated code creates and insists on the presence of the wrapper element. Then the two cannot understand each other!
My question thus: how can one instruct JAXB to NOT add/expect said wrapper element while marshalling/unmarshalling XML?
I have searched the web now for quite a while for solutions or work-arounds to this but found nothing! I can't imagine that nobody else before ever stumbled over this and that there seems no other solution to this other problem than to hand-tweak the XML marshalling/unmarshalling code. Any ideas or suggestions to solve this issue?
I implemented a working web service using CXF (2.7.1) with a WSDL & XSD that include, among other things, the following type:
<xs:simpleType name="SimpleIdType">
<xs:restriction base="xs:string">
<xs:pattern value="[A-Za-z0-9:\.\-]{20}"/>
</xs:restriction>
</xs:simpleType>
I interpret this to be: Accept only 20 character strings which only contain alphanumeric characaters and ':', '.' and '-'.
When I send a SOAP message to my web service with the corresponding element containing FAAAAAAAAAAAAAAAAAAA, the service of course accepts properly without any error.
However, if I send an identical SOAP message with the # instead of F (i.e. #AAAAAAAAAAAAAAAAAAA), the service still accepts the message, without issuing any validation error (unmarshalling or otherwise).
Why?
Isn't the default ValidationEventHandler supposed to handle that by throwing an "Unmarshalling Error"?
The JAXB model (generated or hand coded) does not contain all the metadata from the XML schema in its annotations. If you want to validate against all aspects of the schema you can enable this be specifying an instance of Schema on the Unmarshaller.
http://blog.bdoughan.com/2010/12/jaxb-and-marshalunmarshal-schema.html
I finally found the correct answer for this CXF-based case.
CXF already has runtime schema validation built-in. It is named schema validation via configuration and the only thing that was missing in my code was the XML to enable it, inside the already existing <jaxws:endpoint element in beans.xml AKA application-context.xml:
<jaxws:properties>
<entry key="schema-validation-enabled" value="true" />
</jaxws:properties>
This discovery was made possible thanks to the answer by #Patrick.
The default for minOccurs property of an <element> in an XSD file is 1 (source).
Consider you have an XSD specifying a complex type containing 2 elements: <el1> and <el2>.
If you provide an XDocument only containing <el2>, the XDocument will not validate.
Instead you'll get the message:
The element Message in namespace ___ has invalid child element el2 in namespace ___.
List of possible elements expected: el1
This basically is an error on <el2> where one would expect an error on the complex type for not containing <el1>.
My question is:
Is there a way to check if all <element>-tags which have minOccurs > 0 are present?
I would say this is a very basic check when validating XML with an XSD.
Depending on the way you defined your schema, the order of appearance of elements will matter.
In this case the validator is expecting a <el1> but is seeing the element <el2> so the error is that <el2> is appearing where it should not. I belive that means you used a "sequence" when defining your complex type. So the error you at getting is correct.
If this still bothers you, and the order of the elements does not matter to your parsing use "all" instead of "sequence" which will not enforce order. The validator should then prompt you that a required element <el1> is missing. It should look something like the following:
<xsd:complexType name="MyType">
<xsd:all>
<xsd:element name="el1" minOccurs="1"/>
<xsd:element name="el2" minOccurs="1"/>
</xsd:all>
</xsd:complexType>
I hope this helps.
I am attempting to use JAXB to unmarshall an XML files whose schema is defined by a DTD (ugh!).
The external provider of the DTD has specified one of the element attributes as xml:lang:
<!ATTLIST langSet
id ID #IMPLIED
xml:lang CDATA #REQUIRED
>
This comes into the xjc-generated class (standard generation; no *.xjb magic) as:
#XmlAttribute(name = "xml:lang", required = true)
#XmlJavaTypeAdapter(NormalizedStringAdapter.class)
protected String xmlLang;
However, when unmarshalling valid XML files with JAXB, the xmlLang attribute is always null.
When I edited the XML file, replacing xml:lang with lang and changed the #XmlAttribute to match, unmarshalling was successful (i.e. attributes were non-null).
I did find this http://old.nabble.com/unmarshalling-ignores-element-attribute-%27xml%27-td22558466.html. But, the resolution there was to convert to XML Schema, etc. My strong preference is to go straight from an un-altered DTD (since it is externally provided and defined by an ISO standard).
Is this a JAXB bug? Am I missing something about "namespaces" in attribute names?
FWIW, java -version = "build 1.6.0_20-b02" and xjc -version = "xjc version "JAXB 2.1.10 in JDK 6""
Solved the issue by changing replacing xml: with a namespace declaration in the JAXB-generated class:
#XmlAttribute(name = "lang", namespace="http://www.w3.org/XML/1998/namespace", required = true)
Which makes sense, in a way.
Without this kind of guidance, how would JAXB know how to interpret the otherwise-undefined namespace xml:? Unless, of course, it implemented some special-case internal handling to xml: as done in http://java.sun.com/javase/6/docs/api/javax/xml/stream/XMLStreamReader.html#getNamespaceURI%28java.lang.String%29 (see the first NOTE:)
Whether it's a bug in xjc's generation of the annotated objects or a bug in the unmarhaller, or simply requires a mapping somewhere in the xjc process is still an open question in my mind.
For now, it's working and all it requires is a little xjc magic, so I'm reasonably happy.
Disclaimer: Although 8 years late, I am adding this answer for lost souls such as myself trying to understand auto generation of java files from a DTD.
You can set project wide namespaces for the unmarshaller to work with directly in the project-info.java file via the #XmlSchema option.
This file should be automatically generated by xjc when generating classes from a schema, however it appears xjc does not automatically generate the package-info.java file when generating from a DTD!
However, you can manually make this file, and add it to the same package as the files generated by xjc.
The file would look like the following:
package-info.java :
#XmlSchema(
elementFormDefault=XmlNsForm.QUALIFIED,
xmlns = {
#XmlNs(prefix="xlink", namespaceURI="http://www.w3c.org/1999/xlink"),
#XmlNs(prefix="namespace2", namespaceURI="http://www.w3c.org/1999/namespace2")
})
package your.generated.package.hierarchy;
import javax.xml.bind.annotation.*;
You can add as many namespaces as required, simply add a new line in the form:
#XmlNs(prefix="namespace", namespaceURI="http://www.uri.to.namespace.com")
The benefit of doing it this way, rather than compared to editing the generated #XmlAttribute is that you do not need to change each generated XmlAttribute, and you do not need to manually remove the namespaces from the XmlAttribute name variable.
I have a .xsd file which I use to generate code with the xsd.exe tool from Visual Studio.
Some class members are Guids and the xsd.exe tool gives 2 warnings:
Namespace 'http://microsoft.com/wsdl/types/' is not available to be referenced in this schema.
Type 'http://microsoft.com/wsdl/types/:guid' is not declared.
The Guid type is recognized because the generated C# file is valid and works.
Anyone knows how to get rid of those warnings?
What is the correct syntax for the XSD to be validated AND class members being generated as System.Guid?
Thank you all,
I found how to remove the warnings.
As sysrqb said, the wsdl namespace has either been deleted or never existed. It seems that the xsd.exe tool knows the Guid definition internally, but it cannot validate the xsd schema.
As boj pointed out, the only way to validate the schema with Guids in it, is to (re)define that type in a schema. The trick here is to add the Guid type to the same "http://microsoft.com/wsdl/types" namespace. This way, the xsd.exe will do the proper association between http://microsoft.com/wsdl/types:Guid and System.Guid
I made a new xsd file for the guid type:
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://microsoft.com/wsdl/types/" >
<xs:simpleType name="guid">
<xs:annotation>
<xs:documentation xml:lang="en">
The representation of a GUID, generally the id of an element.
</xs:documentation>
</xs:annotation>
<xs:restriction base="xs:string">
<xs:pattern value="\{[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}\}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
Then, I run xsd.exe with both my original xsd file and this new xsd file:
xsd.exe myschema.xsd guid.xsd /c
Citation from here:
XmlSchema guidSchema = new XmlSchema();
guidSchema.TargetNamespace = "http://microsoft.com/wsdl/types/";
XmlSchemaSimpleTypeRestriction guidRestriction = new XmlSchemaSimpleTypeRestriction();
guidRestriction.BaseTypeName = new XmlQualifiedName("string", XmlSchema.Namespace);
XmlSchemaPatternFacet guidPattern = new XmlSchemaPatternFacet();
guidPattern.Value = #"[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
guidRestriction.Facets.Add(guidPattern);
XmlSchemaSimpleType guidType = new XmlSchemaSimpleType();
guidType.Name = "guid";
guidType.Content = guidRestriction;
guidSchema.Items.Add(guidType);
schemaSet.Add(guidSchema);
XmlSchema speakerSchema = new XmlSchema();
speakerSchema.TargetNamespace = "http://www.microsoft.com/events/teched2005/";
// ...
XmlSchemaElement idElement = new XmlSchemaElement();
idElement.Name = "ID";
// Here's where the magic happens...
idElement.SchemaTypeName = new XmlQualifiedName("guid", "http://microsoft.com/wsdl/types/");
It looks like that wsdl namespace extension page was deleted, so it can't find the type information you need.