Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting POJO into XML without default POJO constructor

I'm trying to convert a POJO (Plain old Java Object) into XML using java.beans.XMLEncoder. My code works fine but I found one interesting problem that occurs when I omit the default constructor in my POJO. Classes are below.

POJO without default constructor

public class NFLTeam implements Serializable {

  private String name;
  private String description;

  // public NFLTeam() {
  //
  // }

  public NFLTeam(String name, String description) {
    this.name = name;
    this.description = description;
  }

  public String getName() {
        return name;
    }

  public void setName(String name) {
    this.name = name;
  }

  public String getDescription() {
    return description;
  }

  public void setDescription(String description) {
    this.description = description;
  }

}

Invocation of XMLEncoder

public static void main(String args[]) {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    XMLEncoder xmlEncoder = new XMLEncoder(byteArrayOutputStream);
    NFLTeam team = new NFLTeam("Bears", "Play for Chicago");
    xmlEncoder.writeObject(team);
    xmlEncoder.close();
    System.out.println(byteArrayOutputStream);
}

Console output with default constructor omitted

java.lang.InstantiationException: oce.wsd.pojos.NFLTeam
Continuing ...
java.lang.Exception: XMLEncoder: discarding statement XMLEncoder.writeObject(NFLTeam);
Continuing ...
<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_45" class="java.beans.XMLDecoder">
</java>

Console output with default constructor

<?xml version="1.0" encoding="UTF-8"?>
<java version="1.7.0_45" class="java.beans.XMLDecoder">
<object class="oce.wsd.pojos.NFLTeam">
    <void property="description">
      <string>Play for Chicago</string>
    </void>
    <void property="name">
     <string>Bears</string>
   </void>
</object>
</java>

I was googling around but cannot find any explanation for this. Why is the implicit default constructor not enough for XMLEncoder?

like image 448
Jason Avatar asked Mar 18 '23 21:03

Jason


1 Answers

Unfortunately JAXB (and linked technologies) requires a non-arg constructor (implicit default constructor is fine as well).

According to the specification and in case of native Oracle JAX library it is required for both marshaling and un-marshaling.

According to the human logic it is not needed for marshaling/serialization. For example the most popular JSON library Jackson does have such a requirement only for de-serialization.

There are third party XML JAX compatible parsers which are less restrictive as well... but this issue is usually not a reason for struggling with a third party library.

JAX allows to have a non-argument constructor non-public. I usually create it as follow:

/** For JAXB only. Do not call directly and do not delete! */
@Deprecated
protected NFLTeam () {
    // nothing
}
like image 88
30thh Avatar answered Apr 06 '23 03:04

30thh