Solved

Problem rendering tree nodes of tree sent to applet from servlet

Posted on 2003-12-08
13
840 Views
Last Modified: 2013-11-24
Hi,

I have an applet and a servlet and a DefaultMutableTreeNode being sent serialized from the servlet to the applet. In the servlet, the root has children of DefaultMutableTreeNodes with Result objects as UserObjects. The JTree in the applet should display the nodes of the root as different colored icons, see MyRenderer. The problem is that in the code in MyRenderer, the getUserObject object is not instanceOf Result, and only displays the dummy (yellow) icon. The getUserObject is null...

When I test with a root node with DFMTreeNode children with Result objects as UserObjects in the applet code, the tree displays with correct colored icons.

The Result.class exists both on server and client side in my deployment.
Why is getUserObject null? How can I get the nodes to render correctly?
Greatful for help - thanks in advance!


CLIENT SIDE:

package result;

import gp.triacq.qc.web.site.style.QCTheme;

import javax.swing.*;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.DefaultMutableTreeNode;
import java.awt.*;

public class TreePanel extends JPanel {

  private JTree _tree;
  private TestApplet _parent;

  public TreePanel(TestApplet parent) {
    super();
    _parent = parent;
    setLayout(new BorderLayout());

    DefaultMutableTreeNode root = new DefaultMutableTreeNode(new Result("Root", 2));
    DefaultMutableTreeNode child_1 = new DefaultMutableTreeNode(new Result("Result 1", 2));
    DefaultMutableTreeNode child_2 = new DefaultMutableTreeNode(new Result("Result 2", 3));
    DefaultMutableTreeNode child_11 = new DefaultMutableTreeNode(new Result("Result 4", 1));
    DefaultMutableTreeNode child_12 = new DefaultMutableTreeNode(new Result("Result 5", 2));
    DefaultMutableTreeNode child_21 = new DefaultMutableTreeNode(new Result("Result 6", 1));
    DefaultMutableTreeNode child_22 = new DefaultMutableTreeNode(new Result("Result 7", 1));
    root.add(child_1);
    root.add(child_2);
    child_1.add(child_11);
    child_1.add(child_12);
    child_2.add(child_21);
    child_2.add(child_22);
    _tree = new JTree(root);
    _tree.setRootVisible(false);
    _tree.setShowsRootHandles(true);
    _tree.setCellRenderer(new MyRenderer(_parent.getGreenIcon(), _parent.getRedIcon(), _parent.getYellowIcon()));
 
   add(_tree);
  }

  public void updateTree(DefaultMutableTreeNode root) {
    if (root != null) {
      if (_tree != null) {
        remove(_tree);
      }
      _tree = new QCTree(root);
      _tree.setRootVisible(false);
      _tree.setShowsRootHandles(true);
      _tree.setCellRenderer(new MyRenderer(_parent.getGreenIcon(), _parent.getRedIcon(), _parent.getYellowIcon()));
      add(_tree);
    } else {
      JLabel label = new JLabel("No result tree structure is available");
    }
  }

  private class MyRenderer extends DefaultTreeCellRenderer {

    private ImageIcon _greenIcon;
    private ImageIcon _redIcon;
    private ImageIcon _yellowIcon;

    public MyRenderer(ImageIcon greenIcon, ImageIcon redIcon, ImageIcon yellowIcon) {
      _greenIcon = greenIcon;
      _redIcon = redIcon;
      _yellowIcon = yellowIcon;
    }

    public Component getTreeCellRendererComponent(JTree tree, Object value, boolean sel, boolean expanded,
                                                  boolean leaf, int row, boolean hasFocus) {


      ResultComponent item;

      super.getTreeCellRendererComponent(tree, value, sel, expanded, leaf, row, hasFocus);
      DefaultMutableTreeNode node = (DefaultMutableTreeNode) value;
      Object temp = node.getUserObject();

      // Debug
      if (temp == null) {
        System.out.println("temp = null"); // This is run for nodes of root from servlet
      } else {
        System.out.println("temp getClass = " + temp.getClass()); // This is run for nodes of root in applet (getClass = result.Result)
      }

      if (temp instanceof Result) {
        item = (Result)temp;

        if (item.getValue() == 1) {
          if (_greenIcon != null) {
            setIcon(_greenIcon);
          }
        }
        if (item.getValue() == 2) {
          if (_redIcon != null) {
            setIcon(_redIcon);
          }
        }
        if (item.getValue() == 3) {
          if (_yellowIcon != null) {
            setIcon(_yellowIcon);
          }
        }

      } else {
        if (_yellowIcon != null) {
          setIcon(_yellowIcon);     // Only this statement is run
        }
      }
      return this;
    }
  }
}


SERVER SIDE


package result;

import javax.servlet.*;
import javax.servlet.http.*;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Vector;
import javax.swing.tree.*;

public class TestServlet extends HttpServlet {

  public void init() {
  }

