当前位置: 首页 > 知识库问答 >
问题:

JAXB ValidationEventHandler的句柄事件方法未被调用

齐向笛
2023-03-14

我试图捕获一个ValidationEvent,其中包含XML规则中不允许使用的字符。(例如,”

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

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

在最后一次尝试中,我尝试在网上搜索,但什么也找不到<任何帮助都将不胜感激:D

我很抱歉补充一个问题。(POJO类有点变化…)我用@XmlPath注释定义了POJO类字段,与XML元素名不同,但它似乎不起作用。我应该将其用作XmlElement吗?

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;
    }
}


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

郝修为
2023-03-14

它适用于两种情况:InputStream和StringReader

只是改变了这一点:

JAXBContext context = JAXBContext.newInstance(Article.class);
宓跃
2023-03-14

正如@Mart和@Sergey所说

更新JAXBContext context=JAXBContextFactory。createContext(新类[]{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。

裴和怡
2023-03-14

最初建议替换

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

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

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

后来您遇到了“…类有两个同名属性”value“…的问题我建议检查这个链接,这解释了它发生的原因。

链接是:在字段之前使用@XmlElement和在getter声明之前使用@XmlElement有什么区别?

编辑以答复新问题:

如果你不介意我问你想用@XmlPath(“image”)做什么?

您的POJO结构与xml不匹配。删除注释并更改图像的setter方法,如下所示:

@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;
    }
}
 类似资料:
  • 我正在使用JSF 2.0创建页面: 我期待在单击复选框时被调用。但是,加载页面时调用一次setMyCheckboxValue()。 如果我写 每次点击都会收到警报。 我的问题是:当我收到警报时,为什么每次onclick事件都不调用? 注意:我也尝试过AJAX,但复选框保持不变。

  • 我有以下2个组件,它们应该首先从Mongo中删除文档,然后从Elastic中删除。 主要流程: 服务: 不幸的是,deleteDocumentInMongo从未被调用。我可以在日志中看到bean已正确注册。 我是做错了什么,还是你需要更多的调试信息?如果我窃听手柄,则deleteDocumentInES。执行输入,但忽略mongo流。

  • 在laravel认证中间件使用我的自定义保护用户,但每次我调用路由与该中间件我得到的错误: 未定义路由[登录]。 现在,我只是想确保中间件被调用。这就是我到目前为止所做的: 上面是身份验证的句柄方法。php。这是我的守卫密码 路由:这是路由组,其中我有一个子组来实现auth中间件

  • 问题内容: 我想使用posix_spawn(…)(或非常相似的东西)生成一个进程集合。此函数接受posix_spawn_file_actions_t类型的参数,该参数允许我指定应如何对待打开的文件句柄。从文档中可以确定,所有文件都是从调用进程继承的,并根据posix_spawn_file_actions_t结构中的信息进行了修改。 我希望所有文件都不会被生成的进程打开(stdin,stdout和s

  • 我希望能够读取我的滑块值,因此我为我的控制器类使用事件侦听器: 我尝试了每一个MouseDragEvent,但没有一个MouseDragEvent被实际调用(比如在拖动时检测到的,在我开始拖动滑块时应该被调用)。我找到了这篇文章,但它并没有解决我的问题。JavaFX鼠标拖动事件未触发

  • 如何使用方法句柄调用私有方法? 据我所知,只有两种可公开访问的实例: 方法andles.lookup 两者都不允许不受限制的私人访问。 还有非公开的这就是我想要的。是否有某种公开的方式获得它(假设SecurityManager允许)?