JAXB unmarshalling返回Null [英] JAXB unmarshalling returning Null

查看:74
本文介绍了JAXB unmarshalling返回Null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在制作这个示例GUI,它只是将计算机部件从一侧移动到另一侧,并能够将列表(以xml格式)加载并保存到桌面。除了重新加载已保存的xml文件外,一切正常。我认为它与Save.java中的注释有关。话虽如此,我不确定需要什么或者问题是什么。任何帮助将不胜感激。

I'm making this example GUI that simply moves computer parts from one side to another, with the ability to load and save list (in xml) to the desktop. Everything works fine except for the reloading of saved xml files. I think it has something to do with the annotations in the Save.java. That being said I'm not sure what is needed or if that is the issue. Any help will be appreciated.

Window.java

import java.awt.EventQueue;

import javax.swing.JFrame;
import javax.swing.JPanel;

import java.awt.BorderLayout;

import javax.swing.JButton;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;

import javax.swing.DefaultListModel;
import javax.swing.JMenuBar;
import javax.swing.JMenuItem;
import javax.swing.JMenu;
import javax.swing.ListSelectionModel;

import java.awt.Component;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;

import javax.swing.BoxLayout;
import javax.swing.JList;

import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;

public class Window {

    private JFrame frame;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    Window window = new Window();
                    window.frame.setVisible(true);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    public Window() {
        initialize();
    }

    public void addTo(JPanel displayPanel, Component contentToAdd)
    {
        displayPanel.add(contentToAdd);
    }

    public void initialize() {

        //setting the dimension for the JList panels
        Dimension sidePanelSize = new Dimension(180, 540);

        frame = new JFrame();
        frame.setBounds(100, 100, 480, 540);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        //Creating the menu bar 
        JMenuBar menuBar = new JMenuBar();
        frame.setJMenuBar(menuBar);

        //adding File option to menu bar
        JMenu mnFile = new JMenu("File");
        menuBar.add(mnFile);

        //adding load option to File
        JMenuItem mntmLoad = new JMenuItem("Load");
        mnFile.add(mntmLoad);

        //adding save option to File
        JMenuItem mntmSave = new JMenuItem("Save");
        mnFile.add(mntmSave);

        //adding exit option to File
        JMenuItem mntmExit = new JMenuItem("Exit");
        mnFile.add(mntmExit);

        //creating Jpanel that will hold JList for computer parts 
        //that you can choose 
        final JPanel itemPanel = new JPanel();
        itemPanel.setPreferredSize(sidePanelSize);
        itemPanel.setBackground(Color.WHITE);
        itemPanel.setLayout(new BorderLayout());

        //Create the model that will hold the computer items
        //For loop to add the strings to the model
        DefaultListModel<String> model = new DefaultListModel<>();
        for (String items : new String [] {"Case", "Motherboard", "CPU", "GPU", "PSU", "RAM", "HDD"})
            model.addElement(items);
        //Create JList(itemList) and set its model to the one 
        //holding the computer parts
        final JList<String> itemList = new JList<>(model);

        //Setting attributes for the JList(itemList) - font, Number of elements you can select at a time
        itemList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        itemList.setFont(new Font("SegoeUI", Font.BOLD, 11));
        //adding the JList to the Panel
        itemPanel.add(itemList, BorderLayout.WEST);
        //adding the Panel to the frame
        frame.getContentPane().add(itemPanel, BorderLayout.WEST);

        //creating two panels that are used for centering the JList buttons
        JPanel buttonContainer = new JPanel();
        JPanel buttonList = new JPanel();
        GridBagConstraints c = new GridBagConstraints();

        //setting the layout managers for the panels and 
        //adding color to the background
        buttonList.setLayout(new BoxLayout(buttonList, BoxLayout.Y_AXIS));
        buttonContainer.setLayout(new GridBagLayout());
        buttonContainer.setBackground(new Color(238, 238, 238));

        //adding the button to add content from Jlist on the left(itemList)
        //to the right JList(addToList)
        JButton addButton = new JButton(">>");
        buttonList.add(addButton);

        //adding the button to remove content form the JList(addToList)
        JButton deleteButton = new JButton("<<");
        buttonList.add(deleteButton);

        //setting where to start inputing element into the
        //grid of the ButtonContainer
        c.gridx = 0;
        c.gridy = 0;

        //adding the button panel container and its constraints 
        //to the main container
        //finally adding it all to the main frame
        buttonContainer.add(buttonList, c);
        frame.getContentPane().add(buttonContainer, BorderLayout.CENTER);

        //creating the JList that we will add and remove from
        final JList<String> addToList = new JList<>(new DefaultListModel<String>());

        //creating the panel to hold the JList(addToList)
        //setting its size and layout in the manager
        //finally adding it to the main frame
        final JPanel displayPanel = new JPanel();
        displayPanel.setPreferredSize(sidePanelSize);
        displayPanel.setBackground(Color.WHITE);
        displayPanel.add(addToList, BorderLayout.EAST);
        frame.getContentPane().add(displayPanel, BorderLayout.EAST);    



        //Here is all the action listeners for button click events and menu events
        //contains all the methods for the action events
        final ActionListeners b = new ActionListeners();

        //Listener that adds selected computer parts from left JList(itemList) to the right JList(addToList)
        addButton.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                b.addContent(itemList, addToList);
            }
        });

        //Listener that removes selected computer part from the JList(addToList) 
        deleteButton.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                b.removeContent(addToList);
            }
        });

        //Listener that calls the save methods to save JList(addToList) content into xml
        mntmSave.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                b.saveContent((DefaultListModel<String>) addToList.getModel());
            }
        });

        //Listener that call the load methods to load xml into the JList(addToList)
        mntmLoad.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                b.loadContent(addToList);
            }
        });

        //Exits the program entirely 
        mntmExit.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                b.exitProgram();
            }
        });
    }
}

