49

I have 2 classes:

@XmlRootElement
public class A {

    private Long id;
    private B b;

    // setters and getters
}

and

@XmlRootElement
public class B {

    private Long id;
    private String field1;
    private String field2;

    // setters and getters
}

By default, if I transform an instance of class A to the XML, I will have all its fields (id) and the referenced B class fields (id, field1, field2) like this:

<a>
    <id>2</id>
    <b>
        <id>5</id>
        <field1>test1</field1>
        <field2>test3</field2>
    </b>
</a>

Is is possible to modify what fields from referenced class B are included in the XML of the A class? E.g. I want to say that when I transform an instance of A class, I just want to get id from the B class (no field1 and field2 fields), so I want to get:

<a>
    <id>2</id>
    <b>
        <id>5</id>
    </b>
</a>

I don't want to permanently annotate the B class (using @XMLTransient or @XMLElement) to achieve it, as there are cases in which I want to export whole B class as is (with id, field1 and field2.)
I just don't want to export all these fields when the B class is referenced from A.

Is this even possible with JAX-B?

Tunaki
  • 132,869
  • 46
  • 340
  • 423
Piotr Nowicki
  • 17,914
  • 8
  • 63
  • 82

3 Answers3

108

You can use annotation @XmlTransient to ignore fields. Put this annotation on field itself or its getter.

GETah
  • 20,922
  • 7
  • 61
  • 103
AlexR
  • 114,158
  • 16
  • 130
  • 208
  • Where should I put it? On the `B` class `field1` and `field2` fields? Wouldn't it cause to remove the `field1` and `field2` from occurring when transforming **an instance of `B` class**? – Piotr Nowicki Jun 10 '12 at 12:11
  • You should put these annotations on fields or methods of class B. Fields of will not be removed. They just will not appear in resulting XML – AlexR Jun 10 '12 at 14:23
  • 1
    Thanks Alex, but I think it's exactly the thing I don't want to do (please refer to the last paragraph of my question). This change will forbid the fields from appearing in resulting XML in **all occurrences** of B class. – Piotr Nowicki Jun 10 '12 at 15:32
34

You can use @XmlTransient on the field. Also the default JAXB bindings can be overridden at a global scope or on a case-by-case basis as needed by using custom binding declarations.

Check out the Guide to JAXB from Baeldung website for more examples.

Eduardo Sanchez-Ros
  • 1,777
  • 2
  • 18
  • 30
  • Thanks! I guess it complicates things a bit if I'm using Glassfish JAXB implementation... It seems that there is no annotation-based solution and I need to create an additional customization XML? – Piotr Nowicki Jun 10 '12 at 16:54
13

Ok, I've come up with some hacky solution:

@XmlRootElement
public class A {

    private Long id;
    private B b;

    // setters and getters
}

I've provided an additional getter just for the REST use case, so it's like:

@XMLTransient
public B getB() {
    return b;
}

@XMLElement(name="b")
public Long getBForREST() {
    return b.getId();
}

It results in the following structure:

<a>
    <id>2</id>
    <b>5</b>
</a>

It's not exactly same structure I aimed for it works for me.

I don't like this solution - an @XMLExclude({"field1", "field2"}) or something like that would be much cleaner in my opinion.

Nevertheless - for now on, it works; it's ugly, but it works.

Piotr Nowicki
  • 17,914
  • 8
  • 63
  • 82