JAXB renaming attributes by itself - java

In my XSD I have the following attribute:
<xs:element name="id8digits" type="xs:string" minOccurs="0"/>
But when i use JAXB to generate java-classes it renames it to:
#XmlElement(name = "id8digits", namespace = "my.org.name")
protected String id8Digits; // Capital D instead of lower case d
The XSD is delivered by a third party, and I cannot change the XSD itself. I have read about bindings-files, but even if I rename the attribute to id8digits with a lower case d, JAXB renames it again to upper case D.
I have also tried to use globalbindings and set enableJavaNamingConventions="false" but that does not do the trick.
bindings.xml
<jxb:bindings xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jxb="http://java.sun.com/xml/ns/jaxb" version="2.1"><jxb:bindings schemaLocation="XSD.xsd">
<jxb:globalBindings enableJavaNamingConventions="false"/>
<jxb:bindings node="//xs:element[#name='id8digits']">
<jxb:property name="id8digits"/>
</jxb:bindings>

You have problem somewhere else:-
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="Test")
#XmlAccessorType(XmlAccessType.FIELD)
public class Test {
#XmlElement(name = "id8digits", namespace = "my.org.name")
protected String id8Digits;
public String getId8Digits() {
return id8Digits;
}
public void setId8Digits(String id8Digits) {
this.id8Digits = id8Digits;
}
public static void main(String[] args) throws JAXBException {
JAXBContext jc = JAXBContext.newInstance(Test.class);
Marshaller m = jc.createMarshaller();
Test jaxbElement = new Test();
jaxbElement.setId8Digits("Testing");
m.marshal(jaxbElement, System.out);
}
}
output:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?><Test xmlns:ns2="my.org.name"><ns2:id8digits>Testing</ns2:id8digits></Test>

Related

Java: Marshalling Object — Removing extra ns2 annotation in xml

I am trying to marshall data within an object into an xml file based on a defined schema. However when I print out the xml file, I recieve extra annotations on the xml tags. Is there any way to get rid of the extra namespace annotation (i.e. ns2)
This is an example of the xml I receive from marshalling.
<?xml version="1.0" encoding="UTF-8" standalone="yes">
<root xmlns:ns2="http://www.something.com/something">
<ns2:food>steak</ns2:food>
<ns2:beverage>water</ns2:beverage>
</root>
What I want is something like this:
<?xml version="1.0" encoding="UTF-8" standalone="yes">
<root xmlns="http://www.something.com/something">
<food>steak</food>
<beverage>water</beverage>
</root>
This is what my Java code is doing:
JAXBContext context = JAXBContext.newInstance("com.schema");
JAXBElement<FoodSchema> element = new JAXBElement<FoodSchema>
(new QName("FoodSchema"), Food.class, foodSchema);
Marshaller marshaller = context.createMarshaller();
OutputStream os = new FileOutputStream(object.getFilePath());
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(element, os);
Any help is much appreciated! Thanks!
By adding a namespace URI ("http://www.something.com/something") to the QName used to construct the JAXB element, and leveraging the package level #XmlSchema annotation will get you the namespace qualification that you are looking for:
package-info
#XmlSchema(
namespace="http://www.something.com/something",
elementFormDefault=XmlNsForm.QUALIFIED)
package forum7014746;
import javax.xml.bind.annotation.*;
Food
package forum7014746;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Food {
private String food;
private String beverage;
public String getFood() {
return food;
}
public void setFood(String food) {
this.food = food;
}
public String getBeverage() {
return beverage;
}
public void setBeverage(String beverage) {
this.beverage = beverage;
}
}
Demo
package forum7014746;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.Marshaller;
import javax.xml.namespace.QName;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jaxbContext = JAXBContext.newInstance(Food.class);
Food foodSchema = new Food();
foodSchema.setFood("steak");
foodSchema.setBeverage("water");
JAXBElement<Food> element = new JAXBElement<Food> (new QName("http://www.something.com/something","FoodSchema"), Food.class, foodSchema);
Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(element, System.out);
}
}
Output
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<FoodSchema xmlns="http://www.something.com/something">
<beverage>water</beverage>
<food>steak</food>
</FoodSchema>
add to xsd schema definition elementFormDefault and attributeFormDefault:
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" ...
elementFormDefault="qualified" attributeFormDefault="unqualified" ... >
Thanks for answer. Just to give sample code
before:
marshaller.marshal(new JAXBElement(new QName(**""**,"Document"),Document.class,swiftDoc), sw);
after:
marshaller.marshal(new JAXBElement(new QName(**"http://www.w3.org/2001/XMLSchema**","Document"),Document.class,swiftDoc), sw);
and extra "ns:" was removed.

