未调用JAXB ValidationEventHandler的handleEvent方法

时间:2019-05-17 17:46:58

标签: java java-8 jaxb inputstream unmarshalling

我正在尝试使用XML规则中不允许的字符捕获ValidationEvent。 (例如,“&”) 另外,我设置了ValidationEventHandler来检查非编组错误。 我尝试使用InputStream进行解组,但是事件处理程序无法捕获错误。 handleEvent方法根本没有执行。另一方面,使用StringReader可以正常使用。

我已经阅读了描述unmarshal方法的Javadoc。但是,我没有看到它无法捕获ValidationEvent。

  

从指定的InputStream解组XML数据,并返回结果内容树。使用这种形式的解组API时,验证事件位置信息可能不完整。

在最后一次尝试中,我确实尝试过在线搜索,但找不到任何东西。
任何帮助将不胜感激:D

其他问题:

很抱歉添加一个问题。 (POJO类已经改变了一点……) 我用与XML元素名称不同的@XmlPath注释定义了 POJO类字段,但似乎不起作用。我应该将其用作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;
    }
}


解组码:

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 个答案:

答案 0 :(得分:9)

最初建议替换

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

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

在JAXBContextFactory.createContext的实现中,您可以看到对您通过了Article的classesToBeBound进行了一些检查,这些检查导致“无法找到要委托的JAXB实现”的异常。这是我在运行代码时遇到的问题,我认为您也有。然后调用了事件处理程序(至少在我的设置中如此)。

稍后您遇到“ ...类的问题,该类具有两个相同名称的“ value” ...”属性,我建议检查此链接,以解释发生这种情况的原因。

链接为:What is the difference between using @XmlElement before field and before getter declaration?

编辑以回答新问题:

如果您不介意我问您要如何使用@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 :(得分:1)

在两种情况下均有效: InputStream StringReader

只是更改为:

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

答案 2 :(得分:0)

如@mart和@Sergey所述

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

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

还添加 @XmlAccessorType(XmlAccessType.FIELD)在您的Article 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。