Дубликат тега принят JAXB - PullRequest
       61

Дубликат тега принят JAXB

0 голосов
/ 22 апреля 2020

В нашем приложении пользователь отправляет XML, как показано ниже:

<Decl>
  <MessageHeader>
     <A>Info</A>
     <B>Info2</B>
  </MessageHeader>
</Decl>

и, используя JABX unmarshller, мы заполняем объект java. Но проблема в том, что клиент просит сгенерировать ошибку, когда он отправляет сообщение, как показано ниже:

<Decl>
  <MessageHeader>
     <A>Info</A>
     <B>Info2</B>
  </MessageHeader>
<MessageHeader>
     <A>Info3</A>
     <B>Info4</B>
  </MessageHeader>
</Decl>

JAXB успешно разбирает xml и заполняет объект вторым объектом MessageHeader. Обратите внимание, что MessageHeader не является типом списка. Есть ли способ, чтобы остановить JAXB вести себя так, и это должно вызвать ParsingException. Мы не можем использовать проверку схемы xml перед анализом по какой-то причине. Но есть ли способ, которым мы можем дать команду анализатору JAXB проверить тип цели в списке или нет и выдать ошибку.

Заранее большое спасибо.

Ответы [ 2 ]

0 голосов
/ 23 апреля 2020

Как уже указывалось, путь к go заключается в использовании проверки схемы. Создайте схему и установите maxOccurs = "1" в MessageHeader. Вы можете установить схему с помощью:

unmarshaller.setSchema(schema);

Если по какой-то странной причине вы абсолютно не можете использовать проверку схемы, вы можете сделать уродливый хак, чтобы вызвать исключение, когда дублирующийся MessageHeader обрабатывается с реализацией Unmarshaller.Listener

unmarshaller.setListener(new Unmarshaller.Listener() {

    boolean messageHeaderAlreadyPresent = false;

    @Override
    public void beforeUnmarshal(Object target, Object parent) {
        // When <Decl> is encountered, set to false
        if (target instanceof Decl) {
            messageHeaderAlreadyPresent = false;
        } else if (target instanceof MessageHeader) {
            if (messageHeaderAlreadyPresent) {
                throw new RuntimeException("duplicate MessageHeader");
            }
            messageHeaderAlreadyPresent = true;
        }
    }
});

Хотя это должно сработать, я настаиваю на том, чтобы вы пересмотрели проверку схемы.

Также обратите внимание, что unmarshaller молча игнорирует некоторые события, например, когда сталкивается с элементом en, который не отображается. Это не ваш случай, потому что в вашем случае использования нет проблем с отображением, но, например, если вы получили сообщение:

<Decl>
  <MessageHeader>
     <A>Info1</A>
     <C>Info3</C>
  </MessageHeader>
</Decl>

с элементом <C> вместо <B>, вы бы в итоге со значениями A = Info1 и B = null, поскольку JAXB будет молча игнорировать элемент <C>.

. Вы можете захватить эти события и сгенерировать исключение, установив ValidationEventHandler для возврата false

unmarshaller.setEventHandler(new ValidationEventHandler() {
    @Override
    public boolean handleEvent(ValidationEvent event) {
        // log event ....
        return false;
    }
});
0 голосов
/ 23 апреля 2020

JAXB - это технология для генерации Java классов для XML модели схемы. Поэтому любая проверка, которую выполняет JAXB, будет использовать XML Проверка схемы.

Есть ли способ остановить JAXB, чтобы он вел себя так, и это должно вызвать ParsingException

Нет. Нет, если вы не включили проверку схемы в своем демаршалере JAXB.

Мы не можем использовать проверку схемы xml перед анализом по какой-то причине.

Вы должны либо предоставить причина или не упоминать об этом. Это очень странное правило, учитывая, что JAXB является технологией XML Schema и Java имеет встроенную поддержку проверки XSD.

Обратите внимание, что MessageHeader не является типом списка.

Тип списка предназначен для простых типов. MessageHeader основан на сложном типе.

Я рекомендую игнорировать правило, которое гласит «нет проверки схемы». Установите maxOccurs = 1 в MessageHeader и включите проверку схемы на демаршаллере JAXB.

...