JAXB ValidationEventHandler метод handleEvent не вызывается - PullRequest
7 голосов
/ 17 мая 2019

Я пытаюсь захватить ValidationEvent с символами, которые не разрешены в правилах XML. (например, "&") Кроме того, я настроил ValidationEventHandler для проверки на немаршальные ошибки. Я пытался отменить маршализацию с помощью InputStream, но обработчик событий не улавливает ошибку. Метод handleEvent вообще не выполняется. С другой стороны, использование StringReader будет работать нормально.

Я уже читал Javadoc, описывающий метод unmarshal. Тем не менее, я не видел, что он не может захватить событие ValidationEvent.

Разархивировать XML-данные из указанного InputStream и вернуть полученное дерево контента. При использовании этой формы немаршального API информация о местоположении события проверки может быть неполной.

С последней попытки я попытался выполнить поиск в Интернете, но ничего не смог найти.
Любая помощь будет оценена: D

Дополнительный вопрос:

Извините, что добавил вопрос. (Класс POJO немного изменился ...) Я определил поле класса POJO с пометкой @XmlPath не так, как имя элемента XML , но, похоже, оно не работает. Должен ли я использовать его как XmlElement?


POJO класс:

import org.eclipse.persistence.oxm.annotations.XmlPath;

import javax.xml.bind.annotation.XmlAttribute;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
import java.util.List;

@XmlRootElement
class Article {
    private String title;
    private String category;
    private List<ArticleImage> imageList;

    public String getTitle() {
        return title;
    }

    @XmlElement
    public void setTitle(String title) {
        this.title = title;
    }

    public String getCategory() {
        return category;
    }

    @XmlElement
    public void setCategory(String category) {
        this.category = category;
    }

    public List<ArticleImage> getImageList() {
        return imageList;
    }

    // for Extra Question... :D
    @XmlPath("image")
    public void setImageList(List<ArticleImage> imageList) {
        this.imageList = imageList;
    }
}

class ArticleImage {
    private String url;
    private String ext;

    public String getUrl() {
        return url;
    }

    @XmlAttribute
    public void setUrl(String url) {
        this.url = url;
    }

    public String getExt() {
        return ext;
    }

    @XmlAttribute
    public void setExt(String ext) {
        this.ext = ext;
    }
}


ValidationEventHandler:

import javax.xml.bind.ValidationEvent;
import javax.xml.bind.ValidationEventHandler;
import javax.xml.bind.ValidationEventLocator;

class CustomValidationHandler implements ValidationEventHandler {

    // This method is not reached when debugging.
    @Override
    public boolean handleEvent(ValidationEvent event) {
        if (event.getSeverity() == ValidationEvent.FATAL_ERROR ||
                event.getSeverity() == ValidationEvent.ERROR) {
            ValidationEventLocator locator = event.getLocator();
            throw new RuntimeException("Error in EventHandler. line number: " + locator.getLineNumber());
        }
        return true;
    }
}


Unmarshal код:

import org.eclipse.persistence.jaxb.JAXBContextFactory;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Unmarshaller;
import java.io.ByteArrayInputStream;
import java.io.InputStream;

public class SomeTest {

    public void someMethod() {
        String xmlString = "<article type=\"item\">\n"
                + "    <title>M&A</title>\n"
                + "    <category>1234-1234</category>\n"
                + "    <image url=\"hello\" ext=\"jpg\"/>\n"
                + "</article>";

        try (InputStream fileInputStream = new ByteArrayInputStream(xmlString.getBytes())) {
            JAXBContext context = JAXBContextFactory.createContext(new Class[]{Article.class}, null);
            Unmarshaller unmarshaller = context.createUnmarshaller();
            unmarshaller.setEventHandler(new CustomValidationHandler());
            Article article = (Article) unmarshaller.unmarshal(fileInputStream);

            System.out.println(article.getTitle());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        new SomeTest().someMethod();
    }
}

Ответы [ 3 ]

9 голосов
/ 21 мая 2019

Изначально предлагалось заменить

JAXBContext context = JAXBContextFactory.createContext(new Class[]{Article.class}, null);

до

JAXBContext context = JAXBContext.newInstance(Article.class);

В реализации JAXBContextFactory.createContext вы можете видеть, что classesToBeBound, который в вашем случае вы передаете Article, выполняет некоторые проверки, которые приводят к исключению «Невозможно найти реализацию JAXB для делегирования». Это проблема, с которой я столкнулся при запуске вашего кода, и я предположил, что у вас тоже. Затем был вызван ваш обработчик событий (по крайней мере, в моей настройке).

Позже у вас возникли проблемы с "... У класса есть два свойства с одним и тем же именем" value "...", и я предложил проверить эту ссылку, которая объясняет причину этого.

ссылка: В чем разница между использованием @XmlElement перед полем и перед объявлением получателя?

Изменить, чтобы ответить на новый вопрос:

Если вы не возражаете, я спрашиваю, что вы пытаетесь сделать с @XmlPath("image")?

Ваша структура POJO не соответствует xml. Удалите аннотацию и измените метод установки для изображения, как показано ниже:

@XmlRootElement
class Article {
    private String title;
    private String category;
    private List<ArticleImage> imageList;

    public String getTitle() {
        return title;
    }

    @XmlElement
    public void setTitle(String title) {
        this.title = title;
    }

    public String getCategory() {
        return category;
    }

    @XmlElement
    public void setCategory(String category) {
        this.category = category;
    }

    public List<ArticleImage> getImage() {
        return imageList;
    }

    // for Extra Question... :D
    // method name changed!
    public void setImage(List<ArticleImage> imageList) {
        this.imageList = imageList;
    }
}

class ArticleImage {
    private String url;
    private String ext;

    public String getUrl() {
        return url;
    }

    @XmlAttribute
    public void setUrl(String url) {
        this.url = url;
    }

    public String getExt() {
        return ext;
    }

    @XmlAttribute
    public void setExt(String ext) {
        this.ext = ext;
    }
}
1 голос
/ 21 мая 2019

работает в обоих случаях: InputStream и StringReader

только что изменилось:

JAXBContext context = JAXBContext.newInstance(Article.class);
0 голосов
/ 21 мая 2019

Как сообщили @mart и @ Sergey

Обновить контекст JAXBContext = JAXBContextFactory.createContext (new Class [] {Article.class}, null);

   JAXBContext context = JAXBContext.newInstance(Article.class);

И также добавьте @ XmlAccessorType (XmlAccessType.FIELD) в ваш класс статьи pojo.

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Article {
    @XmlElement
    private String title;
    @XmlElement
    private String category;

//setter getters

}

Я проверил это, в случае исключения,CustomValidationHandler вызывается.

...