  public void doPost(HttpServletRequest request, HttpServletResponse response)
          throws ServletException, IOException {  

    // Hanle request for applet

    // Tree to return to applet
    Vector roots = new Vector();
    DefaultMutableTreeNode root = new DefaultMutableTreeNode(new Result("Root", 0));
    DefaultMutableTreeNode n1 = new DefaultMutableTreeNode(new Result("A", 0));
    DefaultMutableTreeNode n2 =  new DefaultMutableTreeNode(new Result("B", 1));
    DefaultMutableTreeNode n3 = new DefaultMutableTreeNode(new Result("C", 2));
    n1.add(new DefaultMutableTreeNode(new Result("A 1", 0)));
    n1.add(new DefaultMutableTreeNode(new Result("A 2", 1)));
    n2.add(new DefaultMutableTreeNode(new Result("B 1", 2)));
    n3.add(new DefaultMutableTreeNode(new Result("C 1", 3)));
   
    // Vector with the root object sent to applet
    try {
       ObjectOutputStream outputToApplet = new ObjectOutputStream(response.getOutputStream());
       outputToApplet.writeObject(roots);
       outputToApplet.flush();
       outputToApplet.close();
   } catch(Exception x) {
      x.printStackTrace();
   }
}
 
0
Comment
Question by:MarteJ
13 Comments
 
LVL 15

Expert Comment

by:dualsoul
ID: 9895116
hm...just a suggestion...may be you have different JVM on client an server, so desirialization doesn't work correctly?
    may be you can try use XMLEncoder and XMLDecoder for serialization objects in XML, is should be compatibly between different JVMs. (this featere included in JDK since 1.4.0)
0
 
LVL 92

Expert Comment

by:objects
ID: 9895133
is that just a summaryt of your code?
The servlet returns the vector roots but I don't see where that vector is populated.
0
 
LVL 92

Accepted Solution

by:
objects earned 300 total points
ID: 9895142
Ignore last comment, have found the problem.

the user object member variable in DMTN is declared transient so it does not get serialized.
0
 

Author Comment

by:MarteJ
ID: 9895206
objects,

Yes, it is just a summary, forgot roots.add(root); .

<the user object member variable in DMTN is declared transient so it does not get serialized.>

What does it mean that the userObjcet is transient? The userObject is null because it does not get serialized then? How should I solve this?

Thanks!
0
 
LVL 92

Expert Comment

by:objects
ID: 9895246
A member var that is declared transient is not included in the serialization process.
0
 
LVL 92

Expert Comment

by:objects
ID: 9895252
to solve it you need to use a different structure to pass your tree between servlet and applet.
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 
LVL 35

Assisted Solution

by:TimYates
TimYates earned 200 total points
ID: 9895278
Writew your own class which extends DefaultMutableTreeNode and add your own "Object" field to it...

(make sure you implement Serializable)

Transient is explained here: http://mindprod.com/jgloss/transient.html#TRANSIENT

basically,

"Transient instance fields are neither saved nor restored by the standard serialisation mechanism. You have to handle restoring them yourself."

In DefaultMutableTreeNode.java:

--------------------

public class DefaultMutableTreeNode extends Object implements Cloneable,
       MutableTreeNode, Serializable
{
    ...

    /** optional user object */
    transient protected Object      userObject;

--------------------
0
 
LVL 92

Expert Comment

by:objects
ID: 9895330
just what i was about to suggest :)
Or write your own TreeNode class, or make Result implement TreeNode.
0
 

Author Comment

by:MarteJ
ID: 9895450
Thanks for helping!!

I'm trying to extend DMTreeNode, but I think I got it wrong:


package result;

import javax.swing.tree.*;
import java.io.Serializable;

public class MyTreeNode extends DefaultMutableTreeNode implements Serializable {

  protected Object userObject;

  public MyTreeNode(Result result) {
    setUserObject(result);
  }

  public void setUserObject(Object object) {
    userObject = object;
  }

  public Object getUserObject() {
    return userObject;
  }
}


Since this is used both on client and server side, I copy MyTreeNode.class to the servlet's result directory (as with Result.class)

When running the applet, I get the following error:

java.io.InvalidClassException: result.MyTreeNode; local class incompatible: stream classdesc serialVersionUID = -6854483571538912795, local class serialVersionUID = 4884205795974306009

Help....
0
 
LVL 92

Expert Comment

by:objects
ID: 9895559
you'll get that error if the class doing the serializing is different from the class doing the unserializing. ie. if you update one you need to update the other, and restart webapp and reload applet.
0
 
LVL 86

Expert Comment

by:CEHJ
ID: 9895564
You must place copies of your latest class versions at both ends or you'll get binary incompatibilities with serialization
0
 

Author Comment

by:MarteJ
ID: 9895814
Yessss! It works! I am now able to transfer a tree root from my servlet to my applet, displayed according to the objects each node represents! I'm not totally done with my objectives, but I'm getting there thanks to your help! Probably need some more assistance pretty soon...

Thanks a lot!!
0
 
LVL 92

Expert Comment

by:objects
ID: 9899282
0

Featured Post

How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

Join & Write a Comment

Suggested Solutions

Are you developing a Java application and want to create Excel Spreadsheets? You have come to the right place, this article will describe how you can create Excel Spreadsheets from a Java Application. For the purposes of this article, I will be u…
International Data Corporation (IDC) prognosticates that before the current the year gets over disbursing on IT framework products to be sent in cloud environs will be $37.1B.
Viewers will learn about basic arrays, how to declare them, and how to use them. Introduction and definition: Declare an array and cover the syntax of declaring them: Initialize every index in the created array: Example/Features of a basic arr…
This tutorial will introduce the viewer to VisualVM for the Java platform application. This video explains an example program and covers the Overview, Monitor, and Heap Dump tabs.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now