Creating an XML element with xsi:nil and attributes in .Net/Jaxb

I have an XML Schema that says:
<xs:element name="employerOrganization" nillable="true" minOccurs="1" maxOccurs="1">  <xs:complexType>    <xs:sequence>      ...    </xs:sequence>    <xs:attribute name="classCode" type="EntityClassOrganization" use="required"/>    <xs:attribute name="determinerCode" type="EntityDeterminerSpecific" use="required"/>  </xs:complexType></xs:element>
That means I must be able to create an instance that looks like this:
<employerOrganization classCode="ORG" determinerCode="INSTANCE" xsi:nil="true"/>
According to the XML Schema spec I can (http://www.w3.org/TR/xmlschema-0/#Nils). According to Microsoft .Net I cannot (http://msdn.microsoft.com/en-us/library/ybce7f69(v=vs.100).aspx) and as far as others tell me Jaxb cannot either.
Are both .Net and Jaxb uncompliant? Can I override somehow to get the desired output?
In JAXB you can leverage a JAXBElement for this. The JAXBElement can hold a value which has fields/properties mapped to XML attributes and a flag that tracks whether the element was nil.
Java Model
Foo
Instead of having a field/property of type Bar you specify JAXBElement<Bar>.
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class Foo {
#XmlElementRef(name="bar")
private JAXBElement<Bar> bar;
}
Bar
Bar has fields/properties mapped to XML attributes.
import javax.xml.bind.annotation.XmlAttribute;
public class Bar {
#XmlAttribute
private String baz;
}
ObjectFactory
import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.*;
import javax.xml.namespace.QName;
#XmlRegistry
public class ObjectFactory {
#XmlElementDecl(name="bar")
public JAXBElement<Bar> createBar(Bar bar) {
return new JAXBElement<Bar>(new QName("bar"), Bar.class, bar);
}
}
Demo Code
Demo
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Foo.class, ObjectFactory.class);
Unmarshaller unmarshaller = jc.createUnmarshaller();
File xml = new File("src/forum19797412/input.xml");
Foo foo = (Foo) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(foo, System.out);
}
}
input.xml/Output
<?xml version="1.0" encoding="UTF-8"?>
<foo>
<bar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" baz="Hello World" xsi:nil="true"/>
</foo>

How can I generate a XSD with an xs:element which is optional using JAXB?

My model object look something like this:
#XmlRootElement(name = "appConfig")
#XmlType(propOrder = {})
public class Config implements Serializable {
...
private int advancedFooBar;
...
#XmlElement(name = "advancedfoobar")
public int getAdvancedFooBar() {
return advancedFooBar;
}
public void setAdvancedFooBar(int advancedFooBar) {
this.advancedFooBar = advancedFooBar ;
}
When I generate a schema against this class w/JXC I end up with the following for the above property:
<xs:element name="advancedfoobar" type="xs:int"/>
I'd like this to be an optional element so I tried changing
#XmlElement(name = "advancedfoobar")
to
#XmlElement(name = "advancedfoobar", required=false)
However, that did not result any change to the generated schema. What do I need to do so that the "advancedfoobar" element will be defined as optional in the generated schema?
I am using JDK 1.7.0_U3 on Windows 7 Ultimate x64.
Thanks.
-Noah
WHAT THE JAVADOCS SAY
According to the Javadoc for #XmlElement (see: http://docs.oracle.com/javase/6/docs/api/javax/xml/bind/annotation/XmlElement.html#required%28%29)
If required() is false, then the Javabean property is mapped to XML
Schema element declaration with minOccurs="0". maxOccurs is "1" for a
single valued property and "unbounded" for a multivalued property.
The schema definition for advancedfoobar should be minOccurs=0 for the following mappings:
#XmlElement(name = "advancedfoobar")
public int getAdvancedFooBar() {
return advancedFooBar;
}
and
#XmlElement(name = "advancedfoobar", required=false)
public int getAdvancedFooBar() {
return advancedFooBar;
}
BUG IN MOXy AND REFERENCE IMPLEMENTATION
There appears to be a bug in both EclipseLink JAXB (MOXy) and the JAXB reference implementation regarding primitives and optional elements. I have opened the following bug against MOXy.
http://bugs.eclipse.org/395301
WORKAROUND
You can make the property of type Integer instead of int. Or better yet just set the type property on the #XmlElement annotation to be Integer. Any type capable of holding a null value will be optional by default.
Config
package forum13595629;
import java.io.Serializable;
import javax.xml.bind.annotation.*;
#XmlRootElement(name = "appConfig")
#XmlType(propOrder = {})
public class Config implements Serializable {
private int advancedFooBar;
#XmlElement(name = "advancedfoobar", type=Integer.class)
public int getAdvancedFooBar() {
return advancedFooBar;
}
public void setAdvancedFooBar(int advancedFooBar) {
this.advancedFooBar = advancedFooBar;
}
}
Demo
package forum13595629;
import java.io.IOException;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.SchemaOutputResolver;
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(Config.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
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:complexType name="config">
<xsd:all>
<xsd:element name="advancedfoobar" type="xsd:int" minOccurs="0"/>
</xsd:all>
</xsd:complexType>
<xsd:element name="appConfig" type="config"/>
</xsd:schema>

Jaxb:global binding Double Type Conversion Using XMLAdapter

I have an element defined as an xsd:double. If I try and place a value say 285 into the element and then I marshal it I get an output of 285.0... That is fine .However, if I put a value in of say 285292746, I get an output of 2.85292746E8 when I marshal.
I like something so that double output does not get converted into scientific notation with decimal? Basically I want 285292746 or 2852292746.0000000
java.lang.Double.toString() uses "computerized scientific notation" for certain values which produce isues for xml.
I know double representation of given value is fine. But the fact the value was in exponential format, The system that I am working on is accept my XML but does not know what to do with the exponential value and that causes my program not to work correctly. Changing xsd:double type in WSDL or server is not feasible for me. I am working on client side.
I came across Jaxb:binding for xsd:double type. I am still having hard time to fix the issue to send values double value in non –exponents format.
package com.logger.client
import javax.xml.bind.annotation.adapters.XmlAdapter;
import javax.xml.bind.DatatypeConverter;
public class JaxbDoubleSerializer extends XmlAdapter<String, Double>
{
public Double unmarshal(String value) {
return ((double)javax.xml.bind.DatatypeConverter.parseDouble(value));
}
public String marshal(Double value) {
if (value == null) {
return null;
}
return (javax.xml.bind.DatatypeConverter.printDouble((double)(double)value));
}
}
I need help how to use DoubleSerializer so that I can pass values without exponents. I tried using xmlAdapter Annotation in my class MyLogClient.java. I need to know how I can solve this situation.
package com.logger.client
import javax.xml.ws.BindingProvider;
import javax.xml.bind.JAXBElement;import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.XmlValue;
public class MyLogClient
{
//Private member fields
/** Object factory used to create user-and-role specific objects. */
private static final ObjectFactory _of = new ObjectFactory();
#XmlJavaTypeAdapter(JaxbDoubleSerializer.class)
public JAXBElement<Double> msgFileId;
#XmlJavaTypeAdapter(JaxbDoubleSerializer.class)
public Double dNumber;
public final void createEntry;
(
final String userName,
final String time,
final String logMsgStringId,
final Params logMsgParamsVal,
final Integer logMessageFieldID
)
throws JAXBException
{
JAXBElement<String> username = _of.createParamsParam(userName);
JAXBElement<String> strTime = _of.createLogRequestTime(time);
// Build the LogRequest request.
final LogRequest _LogRequest = _of.createLogRequest();
_LogRequest.setUserName(userName);
_LogRequest.setTime(strTime);
//Following is the main problem
int nMsgArgs = 285292746;
dNumber = Double.parseDouble(Integer.toString(nMsgArgs));
//After parsing double Value I get dNumber is now 2.85292746E8
//MsgFile Id is of Type JAXBElement<Double>
//CreateLogMessageIdentifier takes Double param
//So the main problem is here..the value of double field in soap request
//is being sent in exponential format. I need to send as I explained above
//285292746.
msgFileId = _of.createLogMessageIdentifier(dNumber);
JAXBElement<String> strIdVal = _of.createLogMessageFileId(logMsgStringId);
final LogMessage logMessage = _of.createLogMessage();
JAXBElement<Params> _logMsgParams =_of.createLogMessageParams(logMsgParamsVal);
//Following is where I am trying to use marshall for double type.
JAXBContext context = JAXBContext.newInstance("package com.logger.client ");
context.createMarshaller().marshal(msgFileId, System.out);
logMessage.setIdentifier(msgFileId); //Method takes JAXBElement<Double>
logMessage.setFileId(strIdVal );
logMessage.setParams(_logMsgParams);
JAXBElement<LogMessage> logMsgValue = _of.createLogRequestLogMessage(logMessage);
_LogRequest.setLogMessage(logMsgValue);
// Set the log entry
port.log(_LogRequest); //Request is sent to server.
}
WSDL xsd:type declaration is below:-
<xsd:complexType name="LogMessage">
<xsd:sequence>
<xsd:element name="fileId" type="xsd:string" minOccurs="0" nillable="true" />
<xsd:element name="identifier" type="xsd:double" minOccurs="0" nillable="true" />
<xsd:element name="params" type="tns:Params" minOccurs="0" nillable="true" />
</xsd:sequence>
</xsd:complexType>
Output for identifier field is:-
<identifier> 2.85292746E8</indentifier>
Whereas I want to send as. Because system does accept/recognize following types.
<identifier> 285292746</indentifier>
or
<identifier> 285292746.00000000</indentifier>
You could use an external bindings file like the following:
binding.xml
<jxb:bindings
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:jxb="http://java.sun.com/xml/ns/jaxb"
version="2.1">
<jxb:globalBindings>
<jxb:javaType name="java.lang.Double"
xmlType="xs:double"
parseMethod="javax.xml.bind.DatatypeConverter.parseDouble"
printMethod="javax.xml.bind.DatatypeConverter.printDouble" />
</jxb:globalBindings>
</jxb:bindings>
root.xsd
<?xml version="1.0"?>
<xs:schema
elementFormDefault="qualified"
targetNamespace="http://www.example.com"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:complexType name="root">
<xs:sequence>
<xs:element name="foo" type="xs:double" />
<xs:element name="bar" type="xs:double" />
</xs:sequence>
</xs:complexType>
</xs:schema>
XJC Call
xjc -d out -b binding.xml root.xsd
Root
The class generated for the root type will have XmlAdapter classes registered on the Double properties:
package com.example;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlSchemaType;
import javax.xml.bind.annotation.XmlType;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import org.w3._2001.xmlschema.Adapter1;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlType(name = "root", propOrder = {
"foo",
"bar"
})
public class Root {
#XmlElement(required = true, type = String.class)
#XmlJavaTypeAdapter(Adapter1 .class)
#XmlSchemaType(name = "double")
protected Double foo;
#XmlElement(required = true, type = String.class)
#XmlJavaTypeAdapter(Adapter1 .class)
#XmlSchemaType(name = "double")
protected Double bar;
public Double getFoo() {
return foo;
}
public void setFoo(Double value) {
this.foo = value;
}
public Double getBar() {
return bar;
}
public void setBar(Double value) {
this.bar = value;
}
}
Adapter1
The XmlAdapter utilizes the methods you configured in the binding.xml file.
package org.w3._2001.xmlschema;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class Adapter1 extends XmlAdapter<String, Double> {
public Double unmarshal(String value) {
return (javax.xml.bind.DatatypeConverter.parseDouble(value));
}
public String marshal(Double value) {
if (value == null) {
return null;
}
return (javax.xml.bind.DatatypeConverter.printDouble(value));
}
}
The best way might be to use a custom binding (javaType clause) with your JAXB compiler. Documentation can be found here. Depending if you have to marshal and unmarshall doubles, the solution might be as simple as overriding the mapping to something such as a BigDecimal at the global level (with the understanding that although doubles and decimals are totally different things, you seem to want a decimal representation), or to use a datatype converter (the link above gives you examples for all these options).

Does JAXB support default schema values?

I have a schema that defines default values for elements and attributes. I am trying to parse a document using JAXB based on that schema but JAXB is not setting the default values. Any ideas on how to make JAXB honor the default values from the schema?
example.xsd:
<?xml version="1.0" encoding="UTF-8"?><xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://www.example.org/example"
xmlns:tns="http://www.example.org/example">
<xs:element name="root" type="tns:rootType"/>
<xs:complexType name="rootType">
<xs:sequence>
<xs:element name="child" type="tns:childType"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="childType">
<xs:sequence>
<xs:element name="childVal" type="xs:string" default="defaultElVal"/>
</xs:sequence>
<xs:attribute name="attr" type="xs:string" default="defaultAttrVal"/>
</xs:complexType>
example1.xml
<?xml version="1.0" encoding="UTF-8"?>
<tns:root xmlns:tns="http://www.example.org/example" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.example.org/example example.xsd ">
<child>
<childVal/>
</child>
</tns:root>
TestParser.java
package test;
import java.io.File;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
public class TestParser {
public static void main(String[] pArgs) {
try {
JAXBContext context = JAXBContext.newInstance(RootElement.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
SchemaFactory schemaFac = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema sysConfigSchema = schemaFac.newSchema(
new File("example.xsd"));
unmarshaller.setSchema(sysConfigSchema);
RootElement root = (RootElement)unmarshaller.unmarshal(
new File("example1.xml"));
System.out.println("Child Val: " + root.getChild().getChildVal());
System.out.println("Child Attr: " + root.getChild().getAttr());
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
RootElement.java
package test;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="root", namespace="http://www.example.org/example")
public class RootElement {
private ChildEl child;
public RootElement() {}
public ChildEl getChild() {
return child;
}
public void setChild(ChildEl pChild) {
this.child = pChild;
}
}
ChildEl.java
package test;
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement(name="child")
public class ChildEl {
private String attr;
private String childVal;
public ChildEl() {};
#XmlAttribute
public String getAttr() {
return attr;
}
public void setAttr(String pAttr) {
this.attr = pAttr;
}
public String getChildVal() {
return childVal;
}
public void setChildVal(String pVal) {
this.childVal = pVal;
}
}
Element Default Value
To get the default value on the element property you need to annotate it as follows:
#XmlElement(defaultValue="defaultElVal")
public String getChildVal() {
return childVal;
}
Attribute Default Value
If you use EclipseLink JAXB (MOXy) you will get the default attribute value using the code you supplied. There may be a bug in the Metro implementation of JAXB that is preventing this from working. Note I lead the MOXy implementation.
Alternate Approach
The following code should work with any JAXB implementation without requiring any code changes to your model. You could do the following and leverage SAXSource:
import java.io.File;
import java.io.FileInputStream;
import javax.xml.XMLConstants;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.sax.SAXSource;
import javax.xml.validation.Schema;
import javax.xml.validation.SchemaFactory;
import org.xml.sax.InputSource;
import org.xml.sax.XMLReader;
public class TestParser {
public static void main(String[] pArgs) {
try {
JAXBContext context = JAXBContext.newInstance(RootElement.class);
Unmarshaller unmarshaller = context.createUnmarshaller();
SchemaFactory schemaFac = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI);
Schema sysConfigSchema = schemaFac.newSchema(
new File("example.xsd"));
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setSchema(sysConfigSchema);
XMLReader xmlReader = spf.newSAXParser().getXMLReader();
SAXSource source = new SAXSource(xmlReader, new InputSource(new FileInputStream("example1.xml")));
RootElement root = (RootElement)unmarshaller.unmarshal(
source);
System.out.println("Child Val: " + root.getChild().getChildVal());
System.out.println("Child Attr: " + root.getChild().getAttr());
} catch (Exception e) {
System.out.println(e.getMessage());
e.printStackTrace();
}
}
}
I find what you're trying to do as sensible, especially to have harmony with Attribute vs. Simple Elements. It seems odd me, but it seems the jaxb2 implementors choose to add an extra set of extensions which you have to add to get the desired behavior. See:
http://java.net/projects/jaxb2-commons/pages/Default-Value
(I would have rather seen more natural default behaviors and consistency between Attributes and Elements of at least simple types -- without having to register a plugin. Then provide a plug-in for special cases. My only guys on why this wasn't done was or backwards compatibility--a guess.)
The jaxb2-commons default value plugin refers to an extra commands (and jars) you add to xjc which in turn adds default behaviors to the field. In my case:
public String getScalarOptionalMaxAndDefaultString() {
if (scalarOptionalMaxAndDefaultString == null) {
return "def val 1";
} else {
return scalarOptionalMaxAndDefaultString;
}
}
(Where, of course, the conditional null check presents the default value or not.)
Using Blaise Doughan seems like an practical work around. Depending the nature of your XML doc, this may be perfect.
Yet, it seems this Default Value plugin might move the solution to the build process and not see a change to your code (assuming you're using a Dom as opposed to Sax parser Blaise suggested).
It looks the default-value plugin solve the problem and possibly provide additional extensibility (haven't needed such advanced customization) in the unlikely event you require even more programatic default value control running xjc.
Here is a maven config snippet in case it helps:
<plugin>
<groupId>org.jvnet.jaxb2.maven2</groupId>
<artifactId>maven-jaxb2-plugin</artifactId>
<version>0.8.0</version>
<executions>
<execution>
<phase>generate-sources</phase>
<goals>
<goal>generate</goal>
</goals>
<configuration>
<args>
<arg>-Xdefault-value</arg>
</args>
<plugins>
<plugin>
<groupId>org.jvnet.jaxb2_commons</groupId>
<artifactId>jaxb2-default-value</artifactId>
<version>1.1</version>
</plugin>
</plugins>
</configuration>
</execution>
</executions>
<configuration><schemaDirectory>src/test/resources</schemaDirectory></configuration>
</plugin>
Another way for setting the default value can be a beforeMarshal(Marshaller marshaller) function:
private void beforeMarshal(Marshaller marshaller) {
childVal = (null == getChildVal) ? CHILD_VAL_DEFAULT_VALUE : childVal; }

Resources