Как уже указывалось, путь к 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;
}
});