Load.java

import java.io.File;

import javax.swing.DefaultListModel;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Unmarshaller;


public class Load {
    //loads the file into the JList to be displayed in the program
    public DefaultListModel<String> loadXMLFile() {
        //array that holds the content from the xml file

        //model that will have xml file's content added to it 
        //from the array
        DefaultListModel<String> modelToReturn = new DefaultListModel<>();
        String[] partsList = null;

        try {
            String homeDir = System.getProperty("user.home");
            File file = new File(homeDir + "/Desktop/xml.xml");

            JAXBContext jaxbContext = JAXBContext.newInstance(Save.class);
            Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();

            Save load = (Save) jaxbUnmarshaller.unmarshal(file);
            partsList = new String [load.getPartsList().length];

          } catch (JAXBException e) {
            e.printStackTrace();
          }

        //adds the strings in the arrayToReturn
        //to the model that will be returned
        for(int i = 0; i < partsList.length; i++)
        {
            modelToReturn.addElement(partsList[i]);
        }

        return modelToReturn;
    }
}

ActionListeners.java

import java.io.File;
import java.util.List;

import javax.swing.DefaultListModel;
import javax.swing.JList;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;

public class ActionListeners {

    public void addContent(JList<String> itemList, JList<String> addToList)
    {
        //gets the value selected to be added to other other JList
        List<String> selected = itemList.getSelectedValuesList();
        //gets the model of the List to be added too
        DefaultListModel<String> displayModel = (DefaultListModel<String>) addToList.getModel();

        //adds the elements to the JList
        for (String item: selected) 
        {
            displayModel.addElement(item);
        }
    }

    public void removeContent(JList<String> addToList)
    {
        //gets the element selected to be removed
        List<String> selected = addToList.getSelectedValuesList();
        //gets the model of the JList where content will be removed
        DefaultListModel<String> displayModel = (DefaultListModel<String>) addToList.getModel();

        //removes the selected element
        for (String item: selected) {
            displayModel.removeElement(item);
        }
    }

