tags:

views:

326

answers:

4

I have a JAXB annotated class say

@XmlRootElement(namespace = "http://www.abc.com/customer")
Class Customer{
@XmlElement(namespace = "http://www.abc.com/customer")
  private String  Name;
  @XmlElement(namespace = "http://www.abc.com/customer")
  private String  Address;
 @XmlTransient
  private HashSet set = new HashSet();

  public String getName(){
    return Name;
  }
  public void  setName(String  name){
    this.Name = name;
    set.add("Name");
  }


  public String getAddress(){
    return Address;
  }
  public void  setAddress(String  address){
    this.Address = address;
    set.add("Address");
  }

  public void getSet(){
return set;
}

I have a XML of the form

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Customer xmlns="http://www.abc.com/customer" >
<Name>Ralph</Name>
<Address>Newton Street</Address>
</Customer>

I use JAXB unmarshalling to get the object representation of the XML input. The values for Name and Address are set correctly. However the value of set gets lost(since it is @XMLTransient it gets ignored)

Is there any way of ensuring that it is still set in the object which has been unmarshalled? Some other annotation which I can use?

+2  A: 

Try putting the annotations on the methods rather than on the fields. Specifically, put @XmlElement on getName() and getAddress(), put @XmlTransient on getSet(), and remove all the annotations from the fields.

JAXB should then use the getter/setter method pairs to inject/retrieve the data, rather than the fields, and because setAddress() adds the value to the set field, that should work as you expect. Also, because getSet() is marked as transient, the contents of set should not be marshalled again.

skaffman
Hi, Thanks for the solution. I tried this one, but none of the XML element values are being set(Name, Address) Is it a valid case to add these annotations to the methods?
sswdeveloper
@sswdeveloper: It is valid, yes, but sometimes you have to juggle things a bit. Try annotating the setter methods rather than the getter methods.
skaffman
A: 

I suggest using some post-processor utility to fill your set. Perhaps using reflection or introspection.

Note that the postprocessor will have to inspect the JAXB annotations only, not the xml file.

Bozho
I could do that, but the set contains only those elements which have been set in the XML, not any other elements. So doing a post processing would involve parsing the XML again and then setting the values/reading all class members and checking if they have been set.However this eliminates the whole point of using JAXB and would be a performance hit. Is there any other alternative using JAXB itsef?Thanks.
sswdeveloper
@sswdeveloper no, the postprocessing will include parsing the JAXB annotations only.
Bozho
A: 

I think you have two problems here:

  1. as skaffman told you, you should put your @XmlElement on the getters
  2. if you put you annotation on the getters jaxb will figure out getAddress to correspond to address element and not Address (notice no non capital "A"), so either change your class or the xml.

to be on the safe side and to allow tolerance to refactoring and cross version support i always use the name value in XmlElement annotation:

@XmlElement(name="Name")
public String getName(){
  return Name;
}
public void  setName(String  name){
  this.Name = name;
  set.add("Name");
}
@XmlElement(name="Address")
public String getAddress(){
  return Address;
}
public void  setAddress(String  address){
  this.Address = address;
  set.add("Address");
}
@XmlTransient
public void getSet(){
  return set;
}

I think it will work

By the way, I would loose the capitals in Address and Name.

ekeren
A: 

To Avoid all this boiler plate code of XmLElement annotation all over the code. You can go ahead and use @XmlAccessType.PROPERTY at the top of the class and you can go remove all the @XmlElement Annotations. The XmlAccessType annotation takes care of telling JAXB to look at the setters and getters and not the field itself.

Vanchinathan Chandrasekaran