草庐IT

java - JAXB RI ClassFactory 中的空指针异常

coder 2024-03-13 原文

介绍

我和我的 friend 正在开发一个 JavaFX 应用程序,它充当我们学校的规划师。我们有任务(类作业)、 Activity 、类(class)和学生信息。为了尝试将数据持久存储在用户的硬盘上,我们使用 JAXB。

我们已经注释了我们的类,并且可以在包装器中成功编码 Task 类。问题是从 tasks.xml 解码文件。

以下是相关的代码行:

任务.java

@XmlRootElement
public class Task {
    //constructors

    //complete constructor
    public Task(String className, String assignment, String description, LocalDate dueDate) {
        this.className = new SimpleStringProperty(className);
        this.assignment = new SimpleStringProperty(assignment);
        this.description = new SimpleStringProperty(description);

        this.dueDate = new SimpleObjectProperty<LocalDate>(dueDate);
    }

    /**
     * Sets a model data into the task, sets the 
     * due date to be tomorrow.
     */
    public Task() {
        this("", "", "", LocalDate.now().plusDays(1));

        setClassName("English");
        setAssignment("Read");
        setDescription("1984");

        //setDueDate(LocalDate.now());
    }
    //Instance variables

    private final SimpleStringProperty className;
    private final SimpleStringProperty assignment;
    private final SimpleStringProperty description;

    private final ObjectProperty<LocalDate> dueDate;

//  //Getters and setters

    //... Other getters and setters

    @XmlJavaTypeAdapter(LocalDateAdapter.class)
    public final java.time.LocalDate getDueDate() {
        return this.dueDateProperty().get();
    }
    public final void setDueDate(final java.time.LocalDate dueDate) {
        this.dueDateProperty().set(dueDate);
    }
}

TaskListWrapper.java:

    //used in saving the objects to XML

@XmlRootElement(name="tasks")
public class TaskListWrapper {

        private ObservableList<Task> task;

        @XmlElement(name="task")
        public ObservableList<Task> getTasks() {
            return task;
        }

        public void setTasks(ObservableList<Task> tasks) {
            this.task = tasks;
        }

}

AppData.java 中的方法

它处理文件的保存和解码。

/**
     * Save to XML using JAXB
     * @throws JAXBException 
     * @throws FileNotFoundException 
     */
    public static void save() throws JAXBException, FileNotFoundException {

        //saving other objects
        //...

        TaskListWrapper tl = new TaskListWrapper();

        //MasterTaskList is the entire list of tasks written to memory
        tl.setTasks(AppData.getMasterTaskList());

        saveObject(tl, new File(System.getProperty("user.dir") + "/resources/xml/tasks.xml"));

        saveObject(masterStudentInfo, new File(System.getProperty("user.dir") + "/resources/xml/student_info.xml"));
    }

同一个类中的 saveObject() 方法:

/**
     * Saves a specific Object {@code obj} to an xml file {@code xml} using JAXB.
     * @param obj
     * @param xml
     * @throws FileNotFoundException
     * @throws JAXBException
     */
    private static void saveObject(Object obj, File xml) throws FileNotFoundException, JAXBException {
        //context is used to determine what kind of class is going to be marshalled or unmarshalled
        JAXBContext context = JAXBContext.newInstance(obj.getClass());

        //loads to the XML file
        Marshaller m = context.createMarshaller();
        m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);

        //loads the current list of courses to the courses.xml file
        m.marshal(obj, new FileOutputStream(xml));
    }

App.java 中的 InitFiles()

注意指出空指针异常的注释

/**
     * Initial setup for all the files for the program. Contains all the
     * persistent data for the planner, such as courses, tasks, and events.
     * <p>
     * All data is saved in {@code [place of installment]/resources/xml/...}.
     * @throws IOException
     */
    public void initFiles() throws IOException{

        //... other files for other objects

        File tasks = new File(System.getProperty("user.dir") + "/resources/xml/tasks.xml");

        //check if each file exists, if so unmarshall 
        if(tasks.exists()){
            try {
                JAXBContext context = JAXBContext.newInstance(TaskListWrapper.class);

                //the file location is correct
                System.out.println(tasks.toString());

                //The context knows that both the Task and TaskListWrapper classes exist
                System.out.println(context.toString());

                Unmarshaller um = context.createUnmarshaller();

                //TODO: null pointer exception
                TaskListWrapper taskList = (TaskListWrapper) um.unmarshal(tasks);
                //System.out.println(umObject.getClass());
            } catch (JAXBException e) {
                e.printStackTrace();
            }

        } else {
            tasks.createNewFile();
        }
        //... other checks for files
    }