    public void saveContent(DefaultListModel<String> addToList)
    {
        Save saveFile = new Save();
        //adds the content in the JList to be saved
        //to the object
        saveFile.setPartsList(addToList);

        try {
            JAXBContext jaxbContext = 
                    JAXBContext.newInstance(Save.class);
            Marshaller jaxbMarshaller = 
                    jaxbContext.createMarshaller();
            jaxbMarshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);

            String homeDir = System.getProperty("user.home");

            jaxbMarshaller.marshal(saveFile, new File(homeDir + "/Desktop", "xml.xml"));

            jaxbMarshaller.marshal(saveFile, System.out);
        } catch (JAXBException e) {
            e.printStackTrace();
        }

        //saves the content
        //saveFile.saveFileXml();
    }

    public void loadContent(JList<String> addToList)
    {
        Load loadFile = new Load();
        //gets the model of the JList that loaded content will be added too
        DefaultListModel<String> newModel= (DefaultListModel<String>) addToList.getModel();
        //makes sure the model is clear
        newModel.removeAllElements();
        //makes model that the loaded content will be set too
        DefaultListModel<String> loadedModel = loadFile.loadXMLFile();

        //adds the loaded elements from the file to JList's model
        for(int i = 0; i < loadedModel.getSize(); i++)
        {
            newModel.addElement(loadedModel.get(i));
        }
    }

    public void exitProgram()
    {
        //closes the entire program
        System.exit(0);
    }
}

Save.java

import javax.swing.DefaultListModel;
import javax.xml.bind.annotation.XmlElement;
import javax.xml.bind.annotation.XmlRootElement;


@XmlRootElement (name = "lists")
public class Save {
    //array that will hold the content to be saved
    String[] partsListSave;

    //method to set the array partsListSave
    //with the content that will be saved
     public void setPartsList(DefaultListModel<String> model) {
         //Initialize the array with the length of the content
         //to be added
         partsListSave = new String[model.getSize()];

         //adds the content to the array
         for (int i = 0; i < model.getSize(); i++)
         {
             partsListSave[i] = model.getElementAt(i);
         }
     } 

    @XmlElement (name = "parts")
    public String[] getPartsList() {
        return partsListSave;
    }
}

xml.xml

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<lists>
    <parts>Motherboard</parts>
    <parts>Motherboard</parts>
    <parts>Motherboard</parts>
    <parts>Motherboard</parts>
</lists>


推荐答案

您的 Save.java class需要一个合适的setter方法:

Your Save.java class needs an appropriate setter method:

public void setPartsList(String[] partsListSave) {
    this.partsListSave = partsListSave;
}

为验证这一点,我创建了文件 xml.xml

To verify this, I created file xml.xml:

<lists>
    <parts>Part 1</parts>
    <parts>Part 2</parts>
    <parts>Part 3</parts>
</lists>

测试类包含:

public static void main(String[] args) throws Exception {
    File file = new File("xml.xml");

    JAXBContext jaxbContext = JAXBContext.newInstance(Save.class);
    Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller();
    Save load = (Save) jaxbUnmarshaller.unmarshal(file);

    for (String parts : load.getPartsList())
        System.out.println(parts);
}

使用 Save.java ,NPE失败了。添加setter工作。

With your Save.java, it failed with NPE. Adding the setter worked.

最小,完整且可验证

注意

您的问题部分基于误解。

Your question is partly based on a misunderstanding.

JAXB unmarshaller(对 jaxbUnmarshaller.unmarshal(文件); 的调用)返回 null - 它会返回保存的实例。
unmarshal()本身永远不会返回 null (参见 Unmarshaller 的API文档: unmarshal方法永远不会返回null。) - 但它返回的实例中的字段可能是 null

The JAXB unmarshaller (the call to jaxbUnmarshaller.unmarshal(file);) does not return null - it returns an instance of Save, as it should. unmarshal() itself never returns null (see API docs of Unmarshaller: "An unmarshal method never returns null.") - however the fields in the instance it returns may be null.

在这种情况下,字段 Save.partsListSave null ,因为JAXB无法设置它,因为没有合适的setter,如上所述。

In this case the field Save.partsListSave is null, because JAXB cannot set it, since there is no appropriate setter, as explained above.

您看到的NullPointerException是由尝试使用 getPartsList()返回的值引起的,这是 null

The NullPointerException you see is caused by trying to use the value returned by getPartsList(), which is null.

这篇关于JAXB unmarshalling返回Null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