Opening Serialized Data into the NetBeans Platform

The question of the day comes from Winston Dehaney:
Is there any way to handle what happens whenever I try to open a file. The file is a serialised ArrayList. when I open the file, it is de-serialised to an array then the information from the array is opened. The functionality for the actions to perform when opening this file and how to show it in an editor is already complete. I just wanted to be able to override the functionality in opening a file.

I started by simulating the problem using the code found here, i.e., I created a new Action that creates a serialized file consisting of a list of Patients:

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.List;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.filesystems.FileUtil;
import org.openide.util.NbBundle.Messages;

@ActionID(
        category = "Tools",
        id = "org.patients.ser.SerializeAction")
@ActionRegistration(
        displayName = "#CTL_SerializeAction")
@ActionReference(
        path = "Menu/File", 
        position = -100)
@Messages("CTL_SerializeAction=Serialize")
public final class SerializeAction implements ActionListener {

    List<Patient> pList = new ArrayList<>();

    @Override
    public void actionPerformed(ActionEvent e) {
        pList.add(new Patient("Tom"));
        pList.add(new Patient("Dick"));
        pList.add(new Patient("Harry"));
        try {
            savePatientList();
        } catch (FileNotFoundException ex) {
        }
    }

    private void savePatientList() throws FileNotFoundException {
        try {
            ObjectOutputStream os;
            //I created a "Serialized" folder in the layer,
            //so I know that the "Serialized" folder exists here:
            try (FileOutputStream fs = new FileOutputStream(
                    FileUtil.toFile(FileUtil.getConfigFile("Serialized").
                    createData("Patients.ser")))) {
                os = new ObjectOutputStream(fs);
                os.writeObject(pList);
            }
            os.close();
            System.out.println("Saved!");
        } catch (IOException ex) {
        }
    }
    
}

This leaves me with a "Patients.ser" file. And here is another Action, for deserializing the file and doing something with its content. Here, a TopComponent is created for each Patient in the List, but anything else could be done, of course.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.util.ArrayList;
import java.util.List;
import org.openide.awt.ActionID;
import org.openide.awt.ActionReference;
import org.openide.awt.ActionRegistration;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.util.Exceptions;
import org.openide.util.NbBundle.Messages;
import org.openide.windows.TopComponent;

@ActionID(
        category = "Build",
        id = "org.patients.ser.DeserializeAction")
@ActionRegistration(
        displayName = "#CTL_DeserializeAction")
@ActionReference(
        path = "Menu/File", 
        position = 0)
@Messages("CTL_DeserializeAction=Deserialize")
public final class DeserializeAction implements ActionListener {

    private List<Patient> pList = new ArrayList<>();

    @Override
    public void actionPerformed(ActionEvent e) {
        //Do some checking here to make sure the Serialized folder exists
        //and that it contains the ser files you're interested in:
        for (FileObject serialized : 
                 FileUtil.getConfigRoot().getFileObject("Serialized").getChildren()) {
            try {
                loadPatientList(serialized.getInputStream());
            } catch (FileNotFoundException ex) {
                Exceptions.printStackTrace(ex);
            }
        }
    }

    private void loadPatientList(InputStream fs) {
        ObjectInputStream is;
        try {
            is = new ObjectInputStream(fs);
            pList = (List<Patient>) is.readObject();
            for (Patient p : pList) {
                //As an example,
                //you can see that one TopComponent 
                //is created for each Patient found in the List:
                TopComponent tc = new TopComponent();
                tc.setDisplayName(p.getName());
                tc.open();
                tc.requestActive();
            }
            fs.close();
            is.close();
        } catch (IOException | ClassNotFoundException ex) {
        }
    }
    
}

Finally, to complete the scenario, here is the Patient class used by both Actions above.

public class Patient implements Serializable {

    String name;

    public Patient(String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
    
}

A different approach is to create new File Type support (there's a tutorial and a wizard to help you do that) for SER files, using any MIME Type name you prefer, e.g., "application/x-ser". Then define the DataObject such that a text editor is not opened, assuming you don't want a text editor, while implementing Openable so that when the file is opened (via the "Open" action or by double-clicking on it), the same result as the above is produced:

public class SerDataObject extends MultiDataObject implements Openable {

    private List<Patient> pList = new ArrayList<>();

    public SerDataObject(FileObject pf, MultiFileLoader loader) 
      throws DataObjectExistsException, IOException {
        super(pf, loader);
    }

    @Override
    public void open() {
        try {
            loadPatientList(getPrimaryFile().getInputStream());
        } catch (FileNotFoundException ex) {
            Exceptions.printStackTrace(ex);
        }
    }

    private void loadPatientList(InputStream fs) {
        ObjectInputStream is;
        try {
            is = new ObjectInputStream(fs);
            pList = (List<Patient>) is.readObject();
            for (Patient p : pList) {
                //As an example,
                //you can see that one TopComponent 
                //is created for each Patient found in the List:
                TopComponent tc = new TopComponent();
                tc.setDisplayName(p.getName());
                tc.open();
                tc.requestActive();
            }
            fs.close();
            is.close();
        } catch (IOException | ClassNotFoundException ex) {
        }
    }

}
Comments:

Hey Geertjan,
Awesome posts. I have learned a lot from you.
I am just wondering why have you not used "try with resource" feature of java 7. I see you have used multi catch feature of java 7. Did you try it and gave up?
Try with resource is quite a gem of Java 7. Any specific reason for not using it?
Thanks,
Vignesh

Posted by Vignesh Arjunan on June 01, 2013 at 08:32 PM PDT #

Look again. I am using it.

Posted by Geertjan on June 01, 2013 at 09:45 PM PDT #

Thank you very much Geertjan for sharing this and answering my question. I followed it and it worked. This is truly a great post. I'm going to practice more with file types because I realised I could even use it to implement actions such as undo and redo.

Posted by guest on June 02, 2013 at 12:21 AM PDT #

Just once !!!!

Posted by guest on June 02, 2013 at 12:34 AM PDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Geertjan Wielenga (@geertjanw) is a Principal Product Manager in the Oracle Developer Tools group living & working in Amsterdam. He is a Java technology enthusiast, evangelist, trainer, speaker, and writer. He blogs here daily.

The focus of this blog is mostly on NetBeans (a development tool primarily for Java programmers), with an occasional reference to NetBeans, and sometimes diverging to topics relating to NetBeans. And then there are days when NetBeans is mentioned, just for a change.

Search

Archives
« July 2014
SunMonTueWedThuFriSat
  
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
  
       
Today