来自编码的格式良好的 XML 文档:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<tasks>
    <task>
        <assignment>Book</assignment>
        <className>Math</className>
        <description>problems</description>
        <dueDate>2015-01-17</dueDate>
    </task>
    <task>
        <assignment>Textbook</assignment>
        <className>Religion</className>
        <description>problems</description>
        <dueDate>2015-01-17</dueDate>
    </task>
    <task>
        <assignment>Read</assignment>
        <className>English</className>
        <description>1984</description>
        <dueDate>2015-03-05</dueDate>
    </task>
</tasks>

异常:

 java.lang.NullPointerException
    at com.sun.xml.internal.bind.v2.ClassFactory.create0(Unknown Source)
    at com.sun.xml.internal.bind.v2.ClassFactory.create(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.startPacking(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.startPacking(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.Scope.add(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.property.ArrayERProperty$ReceiverImpl.receive(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallingContext.endElement(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.SAXConnector.endElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.endElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanEndElement(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl$FragmentContentDriver.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl.next(Unknown Source)
    at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.parsers.AbstractSAXParser.parse(Unknown Source)
    at com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser.parse(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal0(Unknown Source)
    at com.sun.xml.internal.bind.v2.runtime.unmarshaller.UnmarshallerImpl.unmarshal(Unknown Source)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    at javax.xml.bind.helpers.AbstractUnmarshallerImpl.unmarshal(Unknown Source)
    at org.sjcadets.planner.App.initFiles(App.java:136)
    at org.sjcadets.planner.App.start(App.java:68)
    at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$153(Unknown Source)
    at com.sun.javafx.application.LauncherImpl$$Lambda$51/1390460753.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$166(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$$Lambda$45/1051754451.run(Unknown Source)
    at com.sun.javafx.application.PlatformImpl.lambda$null$164(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$$Lambda$47/231444107.run(Unknown Source)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.application.PlatformImpl.lambda$runLater$165(Unknown Source)
    at com.sun.javafx.application.PlatformImpl$$Lambda$46/1775282465.run(Unknown Source)
    at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(Unknown Source)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$141(Unknown Source)
    at com.sun.glass.ui.win.WinApplication$$Lambda$37/1109371569.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

空指针在//TODOinitFiles() 中说明方法:

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

                    //the file location is correct
                    System.out.println(tasks.toString());

                    //The context knows that both the Task and TaskListWrapper classes exist
                    System.out.println(context.toString());

                    Unmarshaller um = context.createUnmarshaller();

                    //TODO: null pointer exception
                    TaskListWrapper taskList = (TaskListWrapper) um.unmarshal(tasks);

我们尝试过的事情:

  • 弄乱名称和注释。命名似乎不是问题所在。
  • 检查文件位置以确保它是正确的。
  • Sysouting JAXBContext 的类知道。它同时识别 TaskTaskListWrapper类。
  • 系统调度 um.toString() .它显示内存中的有效地址,因此 um对象本身不是引发空指针异常的原因。
  • 更改 TaskListWrapper.java 的位置到与 Task.java 相同的包裹.
  • 尝试通过将 XML 文件更改为只有一个来解码单个任务 <task>因为根元素在我更改时有效

    TaskListWrapper taskList = (TaskListWrapper) um.unmarshal(tasks);
    

    Task taskList = (Task) um.unmarshal(tasks);
    

我们寻找答案的地方:

  • http://examples.javacodegeeks.com/core-java/xml/bind/jaxb-unmarshal-example/
  • 大量与 @XMLAttribute 的错误有关的 stackoverflow 问题注解。由于我们不使用那些错误不相关的
  • 学习 Java:第 4 版,作者:Patrick Niemeyer 和 Daniel Leuck。我们已经复制了他们设置解码器的确切方法。他们有一个简单的方法:

    JAXBContext context = JAXBContext.newInstance(Inventory.class);
    Unmarshaller unmarshaller = context.createUnmarshaller();
    Inventory inventory = (Inventory) unmarshaller.unmarshall(
        new File("zooinventory.xml") );
    

问题

为什么是TaskListWrapper taskList = (TaskListWrapper) um.unmarshal(tasks);抛出空指针异常?

最佳答案

JAXB 与包装器中的 ObservableList 等 FXCollections 不兼容。您必须编写一个 XmlAdapter 以将其解开为一个普通列表。因此编码将起作用但解码不起作用,正如您在堆栈跟踪行中看到的那样:

at com.sun.xml.internal.bind.v2.runtime.reflect.Lister$CollectionLister.startPacking(Unknown Source)

Lister$CollectionLister 不知道如何处理未知来源。所以 Adpater 应该像这样使用 ListWrapper:

public class TaskList {

  @XmlElement(name = "task")
  List<Task> entries = new ArrayList<>();

  public List<Task> getEntries() {
    return entries;
  }
}

相应的 Adapter 如下所示:

public class TaskListAdapter extends XmlAdapter<TaskList, ObservableList<Task>> {

  @Override
  public ObservableList<Task> unmarshal(TaskList v) throws Exception {
    ObservableList<Task> list = FXCollections.observableArrayList(v.entries);
    return list;
  }

  @Override
  public TaskList marshal(ObservableList<Task> v) throws Exception {
    TaskList taskList = new TaskList();
    v.stream().forEach((item) -> {
      taskList.entries.add(item);
    });
    return taskList;
  }
}

这样您的 TaskListWrapper 最终应该看起来像这样:

//used in saving the objects to XML

@XmlRootElement(name="tasks")
public class TaskListWrapper {

        private ObservableList<Task> task;


        @XmlJavaTypeAdapter(TaskListAdapter.class)
        public ObservableList<Task> getTasks() {
            return task;
        }

        public void setTasks(ObservableList<Task> tasks) {
            this.task = tasks;
        }

}

顺便说一句,您使用了很多 FX 属性,所以也许您最好使用 @XmlAccessorType(XmlAccessType.PROPERTY) 注释您的类任务,并确保每个字段设置一个 getter/setter 存在。正如 FXProperties 约定所说:

private final StringProperty description = new SimpleStringProperty();
public String getDescription() {
  return description.get();
}
public void setDescription(String description) {
  this.description.set(description);
}
public StringProperty descriptionProperty(){
  return description;
}

注解 @XmlAccessType(XmlAccessorType.PROPERTY) 在这里有详细描述:JAXB JavaDoc .如果在包或类上没有任何注释,那么默认值将是 @XmlAccessorType(XmlAccessType.PUBLIC_MEMBER),其中 JavaDoc 说:

Every public getter/setter pair and every public field will be automatically bound to XML, unless annotated by XmlTransient.

因此在 FX 类(特殊模型)中,您尝试将使用的属性隐藏在私有(private)字段中。但是,如果您需要一个不应编码的公共(public)字段怎么办?然后我建议执行 @XmlAccessorType(XmlAccessType.PROPERTY) 注释。它的 JavaDoc 说:

Every getter/setter pair in a JAXB-bound class will be automatically bound to XML, unless annotated by XmlTransient.

注意 public 这个词的细微差别,所以如果用 @XmlAccessorType(XmlAccessType.PROPERTY) 注释,甚至私有(private) getter/setter 也会被考虑在内。

但我认为大多数人使用 @XmlAccessorType(XmlAccessType.FIELD) JavaDoc 说:

Every non static, non transient field in a JAXB-bound class will be automatically bound to XML, unless annotated by XmlTransient.

这在具有 FX 属性的 FX 类中可能有点棘手。我不会向您推荐它。

关于java - JAXB RI ClassFactory 中的空指针异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28929569/

有关java - JAXB RI ClassFactory 中的空指针异常的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  5. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  6. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  7. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  8. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

  9. ruby - rspec 需要 .rspec 文件中的 spec_helper - 2

    我注意到像bundler这样的项目在每个specfile中执行requirespec_helper我还注意到rspec使用选项--require,它允许您在引导rspec时要求一个文件。您还可以将其添加到.rspec文件中,因此只要您运行不带参数的rspec就会添加它。使用上述方法有什么缺点可以解释为什么像bundler这样的项目选择在每个规范文件中都需要spec_helper吗? 最佳答案 我不在Bundler上工作,所以我不能直接谈论他们的做法。并非所有项目都checkin.rspec文件。原因是这个文件,通常按照当前的惯例,只

  10. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

随机推荐