True Soft
True Soft

Reputation: 8796

Setting an object value providing only the name of the xml attribute/element

Is it possible to set an attribute/element value to a JAXB object using only the name of that property?

Example:

If I have a class

@XmlRootElement(name = "book")
public class Book {

  @XmlElement(name = "title")
  private String name;
  @XmlElement(name = "author")
  private String author;

  // setters and getters
}

Can I set the name without using its setter(setName()), but only knowing the xml element name? Which in this case is "title". It could look like this:

JAXBContext context = JAXBContext.newInstance(Book.class);
Something s = context.create***();
s.setValueToObject(book, "title", "New name"); // should do the same like book.setName("New name")

Upvotes: 3

Views: 3992

Answers (2)

bdoughan
bdoughan

Reputation: 149007

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

SETTING VALUES BY PROPERTY NAME

You could use the java.lang.reflect APIs to set a value on your object.

package forum13952415;

import java.lang.reflect.Field;
import javax.xml.bind.*;

public class ReflectionDemo {

    public static void main(String[] args) throws Exception {
        Customer customer = new Customer();

        setValueToObject(customer, "firstName", "Jane");
        setValueToObject(customer, "lastName", "Doe");

        JAXBContext jc = JAXBContext.newInstance(Customer.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(customer, System.out);
    }

    private static void setValueToObject(Object object, String property, Object value) throws Exception {
        Class clazz = object.getClass();
        Field field = clazz.getDeclaredField(property);
        field.setAccessible(true);
        field.set(object, value);
    }

}

SETTING VALUES BY XPATH

MOXy offers the ability to get/set values in a domain object by XPath. Below is an example.

Demo

In the example below we need to dig down to the underlying MOXy implementation to get access to the setValueByXPath method.

package forum13952415;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import org.eclipse.persistence.jaxb.JAXBHelper;
import org.eclipse.persistence.oxm.XMLContext;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Customer.class);

        XMLContext xmlContext = JAXBHelper.unwrap(jc, XMLContext.class);

        Customer customer = new Customer();
        xmlContext.setValueByXPath(customer, "@id", null, 123);
        xmlContext.setValueByXPath(customer, "first-name/text()", null, "Jane");
        xmlContext.setValueByXPath(customer, "last-name/text()", null, "Doe");

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(customer, System.out);
    }

}

Output

Below is the output from running the demo code.

<?xml version="1.0" encoding="UTF-8"?>
<customer id="123">
   <first-name>Jane</first-name>
   <last-name>Doe</last-name>
</customer>

Customer

Below is a sample domain model. I've used one where the XML names are different from the Java names.

package forum13952415;

import javax.xml.bind.annotation.*;

@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Customer {

    @XmlAttribute(name="id")
    private int primaryKey;

    @XmlElement(name="first-name")
    private String firstName;

    @XmlElement(name="last-name")
    private String lastName;

}

jaxb.properties

To use MOXy as your JAXB provider you need to add a file called jaxb.properties in the same package as your domain model with the following entry (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html):

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

Upvotes: 1

Festus Tamakloe
Festus Tamakloe

Reputation: 11310

The best way is to provide them over its setters.

if your method

s.setValueToObject(book, "title", "New name"); // should do the same like book.setName("New name")

do the setter work for you. then it's also correct

Upvotes: 0

Related Questions