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

JAXB RI ClassFactory中出现空指针异常

易扬
2023-03-14

我和我的朋友正在开发一个JavaFX应用程序,它充当我们学校的规划器。我们有任务(课堂作业)、事件、课程和学生信息。为了将数据持久地存储在用户的硬盘上,我们使用了JAXB。

我们已经注释了我们的类,并且可以成功地在包装器中整理任务类。问题是解组tasks.xml文件。

@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);
    }
}
    //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;
        }

}
/**
     * 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"));
    }
/**
     * 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));
    }
/**
     * 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 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)
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);

>

  • 混淆名称和注释。命名似乎不是问题所在。
  • 确定文件位置以确保其正确。
  • 确定jaxbcontext知道的类。它同时识别TaskTaskListWrapper类。
  • sysoutingum.toString()。它在内存中显示了一个有效地址,因此um对象本身不是引发nullpointer异常的对象。
  • TaskListWrapper.java的位置更改为与Task.java相同的包。
  • 尝试通过将XML文件更改为只有一个 来取消封送单个任务,因为更改时根元素工作

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

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

    >

  • http://examples.javacodeGeeks.com/core-java/xml/bind/jaxb-unmarshal-example/
  • 大量stackoverflow问题,这些问题与@XmlAttribute注释的bug有关。因为我们不使用那些与bug无关的
  • Learning Java:第四版作者:Patrick Niemeyer和Daniel Leuck。我们复制了他们设置解组器的精确方法。他们有一个简单的方法:

    JAXBContext context = JAXBContext.newInstance(Inventory.class);
    Unmarshaller unmarshaller = context.createUnmarshaller();
    Inventory inventory = (Inventory) unmarshaller.unmarshall(
        new File("zooinventory.xml") );
    
  • 共有1个答案

    蒋俊
    2023-03-14

    JAXB与FXCollections不兼容,比如包装器中的ObservableList。您必须编写一个XmlAdapter来将其解缠成一个普通列表。因此封送处理将起作用,但解封处理不起作用,正如您可以在StackTrace的行中看到的:

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

    相应的适配器如下所示:

    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;
      }
    }
    
    //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;
            }
    
    }
    
    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(XMLAccessStype.public_Member),其中JavaDoc表示:

    每个公共getter/setter对和每个公共字段都将自动绑定到XML,除非通过XMLTransient进行注释。

    因此,在FX类(特别是一个模型)中,您尝试将使用的属性隐藏在私有字段中。但是如果您需要一个不应该封送的公共字段怎么办?那么我建议执行@XmlAccessorType(XmlAccessStype.Property)注释。它的JavaDoc说:

    注意一个词public的差别很小,因此如果用@XmlAccessorType(XmlAccessStype.Property)注释,甚至私有getter/setter也会被考虑在内。

    但我认为大多数人使用@XMLAccessorType(XMLAccessStype.field),JavaDoc会说:

    JAXB绑定类中的每个非静态、非瞬态字段都将自动绑定到XML,除非使用XMLTransient进行注释。

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

     类似资料:
    • 以下是在sun.reflect.nativeMethodAccessorImpl.Invoke0(本机方法)在sun.reflect.nativeMethodAccessorImpl.Invoke(未知源)在sun.reflect.NativeMethodAccessorImpl.Invoke(未知源)在java.lang.Reflect.Method.Invoke(未知源)在com.codena

    • 问题内容: 我正在android中做一个应用程序,因此我需要访问com.android.internal.telephony API。现在,我可以访问这些API了,但问题是,无论我在自己的类中调用Class Call.java方法的什么地方,都会抛出。您可以在http://hi- android.info/src/com/android/internal/telephony/Call.java.h

    • 我正在创建一个包含教授字段的表单,这个字段是id(长)、nome(字符串)、username(字符串)、email(字符串)和curso_coord(curso),因为curso是一个类课程的引用变量。 我尝试了curso.get(0).getid()来解决这个问题,但这是不够的 2019-10-04 15:37:00.700错误17580---[nio-8081-exec-1]C.P.P.Con

    • 我正在尝试使用selenium webdriver、testng和page Factory实现自动化。但我面临空指针异常。

    • > 单击 受保护得空onPrepareDialog(int id,Dialog Dialog) 受保护的对话框onCreateDialog(int id) 如果我对timepickerdialog代码做了什么错误,请告诉我。

    • 问题内容: 此代码导致空指针异常。我不知道为什么: 我已经在调试器中检查了它,所有局部变量都不为空。怎么会这样呢?BiMap来自Google Collections。 问题答案: 空指针异常是将的结果拆箱的结果。如果不包含键,则返回“ of type” 。假设分配是给引用的,Java将值拆箱到中,导致空指针异常。 您应该检查或用作局部变量类型,以免取消装箱并采取相应措施。适当的机制取决于您的上下文