Friday, May 7, 2010

JAXB immutable objects

Yesterday, we faced a weird problem. Apache cxf was not generating schema definitions for immutable objects. Looking a bit deeper, the problem was with JAXB, the default databinding technology for apache cxf. Googled "jaxb immutable", and found out i was not alone facing the problem, but the solution of using the "no-args constructor" did not work me. Finally after spending a good 2 hrs on it, finally found the solution. You need to add a no-args constructor AND add @XmlAccessorType(XmlAccessType.FIELD) annotation to the class.

The following object did NOT work -

public class CreditCardVO implements Serializable {
private Long ccNumber;
private String ccName;

public CreditCardVO(Long ccNumber, String ccName) {
this.ccNumber = ccNumber;
this.ccName = ccName;
}

public Long getCcNumber() {
return ccNumber;
}

public String getCcName() {
return ccName;
}

}

When i added the no-args constructor and the annotations it worked!

@XmlAccessorType(XmlAccessType.FIELD)
public class CreditCardVO implements Serializable {
private Long ccNumber;
private String ccName;

public CreditCardVO(Long ccNumber, String ccName) {
this.ccNumber = ccNumber;
this.ccName = ccName;
}

private CreditCardVO() {
// for JAXB's Magic
}

public Long getCcNumber() {
return ccNumber;
}

public String getCcName() {
return ccName;
}

}

5 comments:

Blaise Doughan said...

Hello,

Below is an alternate approach to handling immutable objects in JAXB using XmlAdapter:

Java XML Binding: JAXB and Immutable Objects

-Blaise

Ashish Waghmare said...

Better is use Private Default No Arg constructor and use static function to create objects

Anonymous said...

Hey! Ashish. I tried your solution but i am get Error while loading configuration file: Unable to create an instance of error. The class is not an abstract class. you have any idea on why I am getting this error?

Shaligram said...

Thnks for sharing knowledge
http://www.shaligram.com/index.php

Joachim Lous said...

I hate boilerplate, so my immutable objects always use public final fields and no getters, if I can get away with it.

With jaxb that means adapters (boilerplate galore!), so it has to be jackson-dataformat-xml. Sadly that does not support default namespaces, so you need to annotate every single field if you use a namespace. So you get boilerplate anyway, but alt least it is trivial boilerplate, and the actual java code (excluding annotations) is clean.