Thursday, July 29, 2010

JAXB2 Annotations

It is scary to find out that a dependency of your project is no longer supported and you really need a code update. That's what happened to me when I requested the source code of one dependency and I was told no one can find it.

The dependency I need to update is a JAXB client implementation to connect to liveglobalbid (lgb) - a leading developer of online auction software providing a high quality, real time simultaneous video and audio broadcast of a live auction sale. And surprisingly, I was able to get rid of the dependency along with the JAXB dependencies and use JAXB 2.0 API that comes with Java 5 and above.  Besides that, by using JAXB 2.0 Annotations, the new client implementation is simple and light.

First, a sample xml I'll get from lgb:
<?xml version="1.0" encoding="UTF-8" ?>
<caster xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://www.liveglobalbid.com/caster.xsd">
    <pid>25717</pid>
    <mountpoint name="blah blah">
        <source id="9">
            <type>sound</type>
            <remoteid>blah blah</remoteid>
            <average_frame_size>94</average_frame_size>
            <average_frame_rate>3.83</average_frame_rate>
        </source>
    </mountpoint>
</caster>

Basic structure here is:
  • Caster is the main object (XmlRootElement), which contains a pid and one or more mountpoint object (XmlElement).
  • A mountpoint object has one or more source object (XmlElement)
  • A source has type, remoteid, average_frame_size, and average_frame_rate (XmlElement)
  • So in total, we'll need 3 object models: Caster, MountPoint (XmlType), and Source (XmlType).
  • MountPoint has an attribute called name (XmlAttribute)
  • Source has an attribute called id (XmlAttribute)

Source.java
package com.my.company.caster.jaxb2;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 * @author k_wang
 *
 */
@XmlType
public class Source {

    @XmlAttribute
    protected int id;

    @XmlElement
    protected String type;

    @XmlElement
    protected String remoteid;

    @XmlElement
    protected int average_frame_size;

    @XmlElement
    protected double average_frame_rate;

    /**
     * default constructor
     */
    public Source() {
        super();
    }

    /**
     * full constructor
     */
    public Source(int id, String type, String remoteid,
          int average_frame_size, double average_frame_rate) {
        super();
        this.id = id;
        this.type = type;
        this.remoteid = remoteid;
        this.average_frame_size = average_frame_size;
        this.average_frame_rate = average_frame_rate;
    }

    public int getId() {
        return id;
    }

    public String getType() {
        return type;
    }

    public String getRemoteid() {
        return remoteid;
    }

    public int getAverageFrameSize() {
        return average_frame_size;
    }

    public int getAverageFrameRate() {
        return average_frame_rate;
    }
}


MountPoint.java
package com.my.company.caster.jaxb2;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlType;

/**
 * @author k_wang
 *
 */
@XmlType(name="mountpoint")
public class MountPoint {

    @XmlAttribute
    protected String name;

    @XmlElement
    protected List<Source> source = new ArrayList<Source>();

    public MountPoint() {
        super();
    }

    /**
     * @param name
     * @param source
    */
    public MountPoint(String name, List<Source> source) {
        super();
        this.name = name;
        if(source != null)
            this.source = source;
    }

    public String getName() {
        return name;
    }

    public List<Source> getSource() {
        return source;
    }
}


Caster.java
package com.my.company.caster.jaxb2;

import java.util.ArrayList;
import java.util.List;

import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;

/**
 * @author k_wang
 *
 */
 @XmlRootElement(name="caster")
public class Caster {

    @XmlElement
    protected long pid;

    @XmlElement
    protected List<MountPoint> mountpoint = new ArrayList<MountPoint>();

    public Caster() {
        super();
    }

    public Caster(long pid, List<MountPoint> mountpoint) {
        super();
        this.pid = pid;
        this.mountpoint = mountpoint;
    }

    public long getPid() {
        return pid;
    }

    public List<MountPoint> getMountpoint() {
        return mountpoint;
    }
}


And to get the Caster model from a URL:
public Caster getCaster(URL url) throws JAXBException {
    Caster caster = null;
    try {
        InputStream in = url.openStream();
        Unmarshaller unmarshaller = JAXBContext.newInstance(Caster.class).createUnmarshaller();
        caster = (Caster) unmarshaller.unmarshal(new StreamSource(in));
        in.close();
    } catch (IOException e) {
        new JAXBException("Unable to parse source input stream: ", e);
    }
    return caster;
}

No comments: