Какую информацию о пакете я комментирую с помощью XmlJavaTypeAdapters?

Я изучил Блейз Дохан, отвечая на вопрос по этому вопросу, но у вас есть еще один вопрос.

XmlJavaTypeAdapters позволяет вам перечислить кучу аннотаций XmlJavaTypeAdapter, каждый из которых определяет, как не привязываемый тип сопоставляется с привязываемым типом по JAXB.

Вы можете использовать эту аннотацию на уровне пакета. Когда вы это делаете, каждая аннотация XmlJavaTypeAdapter нуждается в полном атрибуте type().

Как представляется, не требуется требование, чтобы пакет, который был аннотирован, имеет какое-либо отношение к пакету адаптируемых типов, не подлежащих связыванию. Это удобно и приятно.

Это, однако, приводит меня к следующему вопросу: если нет никакой связи между аннотированным пакетом и пакетом адаптируемого типа, как JAXB обнаруживает аннотации на уровне пакетов XmlJavaTypeAdapters? Как, другими словами, он знает, какие пакеты проконсультироваться для потенциальных аннотаций XmlJavaTypeAdapters? Могу ли я сделать случайный пакет, скажем, в файле .jar в каталоге .ear file lib, который содержит один, ginormous package-info класс, который аннотируется со всеми адаптерами для всех моих не связанных между собой типов

Ответ 1

Когда среда выполнения JAXB загружает класс, аннотированный JAXB, он ищет package-info.java в том же пакете, что и этот класс, и проверяет, что искать аннотации на уровне пакета. Поэтому, пока XmlJavaTypeAdapters не должен находиться в том же пакете, что и типы "не привязываемые", он должен находиться в том же пакете, что и типы "bindable".

Например, скажем, у меня есть JAXB-аннотированный класс A, в пакете X, который имеет свойство типа B в пакете Y. Чтобы связать свойство B, скажем, требуется адаптер типа. Этот адаптер можно указать непосредственно в A или он может быть указан в package-info.java в пакете X. Пакет Y в значительной степени произволен и не представляет интереса для среды выполнения JAXB.

Надеюсь, это имеет смысл.

Ответ 2

Там, как представляется, не требуется, чтобы пакет, который будучи аннотированными, имеют какое-либо отношение к пакету не привязываемые типы. Это удобно и приятно.

Это правильно. Когда @XmlJavaTypeAdapter используется на уровне пакета, это означает, что этот адаптер применяется ко всем свойствам указанного типа для классов, которые находятся в этом пакете. Ниже я приведу пример.

forum8735737.bar.package-инфо

В этом пакете мы укажем XmlAdapter, который будет применяться ко всем полям/свойствам типа String внутри этого пакета.

@XmlJavaTypeAdapters({
    @XmlJavaTypeAdapter(value=StringAdapter.class, type=String.class)
})
package forum8735737.bar;

import javax.xml.bind.annotation.adapters.*; 

forum8735737.bar.StringAdapter

Наш XmlAdapter будет просто преобразовывать все экземпляры String в верхний регистр при сортировке:

package forum8735737.bar;

import javax.xml.bind.annotation.adapters.XmlAdapter;

public class StringAdapter extends XmlAdapter<String, String> {

    @Override
    public String unmarshal(String v) throws Exception {
        return v;
    }

    @Override
    public String marshal(String v) throws Exception {
        if(null == v) {
            return v;
        }
        return v.toUpperCase();
    }

}

forum8735737.bar.Bar

Bar представляет POJO в этом пакете с свойством типа String:

package forum8735737.bar;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Bar {

    private String name;

    public String getName() {
        return name;
    }

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

}

forum8735737.foo.Foo

Foo представляет объект домена с свойством типа String, который существует в другом пакете. XmlAdapter, зарегистрированный для пакета forum8735737.bar, не будет применяться к этому классу:

package forum8735737.foo;

import javax.xml.bind.annotation.XmlRootElement;

@XmlRootElement
public class Foo {

    private String name;

    public String getName() {
        return name;
    }

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

}

Demo

В следующем коде создаются экземпляры как Foo, так и Bar и помещаются в XML:

package forum8735737;

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

import forum8735737.bar.Bar;
import forum8735737.foo.Foo;

public class Demo {

    public static void main(String[] args) throws Exception {
        JAXBContext jc = JAXBContext.newInstance(Foo.class, Bar.class);
        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

        Foo foo = new Foo();
        foo.setName("Foo");
        marshaller.marshal(foo, System.out);

        Bar bar = new Bar();
        bar.setName("Bar");
        marshaller.marshal(bar, System.out);
    }

}

Выход

Обратите внимание, что значение элемента name внутри Bar было преобразовано в верхний регистр:

<?xml version="1.0" encoding="UTF-8"?>
<foo>
   <name>Foo</name>
</foo>
<?xml version="1.0" encoding="UTF-8"?>
<bar>
   <name>BAR</name>
</bar>