Tuesday, February 17, 2015

Ran into an interesting JAXB issue. We have several classes that all extends a Base class. At one point I introduced an object property into the base class, that also happened to be a property defined in just ONE of the subclasses. This caused any setter of this property from ANY subclasses (outside the one with that property overridden) to have this property completely ignored in the XML output. Example
@XmlRootElement(name = "animal")
@XmlAccessorType(XmlAccessType.FIELD)
@XmlSeeAlso({Dog.class, Fish.class})
public class Animal {
    protected String movement;
     ....
}

@XmlRootElement(name = "dog")
@XmlSeeAlso({Animal.class})
@XmlAccessorType(XmlAccessType.FIELD)
public class Dog extends Animal {
   private String breed;
   protected String movement;
   ....
}

@XmlRootElement(name = "fish")
@XmlSeeAlso({Animal.class})
@XmlAccessorType(XmlAccessType.FIELD)
public class Fish extends Animal {
    private String scaleType;
    ....
}

public static void main(String[] args) {
    Dog dog = new Dog();
    dog.setBreed("lab");
    dog.setMovement("walks"); 
    String xml = AnimalJaxb.toXml(dog);
    System.out.println("dog = "+xml);

    Fish fish = new Fish();
    fish.setMovement("swims"); //WILL NOT SHOW UP IN XML!
    fish.setScaleType("normal"); 
    String xml = AnimalJaxb.toXml(fish);
    System.out.println("fish = "+xml); 
When the above runs. The "movement" property on Fish will NOT be in the XML. To fix this, I needed to remove the overridden movement property in the Dog class. What's frustrating is JAXB doesn't throw any errors or complain. The only way it will complain is if I make the base class (Animal) abstract and mark it @XmlTransient, afterwhich JAXB will complain about having "two properties with the same name."

No comments :

Post a Comment

Blogger Syntax Highliter