Geertjan's Blog

  • June 25, 2011

Node Serialization in NetBeans Platform 7.0

Geertjan Wielenga
Product Manager

Node serialization makes sense when you're not interested in the data (since that should be serialized to a database), but in the state of the application. For example, when the application restarts, you want the last selected node to automatically be selected again. That's not the kind of information you'll want to store in a database, hence node serialization is not about data serialization but about application state serialization.

I've written about this topic in October 2008, here and here, but want to show how to do this again, using NetBeans Platform 7.0. Somewhere I remember reading that this can't be done anymore and that's typically the best motivation for me, i.e., to prove that it can be done after all.

Anyway, in a standard POJO/Node/BeanTreeView scenario, do the following:

  1. Remove the "@ConvertAsProperties" annotation at the top of the class, which you'll find there if you used the Window Component wizard. We're not going to use property-file based serialization, but plain old java.io.Serializable  instead.

  2. In the TopComponent, assuming it is named "UserExplorerTopComponent", typically at the end of the file, add the following:

    public Object writeReplace() {
    //We want to work with one selected item only
    //and thanks to BeanTreeView.setSelectionMode,
    //only one node can be selected anyway:
    Handle handle = NodeOp.toHandles(em.getSelectedNodes())[0];
    return new ResolvableHelper(handle);
    public final static class ResolvableHelper implements Serializable {
    private static final long serialVersionUID = 1L;
    public Handle selectedHandle;
    private ResolvableHelper(Handle selectedHandle) {
    this.selectedHandle = selectedHandle;
    public Object readResolve() {
    WindowManager.getDefault().invokeWhenUIReady(new Runnable() {
    public void run() {
    try {
    //Get the TopComponent:
    UserExplorerTopComponent tc = (UserExplorerTopComponent) WindowManager.getDefault().findTopComponent("UserExplorerTopComponent");
    //Get the display text to search for:
    String selectedDisplayName = selectedHandle.getNode().getDisplayName();
    //Get the root, which is the parent of the node we want:
    Node root = tc.getExplorerManager().getRootContext();
    //Find the node, by passing in the root with the display text:
    Node selectedNode = NodeOp.findPath(root, new String[]{selectedDisplayName});
    //Set the explorer manager's selected node:
    tc.getExplorerManager().setSelectedNodes(new Node[]{selectedNode});
    } catch (PropertyVetoException ex) {
    } catch (IOException ex) {
    return null;

  3. Assuming you have a node named "UserNode" for a type named "User" containing a property named "type", add the bits in bold below to your "UserNode":

    public class UserNode extends AbstractNode implements Serializable {static final long serialVersionUID = 1L;
    public UserNode(User key) {
    public Handle getHandle() {
    return new CustomHandle(this, getName());
    public class CustomHandle implements Node.Handle {
    static final long serialVersionUID = 1L;
    private AbstractNode node = null;
    private final String searchString;
    public CustomHandle(AbstractNode node, String searchString) {
    this.node = node;
    this.searchString = searchString;
    public Node getNode() {
    return node;


  4. Run the application and select one of the user nodes. Close the application. Start it up again. The user node is not automatically selected, in fact, the window does not open, and you will see this in the output:

    Caused: java.io.InvalidClassException: org.serialization.sample.UserNode; no valid constructor

    Read this article and then you'll understand the need for this class:

    public class BaseNode extends AbstractNode {
    public BaseNode() {
    public BaseNode(Children kids) {
    public BaseNode(Children kids, Lookup lkp) {
    super(kids, lkp);

    Now, instead of extending AbstractNode in your UserNode, extend BaseNode. Then the first non-serializable superclass of the UserNode has an explicitly declared no-args constructor,

Do the same as the above for each node in the hierarchy that needs to be serialized. If you have multiple nodes needing serialization, you can share the "CustomHandle" inner class above between all the other nodes, while all the other nodes will also need to extend BaseNode (or provide their own non-serializable super class that explicitly declares a no-args constructor).

Now, when I run the application, I select a node, then I close the application, restart it, and the previously selected node is automatically selected when the application has restarted.

Join the discussion

Comments ( 2 )
  • Jesse Glick Monday, June 27, 2011

    You probably do not need a writeReplace for the TC and all the work with saving the selection state. ExplorerManager is itself serializable, so try just overriding read/writeExternal to call super and then load/store the ExplorerManager field.

    Making a Node serializable is not a good idea. There is a bunch of stuff in there like the Lookup and the Children that you probably do not want to persist. In this case, UserNode.getHandle should just return a class with a single field corresponding to key.getType() (or simply key, if User is serializable); the handle's getNode should make a new UserNode based on that key.

  • guest Tuesday, May 8, 2012

    Not sure why ResolvableHelper - readResolve is never called..even after following your blog in 7.1. All the connected blog entries seems to be non-existing URLs

    Persisting the nodes of a TopComponent seems to be not so well explained in any forums..

    //@ConvertAsProperties(dtd = "-//test//UserTop//EN", autostore = false)

    public final class UserTopComponent extends TopComponent implements ExplorerManager.Provider, Serializable {


Please enter your name.Please provide a valid email address.Please enter a comment.CAPTCHA challenge response provided was incorrect. Please try again.