Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Marshalling selected fields only, using JAXB

I am using JAXB for marshalling java object to XML. The problem I am facing is that not all member variables of java object instance need to be marshalled XML. For example, my complete XML doc should look like-

<Disk>
  <status>attached</status>
  <size>10000000000</size>
  <freeSpace>25600000<freeSpace>
  <id>MI45563PO</id>
</Disk>

But in case of updates only selected properties will change and only changed properties should be part of marshalled XML. Like 'status' property could change to 'detached', in that case marshalled XML should look as follows-

<Disk>
  <status>detached</status>
</Disk>

Or, in case of 'freeSpace' change XML should look like-

<Disk>
  <freeSpace>20000000<freeSpace>
</Disk>

My question: is defining unchanged fields as null (and hence defining all primitive types as wrapper class variables like Integer, Boolean and so on) the only solution to get the desired result? Or, is there any way in JAXB to specify the selected fields, which should be marshalled in resultant XML and rest of the fields should be ignored.

Please note that set of fields which need to be ignored and which need to be included is not fixed at any point of time.

like image 585
Piyush Behre Avatar asked Nov 03 '22 10:11

Piyush Behre


1 Answers

If You want to have a few views of one class, You should create decorator class for each view. Example source code:

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;

public class Program {

    public static void main(String[] args) throws Exception {
        JAXBContext context = JAXBContext.newInstance(Disk.class,
                OnlyDiskStatusDecorator.class, OnlyDiskFreeSpaceDecorator.class);
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        Disk disk = new Disk();
        disk.setStatus("attached");
        disk.setSize(10000000000L);
        disk.setFreeSpace(25600000L);
        disk.setId("MI45563PO");

        m.marshal(disk, System.out);
        m.marshal(new OnlyDiskStatusDecorator(disk), System.out);
        m.marshal(new OnlyDiskFreeSpaceDecorator(disk), System.out);
    }

}

@XmlRootElement
class Disk {
    private String status;
    private long size;
    private long freeSpace;
    private String id;

    public String getStatus() {
        return status;
    }

    public void setStatus(String status) {
        this.status = status;
    }

    public long getSize() {
        return size;
    }

    public void setSize(long size) {
        this.size = size;
    }

    public long getFreeSpace() {
        return freeSpace;
    }

    public void setFreeSpace(long freeSpace) {
        this.freeSpace = freeSpace;
    }

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    @Override
    public String toString() {
        return "Disk [status=" + status + ", size=" + size + ", freeSpace="
                + freeSpace + ", id=" + id + "]";
    }
}

@XmlRootElement(name = "Disk")
class OnlyDiskStatusDecorator {
    private Disk disk;

    public OnlyDiskStatusDecorator() {
    }

    public OnlyDiskStatusDecorator(Disk disk) {
        this.disk = disk;
    }

    public String getStatus() {
        return disk.getStatus();
    }

    public void setStatus(String status) {
    }
}

@XmlRootElement(name = "Disk")
class OnlyDiskFreeSpaceDecorator {
    private Disk disk;

    public OnlyDiskFreeSpaceDecorator() {
    }

    public OnlyDiskFreeSpaceDecorator(Disk disk) {
        this.disk = disk;
    }

    public long getFreeSpace() {
        return disk.getFreeSpace();
    }

    public void setFreeSpace(long freeSpace) {
    }
}

Above example prints:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<disk>
    <freeSpace>25600000</freeSpace>
    <id>MI45563PO</id>
    <size>10000000000</size>
    <status>attached</status>
</disk>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Disk>
    <status>attached</status>
</Disk>
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Disk>
    <freeSpace>25600000</freeSpace>
</Disk>

I have created two decorators for two views of class. First decorator for status update and second for update freeSpace value. You could also, create implementation of XmlAdapter for specific serialization but I think it is a little more complicated.

like image 116
Michał Ziober Avatar answered Nov 08 '22 09:11

Michał Ziober