Can JAXB/MOXy serialize enums in the same way as regular classes (non-enums)? - jaxb

Imagine I have enum defined like this:
public enum ArchiveStatus implements Serializable {
CANDIDATE (0, "CANDIDATE", "Candidate for archival"),
IN_LIBRARY (1, "IN-LIBRARY", ".."),
FROM_LIBRARY (2, "FROM-LIBRARY", "..");
private int id;
private String shortName;
private String longName;
public ArchiveStatus( int id, String shortName, String longName ) {
..
}
public int getId() { .. }
public String getShortName() { .. }
public String getLongName() { .. }
}
By default MOXy is going to serialize it to JSON like this:
{
..
"archiveStatus": "CANDIDATE",
..
}
Is there a way to configure MOXy (in the mapping file) to serialize the enum like a regular class:
{
..
"archiveStatus": { "id" : 0, "shortName": "CANDIDATE", "longName": "Candidate for archival" },
..
}

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB 2 (JSR-222) expert group.
ArchiveStatusAdapter
You can solve this use case by leveraging an XmlAdapter. XmlAdapter is a JAXB mechanism that allows you to marshal one type of object as another.
package forum10144489;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class ArchiveStatusAdapter extends XmlAdapter<ArchiveStatusAdapter.AdaptedArchiveStatus, ArchiveStatus> {
public static class AdaptedArchiveStatus {
public int id;
public String shortName;
public String longName;
}
#Override
public ArchiveStatus unmarshal(AdaptedArchiveStatus adaptedArchiveStatus) throws Exception {
if(null == adaptedArchiveStatus) {
return null;
}
return ArchiveStatus.valueOf(adaptedArchiveStatus.shortName);
}
#Override
public AdaptedArchiveStatus marshal(ArchiveStatus archiveStatus) throws Exception {
if(null == archiveStatus) {
return null;
}
AdaptedArchiveStatus adaptedArchiveStatus = new AdaptedArchiveStatus();
adaptedArchiveStatus.id = archiveStatus.getId();
adaptedArchiveStatus.longName = archiveStatus.getLongName();
adaptedArchiveStatus.shortName = archiveStatus.getShortName();
return adaptedArchiveStatus;
}
}
Root
The XmlAdapter can be specified at the field, property, type, or package level using the #XmlJavaTypeAdapter annotation.
package forum10144489;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
public class Root {
private ArchiveStatus archiveStatus;
#XmlJavaTypeAdapter(ArchiveStatusAdapter.class)
public ArchiveStatus getArchiveStatus() {
return archiveStatus;
}
public void setArchiveStatus(ArchiveStatus archiveStatus) {
this.archiveStatus = archiveStatus;
}
}
jaxb.properties
To specify MOXy as your JAXB provider you need to add a file called jaxb.properties in the same package as your domain classes with the following entry.
javax.xml.bind.context.factory = org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
package forum10144489;
import java.io.StringReader;
import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>(2);
properties.put("eclipselink.media-type", "application/json");
properties.put("eclipselink.json.include-root", false);
JAXBContext jc = JAXBContext.newInstance(new Class[] {Root.class}, properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StringReader jsonStringReader = new StringReader("{\"archiveStatus\" : {\"id\" : 0, \"shortName\" : \"CANDIDATE\", \"longName\" : \"Candidate for archival\"}}");
StreamSource jsonSource = new StreamSource(jsonStringReader);
Root root = unmarshaller.unmarshal(jsonSource, Root.class).getValue();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Output
Below is the output from running the demo code:
{
"archiveStatus" : {
"id" : 0,
"shortName" : "CANDIDATE",
"longName" : "Candidate for archival"
}
}
For More Information
http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html
http://blog.bdoughan.com/search/label/XmlAdapter
http://blog.bdoughan.com/search/label/jaxb.properties

Related

Creating null object for input StringReader using JAXBContext

I am trying to create bean from string but unable to create as it is returning null.Here is my code
public ModelAndView checkPhotoQualityRequest(
#RequestBody String photoDataXml, HttpServletRequest request) {
PhotoQuality photoQuality = null;
try {
JAXBContext jaxbContext = JAXBContext
.newInstance(PhotoQuality.class);
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
StringReader reader = new StringReader(photoDataXml);
photoQuality = (PhotoQuality) unmarshaller.unmarshal(reader);
PhotoQuality.java
package in.gov.uid.opencvaccess.bean;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.XmlType;
#XmlType(name = "PhotoQuality")
#XmlRootElement(name = "PhotoQuality")
public class PhotoQuality {
private String photoid;
private byte[] photo;
private boolean quality;
private String message;
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public String getPhotoid() {
return photoid;
}
public void setPhotoid(String photoid) {
this.photoid = photoid;
}
public byte[] getPhoto() {
return photo;
}
public void setPhoto(byte[] photo) {
this.photo = photo;
}
public boolean isQuality() {
return quality;
}
public void setQuality(boolean quality) {
this.quality = quality;
}
}
Please help me to sort out this issue.When I debug and check bean its showing all null values but photoDataXml showing complete xml.
I have found the reason.When I tried using RESTClient its giving null object. But as soon as I written client code and passed StringWriter value created from PhotoQuality Object then it runs properly.

JAXB and inheritance

I am trying to read a JSON file like:
{
"a": "abc",
"data" : {
"type" : 1,
...
}
}
where the ... part is replaceable based on the type like:
{
"a": "abc",
"data" : {
"type" : 1,
"b" : "bcd"
}
}
or:
{
"a": "abc",
"data" : {
"type" : 2,
"c" : "cde",
"d" : "def",
}
}
For the life of me I cannot figure out the proper JAXB annotations/classes to use to make this happen.
I don't have an issue moving the type variable outside of the data block if needed.
I'm using Glassfish 3.1.2.2.
Edit:
Based on the code provided by Perception I did a quick attempt... doesn't work in glassfish though:
#JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = As.PROPERTY, property = "type")
#JsonSubTypes(
{
#JsonSubTypes.Type(value = DataSubA.class, name = "1"),
#JsonSubTypes.Type(value = DataSubB.class, name = "2")
})
#XmlRootElement
public abstract class Data implements Serializable
{
private static final long serialVersionUID = 1L;
public Data()
{
super();
}
}
#XmlRootElement
#XmlAccessorType(XmlAccessType.NONE)
public class DataSubA
extends Data
{
private static final long serialVersionUID = 1L;
#XmlElement
private BigDecimal expenditure;
public DataSubA() {
super();
}
public DataSubA(final BigDecimal expenditure) {
super();
this.expenditure = expenditure;
}
#Override
public String toString() {
return String.format("%s[expenditure = %s]\n",
getClass().getSimpleName(), getExpenditure());
}
public BigDecimal getExpenditure() {
return expenditure;
}
public void setExpenditure(BigDecimal expenditure) {
this.expenditure = expenditure;
}
}
#XmlRootElement
#XmlAccessorType(XmlAccessType.NONE)
public class DataSubB
extends Data
{
private static final long serialVersionUID = 1L;
#XmlElement
private String name;
#XmlElement
private Integer age;
public DataSubB()
{
super();
}
public DataSubB(final String name, final Integer age)
{
super();
this.name = name;
this.age = age;
}
#Override
public String toString()
{
return String.format("%s[name = %s, age = %s]\n",
getClass().getSimpleName(), getName(), getAge());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return age;
}
public void setAge(Integer age) {
this.age = age;
}
}
#XmlRootElement
#XmlAccessorType(XmlAccessType.NONE)
public class DataWrapper
{
#XmlElement
private Data data;
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
}
And a simple POST that takes it in:
#Stateless
#Path("x")
public class Endpoint
{
#POST
#Consumes(
{
MediaType.APPLICATION_JSON,
})
#Produces(
{
MediaType.APPLICATION_JSON,
})
public String foo(final DataWrapper wrapper)
{
return ("yay");
}
}
When I pass in JSON like:
{
"data" :
{
"type" : 1,
"expenditure" : 1
}
}
I get a message like:
Can not construct instance of Data, problem: abstract types can only be instantiated with additional type information
at [Source: org.apache.catalina.connector.CoyoteInputStream#28b92ec1; line: 2, column: 5] (through reference chain: DataWrapper["data"])
On the DataClass add an #XmlSeeAlso annotation that specifies all of the subclasses:
#XmlRootElement
#XmlSeeAlso({DataSubA.class, DataSubB.class})
public abstract class Data implements Serializable {
Then on each of the subclasses use the #XmlType annotation to specify the type name.
#XmlType(name="1")
public class DataSubA extends Data {
UPDATE
Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.
The JAXB (JSR-222) specification doesn't cover JSON-binding. There are different ways JAX-RS allows you to specify JSON mapping via JAXB annotations:
A JAXB implementation plus a library like Jettison that converts StAX events to JSON (see: http://blog.bdoughan.com/2011/04/jaxb-and-json-via-jettison.html)
By leveraging a JAXB impl that offers a JSON-binding (see: http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html)
Leveraging a JSON-binding tool that offers support for some JAXB metadata (i.e Jackson).
Since your model doesn't seem to be reacting as expected to the annotations I'm guessing you are using scenario 3. Below I will demonstrate the solution as if you were using scenario 2.
DataWrapper
import javax.xml.bind.annotation.*;
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public class DataWrapper {
private String a;
private Data data;
}
Data
import javax.xml.bind.annotation.*;
#XmlAccessorType(XmlAccessType.FIELD)
#XmlSeeAlso({DataSubA.class, DataSubB.class})
public class Data {
}
DataSubA
import javax.xml.bind.annotation.XmlType;
#XmlType(name="1")
public class DataSubA extends Data {
private String b;
}
DataSubB
import javax.xml.bind.annotation.XmlType;
#XmlType(name="2")
public class DataSubB extends Data {
private String c;
private String d;
}
jaxb.properties
To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.JAXBContextProperties;
public class Demo {
public static void main(String[] args) throws Exception {
Map<String, Object> properties = new HashMap<String, Object>();
properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
JAXBContext jc = JAXBContext.newInstance(new Class[] {DataWrapper.class}, properties);
Unmarshaller unmarshaller = jc.createUnmarshaller();
StreamSource json = new StreamSource("src/forum16429717/input.json");
DataWrapper dataWrapper = unmarshaller.unmarshal(json, DataWrapper.class).getValue();
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(dataWrapper, System.out);
}
}
input.json/Output
MOXy can read in the numeric value 2 as the inheritance indicator, but currently it will always write it out as "2". I have opened the following enhancement request to address this issue: http://bugs.eclipse.org/407528.
{
"a" : "abc",
"data" : {
"type" : "2",
"c" : "cde",
"d" : "def"
}
}
For More Information
The following link will help you use MOXy in a JAX-RS implementation.
http://blog.bdoughan.com/2012/05/moxy-as-your-jax-rs-json-provider.html

MOXy JAXB: how to map several XML tag elements to the same JAVA bean property

I am trying to unmarshall an XML file using MOXy JAXB. I have a set of classes, already generated, and I am using Xpath to map every XML element I need into my model.
I have an XML file like this:
<?xml version="1.0" encoding="UTF-8"?>
<fe:Facturae xmlns:ds="http://www.w3.org/2000/09/xmldsig#"
xmlns:fe="http://www.facturae.es/Facturae/2009/v3.2/Facturae">
<Parties>
<SellerParty>
<LegalEntity>
<CorporateName>Company Comp SA</CorporateName>
<TradeName>Comp</TradeName>
<ContactDetails>
<Telephone>917776665</Telephone>
<TeleFax>917776666</TeleFax>
<WebAddress>www.facturae.es</WebAddress>
<ElectronicMail>facturae#mityc.es</ElectronicMail>
<ContactPersons>Fernando</ContactPersons>
<CnoCnae>28000</CnoCnae>
<INETownCode>2134AAB</INETownCode>
<AdditionalContactDetails>Otros datos</AdditionalContactDetails>
</ContactDetails>
</LegalEntity>
</SellerParty>
<BuyerParty>
<Individual>
<Name>Juana</Name>
<FirstSurname>MauriƱo</FirstSurname>
<OverseasAddress>
<Address>Juncal 1315</Address>
<PostCodeAndTown>00000 Buenos Aires</PostCodeAndTown>
<Province>Capital Federal</Province>
<CountryCode>ARG</CountryCode>
</OverseasAddress>
<ContactDetails>
<Telephone>00547775554</Telephone>
<TeleFax>00547775555</TeleFax>
</ContactDetails>
</Individual>
</BuyerParty>
</Parties>
</fe:Facturae>
Then I have my model:
#XmlRootElement(namespace="http://www.facturae.es/Facturae/2009/v3.2/Facturae", name="Facturae")
public class Facturae implements BaseObject, SecuredObject, CreationDataAware {
#XmlPath("Parties/SellerParty")
private Party sellerParty;
#XmlPath("Parties/BuyerParty")
private Party buyerParty;
}
public class Party implements BaseObject, SecuredObject, CreationDataAware {
#XmlPath("LegalEntity/ContactDetails")
private ContactDetails contactDetails;
}
As you can see, <ContactDetails></ContactDetails> is present in <SellerParty></SellerParty> and <BuyerParty></BuyerParty> but this two tags share the same JAVA object (Party). With the previous mapping (#XmlPath("LegalEntity/ContactDetails")) I can pass correctly the ContactDetails info in SellerParty, but I want also to pass the ContactDetails in <BuyerParty> at the same time.
I was trying something like that:
#XmlPaths(value = { #XmlPath("LegalEntity/ContactDetails"),#XmlPath("Individual/ContactDetails") })
private ContactDetails contactDetails;
but it doesn't work.
Can you guys give me a hand?
Thank you very much.
You could use an XmlAdapter for this use case:
PartyAdapter
We will use an XmlAdapter to convert an instance of Party to another type of object AdaptedParty. AdaptedParty will have two properties corresponding to each property in Party (one for each mapping possibility). We will take advantage of the ability to pre-initialize an instance of XmlAdapter to set an instance of Facturae on it. We will use the instance of Facturae to determine if the instance of Party we are handling is a sellerParty or a buyerParty.
package forum9807536;
import javax.xml.bind.annotation.adapters.XmlAdapter;
import org.eclipse.persistence.oxm.annotations.XmlPath;
public class PartyAdapter extends XmlAdapter<PartyAdapter.AdaptedParty, Party> {
private Facturae facturae;
public PartyAdapter() {
}
public PartyAdapter(Facturae facturae) {
this.facturae = facturae;
}
#Override
public Party unmarshal(AdaptedParty v) throws Exception {
Party party = new Party();
if(v.individualName != null) {
party.setName(v.individualName);
party.setContactDetails(v.individualContactDetails);
} else {
party.setName(v.sellPartyName);
party.setContactDetails(v.sellerPartyContactDetails);
}
return party;
}
#Override
public AdaptedParty marshal(Party v) throws Exception {
AdaptedParty adaptedParty = new AdaptedParty();
if(null == facturae || facturae.getSellerParty() == v) {
adaptedParty.sellPartyName = v.getName();
adaptedParty.sellerPartyContactDetails = v.getContactDetails();
} else {
adaptedParty.individualName = v.getName();
adaptedParty.individualContactDetails = v.getContactDetails();
}
return adaptedParty;
}
public static class AdaptedParty {
#XmlPath("Individual/Name/text()")
public String individualName;
#XmlPath("Individual/ContactDetails")
public ContactDetails individualContactDetails;
#XmlPath("LegalEntity/CorporateName/text()")
public String sellPartyName;
#XmlPath("LegalEntity/ContactDetails")
public ContactDetails sellerPartyContactDetails;
}
}
Party
We will use the #XmlJavaTypeAdapter to associate the PartyAdapter to the Party class:
package forum9807536;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlJavaTypeAdapter(PartyAdapter.class)
public class Party implements BaseObject, SecuredObject, CreationDataAware {
private String name;
private ContactDetails contactDetails;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ContactDetails getContactDetails() {
return contactDetails;
}
public void setContactDetails(ContactDetails contactDetails) {
this.contactDetails = contactDetails;
}
}
Demo
The following demo code demonstrates how to set a pre-initialized XmlAdapter on the Marshaller:
package forum9807536;
import java.io.File;
import javax.xml.bind.*;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Facturae.class);
File xml = new File("src/forum9807536/input.xml");
Unmarshaller unmarshaller = jc.createUnmarshaller();
Facturae facturae = (Facturae) unmarshaller.unmarshal(xml);
Marshaller marshaller = jc.createMarshaller();
marshaller.setAdapter(new PartyAdapter(facturae));
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(facturae, System.out);
}
}
Output
Below is the output from the demo code that corresponds to the portion of your model that I have mapped.
<?xml version="1.0" encoding="UTF-8"?>
<ns0:Facturae xmlns:ns0="http://www.facturae.es/Facturae/2009/v3.2/Facturae">
<Parties>
<BuyerParty>
<Individual>
<Name>Juana</Name>
<ContactDetails/>
</Individual>
</BuyerParty>
<SellerParty>
<LegalEntity>
<CorporateName>Company Comp SA</CorporateName>
<ContactDetails/>
</LegalEntity>
</SellerParty>
</Parties>
</ns0:Facturae>
For More Information
http://blog.bdoughan.com/search/label/XmlAdapter
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html

Marshall object field as attribute

Here is what I have so far to marshall my POJO using JAXB :
#XmlRootElement
public class Local {
private Entity entity;
public void setEntity(Entity entity) {
this.entity = entity;
}
#XmlElement
public Entity getEntity() {
return entity;
}
}
and
#XmlRootElement
public class Entity {
private String name;
private String comment;
public void setName(String name){
this.name = name;
}
#XmlAttribute
public String getName(){
return this.name;
}
public void setComment...
#XmlAttribute
public void getComment...
}
With that, I get something like this:
<local>
<entity name="" comment=""></entity>
</local>
However, I would prefer to have the name attribute as an attribute of the local:
<local entityName="" entityComment=""></local>
Is the XmlJavaTypeAdapter a good way to begin with?
Thanks,
Alex
There are a couple of different options to handle this use case:
Option #1 - XmlAdapter (Any JAXB implementation)
You could use an XmlAdapter for this use case. This will work as long as only one attribute value comes from the Entity object:
EntityAdapter
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class EntityAdapter extends XmlAdapter<String, Entity>{
#Override
public String marshal(Entity entity) throws Exception {
if(null == entity) {
return null;
}
return entity.getName();
}
#Override
public Entity unmarshal(String name) throws Exception {
Entity entity = new Entity();
entity.setName(name);
return entity;
}
}
Local
The XmlAdapter is linked with the field/property using the #XmlJavaTypeAdapter annotation:
import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
#XmlRootElement
public class Local {
private Entity entity;
public void setEntity(Entity entity) {
this.entity = entity;
}
#XmlAttribute
#XmlJavaTypeAdapter(EntityAdapter.class)
public Entity getEntity() {
return entity;
}
}
For More Information
http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html
http://blog.bdoughan.com/2010/12/jaxb-and-immutable-objects.html
Option #2 - #XmlPath (EclipseLink JAXB (MOXy)
Alternatively if you are using EclipseLink JAXB (MOXy), the you could use the #XmlPath extension. This is useful with the Entity object corresponds to multiple XML attributes:
Local
Specifying the XPath "." indicated that the child contents will be written into the parent element
import javax.xml.bind.annotation.*;
import org.eclipse.persistence.oxm.annotations.*;
#XmlRootElement
public class Local {
private Entity entity;
public void setEntity(Entity entity) {
this.entity = entity;
}
#XmlPath(".")
public Entity getEntity() {
return entity;
}
}
Entity
public class Entity {
private String name;
private String comment;
public void setName(String name){
this.name = name;
}
#XmlAttribute(name="entityName")
public String getName(){
return this.name;
}
public void setComment(String comment){
this.comment = comment;
}
#XmlAttribute(name="entityComment")
public String getComment(){
return this.comment;
}
}
For More Information
http://bdoughan.blogspot.com/2010/07/xpath-based-mapping.html
http://blog.bdoughan.com/2010/09/xpath-based-mapping-geocode-example.html
http://blog.bdoughan.com/2011/03/map-to-element-based-on-attribute-value.html
http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html

How to prevent marshalling empty tags in JAXB when string is empty but not null

I am trying to make JAXB do not marshal empty tags when string is empty.
I can make it by creating XmlAdapter where insted empty string null would be returned. But in that way, I will have to annotate each attribute with this adapter.
Is there any way to make it more global?
EclipseLink JAXB (MOXy) will let you specify the XmlAdapter for java.lang.String at the package level (I'm the MOXy tech lead):
package-info
#XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
package example;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
StringAdapter
package example;
import javax.xml.bind.annotation.adapters.XmlAdapter;
public class StringAdapter extends XmlAdapter<String, String> {
#Override
public String unmarshal(String v) throws Exception {
return v;
}
#Override
public String marshal(String v) throws Exception {
if("".equals(v)) {
return null;
}
return v;
}
}
Root
package example;
import javax.xml.bind.annotation.XmlRootElement;
#XmlRootElement
public class Root {
private String foo;
private String bar;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
public String getBar() {
return bar;
}
public void setBar(String bar) {
this.bar = bar;
}
}
jaxb.properties
To use MOXy as your JAXB provider you need to include a file named jaxb.properties in the same package as your model classes with the following entry:
javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory
Demo
package example;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
public class Demo {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Root.class);
System.out.println(jc);
Root root = new Root();
root.setFoo("");
root.setBar("");
Marshaller marshaller = jc.createMarshaller();
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
marshaller.marshal(root, System.out);
}
}
Note
Due to what I feel is a bug in the JAXB reference implementation, the following exception is thrown if you use the version of JAXB included in Java SE 6:
Exception in thread "main" java.lang.NullPointerException
at com.sun.xml.bind.v2.runtime.output.Encoded.setEscape(Encoded.java:107)
at com.sun.xml.bind.v2.runtime.output.UTF8XmlOutput.doText(UTF8XmlOutput.java:315)
at com.sun.xml.bind.v2.runtime.output.UTF8XmlOutput.text(UTF8XmlOutput.java:299)
at com.sun.xml.bind.v2.runtime.output.IndentingUTF8XmlOutput.text(IndentingUTF8XmlOutput.java:153)
at com.sun.xml.bind.v2.runtime.XMLSerializer.leafElement(XMLSerializer.java:325)
at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$1.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:210)
at com.sun.xml.bind.v2.model.impl.RuntimeBuiltinLeafInfoImpl$1.writeLeafElement(RuntimeBuiltinLeafInfoImpl.java:209)
at com.sun.xml.bind.v2.runtime.reflect.TransducedAccessor$CompositeTransducedAccessorImpl.writeLeafElement(TransducedAccessor.java:250)
at com.sun.xml.bind.v2.runtime.property.SingleElementLeafProperty.serializeBody(SingleElementLeafProperty.java:98)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeBody(ClassBeanInfoImpl.java:340)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsSoleContent(XMLSerializer.java:593)
at com.sun.xml.bind.v2.runtime.ClassBeanInfoImpl.serializeRoot(ClassBeanInfoImpl.java:324)
at com.sun.xml.bind.v2.runtime.XMLSerializer.childAsRoot(XMLSerializer.java:494)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.write(MarshallerImpl.java:315)
at com.sun.xml.bind.v2.runtime.MarshallerImpl.marshal(MarshallerImpl.java:244)
at javax.xml.bind.helpers.AbstractMarshallerImpl.marshal(AbstractMarshallerImpl.java:75)
at example.Demo.main(Demo.java:18)

Resources