Статьи

JAXB делает это неправильно;

JAXB — это 10-летняя технология Java, которая позволяет нам преобразовывать объект Java в документ XML (маршалинг) и обратно (демаршаллинг). Эта технология основана на методах установки и получения и, на мой взгляд, нарушает ключевые принципы объектно-ориентированного программирования, превращая объекты в пассивные структуры данных . Я бы порекомендовал вам вместо этого использовать Xembly для маршалинга объектов Java в документы XML.

Так работает JAXB. Скажем, у вас есть класс Book который необходимо преобразовать в документ XML. Вы должны создать геттеры и аннотировать их:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
public class Book {
  private final String isbn;
  private final String title;
  public Book(final String isbn, final String title) {
    this.isbn = isbn;
    this.title = title;
  }
  @XmlElement
  public String getIsbn() {
    return this.isbn;
  }
  @XmlElement
  public String getTitle() {
    return this.title;
  }
}

Затем вы создаете маршаллер и просите его преобразовать экземпляр класса Book в XML:

1
2
3
4
final Book book = new Book("0132350882", "Clean Code");
final JAXBContext context = JAXBContext.newInstance(Book.class);
final Marshaller marshaller = jaxbContext.createMarshaller();
marshaller.marshal(book, System.out);

Вы должны ожидать что-то вроде этого в выводе:

1
2
3
4
5
<?xml version="1.0"?>
<book>
  <isbn>0132350882</isbn>
  <title>Clean Code</title>
</book>

Так что с этим не так? Практически то же самое, что не так с объектно-реляционным отображением, которое объясняется в ORM Is Offensive Anti-Pattern . JAXB рассматривает объект как пакет данных, извлекает данные и преобразует их в XML так, как хочет JAXB. Объект не контролирует этот процесс. Поэтому объект больше не является объектом , а скорее пассивным пакетом данных.

Идеальным подходом было бы изменить дизайн нашего класса Book следующим образом:

01
02
03
04
05
06
07
08
09
10
11
public class Book {
  private final String isbn;
  private final String title;
  public Book(final String isbn, final String title) {
    this.isbn = isbn;
    this.title = title;
  }
  public String toXML() {
    // create XML document and return
  }
}

Однако есть несколько проблем с этим подходом. Прежде всего, существует массовое дублирование кода. Создание документа XML — довольно многословный процесс в Java. Если бы каждый класс должен был повторно реализовать его в своем toXML() , у нас была бы большая проблема с дублирующимся кодом.

Вторая проблема заключается в том, что мы не знаем точно, в какой тип упаковки должен быть доставлен наш XML-документ. Это может быть String или InputStream или, может быть, экземпляр org.w3c.dom.Document . Создание многих toXML() в каждом объекте определенно было бы катастрофой.

Xembly предоставляет решение. Как я упоминал ранее , это обязательный язык для XML-конструкций и манипуляций. Вот как мы можем реализовать наш объект Book с помощью Xembly:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
import org.xembly.Directive;
public class Book {
  private final String isbn;
  private final String title;
  public Book(final String isbn, final String title) {
    this.isbn = isbn;
    this.title = title;
  }
  public Iterable<Directive> toXembly() {
    return new Directives()
      .add("book")
      .add("isbn").set(this.isbn).up()
      .add("title").set(this.title).up()
      .up();
  }
}

Теперь, чтобы построить XML-документ, мы должны использовать этот код вне объекта:

1
2
final Book book = new Book("0132350882", "Clean Code");
final String xml = new Xembler(book.toXembly()).xml();

Этот класс Xembler преобразует директивы Xembly в документ XML.

Прелесть этого решения в том, что внутренние объекты объекта не открываются через геттеры, а объект полностью отвечает за процесс маршалинга XML. Кроме того, сложность этих директив может быть очень высокой — намного выше, чем довольно громоздкие аннотации JAXB.

  • Xembly — это проект с открытым исходным кодом, поэтому не стесняйтесь отправлять свои вопросы или исправления в Github .
Ссылка: JAXB делает это неправильно; Попробуйте Xembly от нашего партнера JCG Егора Бугаенко в блоге About Programming .