DefaultTreeModel Not Being Received Correctly
Hi There,
I am writing an application in which I am using a JTree to display a DefaultTreeModel which initially contains one parent TreeNode with about 2200 TreeNodes as children, i.e. two levels of nodes. As the user clicks on each of the children, that TreeNode's children are lazy-loaded into the TreeModel, and the JTree is re-painted. That all works.
I am currently implementing the cache by sending the TreeModel to the server each time a new child is lazy-loaded in the client using Sockets. I have tested the object that is being written to the ObjectOutputStream, and that is the correct TreeModel. However, when I test the object that is received through the ObjectInputStream on the server side, it reverts back to the previous version of the TreeModel - i.e. it is not receiving the most up-to-date version. I really don't know why. I have experimented with putting objectOutputStream.flush() in various places and that doesn't seem to make a difference.
This is the method on the client side:
privatevoid writeToServer(ObjectOutputStream oos, RequestProtocolInterface request)
{
try
{
oos.writeObject(request);//this request object contains the most up-to-date version of DefaultTreeModel
oos.flush();
}
catch(IOException e)
{
System.out.println(e.toString());
}
}
This is the run() method on the server side thread:
publicvoid run()
{
RequestProtocolInterface request =null;
Object readObject =null;
while(connected)
{
try
{
readObject = ois.readObject();//for some reason, this does not contain the most up-to-date version
request = (RequestProtocolInterface)readObject;
request.process(this);
}
catch(Exception e)
{
closeConnection();
}
}
}
If you need more information or code, please let me know. I would appreciate any help.
[2798 byte] By [
RoxyLJa] at [2007-10-3 8:10:03]

Hi ejp,
I think this topic might have been more appropriate for the Networking forum. Oh well.
Anyway, sorry for the delay in replying. I've been testing it and trying to find the reason behind why it's not writing the TreeModel correctly, but honestly have not been able to come up with more of an answer. The client is sending the correct TreeModel, but the server is not receiving the correct one. I really don't know why.
I have written a little test program to illustrate the problem. To keep it simple I have not added any methods to close streams or connections. The server throws a socket exception when the first client is run, but on every subsequent run of the client, the problem I'm having is duplicated.
The client's output (on every run after the first) is:
On write 1, the root had 3 children.
On write 2, the root had 4 children.
This is correct. However, the client's output (on every run after the first) is:
On read 1, the root had 3 children.
On read 2, the root had 3 children.
...but the output that I actually want the server to have is:
On read 1, the root had 3 children.
On read 2, the root had 4 children.
Here is the code:
Server.java
import java.net.*;
import java.sql.*;
public class Server extends Thread
{
private final String USERNAME = "JohnDoe";//replace with own username
private final String PASSWORD = "MyPassword";//replace with own password
private final String DATABASE = "MY_DB";//replace with own database
private final String URL = "jdbc:odbc:" + DATABASE;
private final int PORT = 5000;//replace with available port if necessary
private final String DRIVER = "sun.jdbc.odbc.JdbcOdbcDriver";
private ServerSocket serverSocket = null;
private Connection connection = null;
public static void main(String[] args)
{
try
{
new Server();
}
catch (Exception e)
{
System.out.println(e.toString());
}
}
public Server() throws Exception
{
try
{
Class.forName(DRIVER);
connection = DriverManager.getConnection(URL, USERNAME, PASSWORD);
serverSocket = new ServerSocket(PORT);
}
catch (Exception e)
{
System.out.println(e.toString());
}
this.start();
}
public void run()
{
while(true)
{
try
{
System.out.println("Waiting for client connections...");
Socket client = serverSocket.accept();
System.out.println("Accepted a connection from client " + client.getInetAddress().getLocalHost() + ".");
new ServerThread(client, connection);
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
}
}
ServerThread.javaimport java.io.*;
import java.net.Socket;
import java.sql.Connection;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
public class ServerThread extends Thread
{
private ObjectInputStream ois = null;
private Connection conn = null;
private Socket sock = null;
public ServerThread(Socket sock, Connection conn)
{
this.sock = sock;
try
{
InputStream in = this.sock.getInputStream();
ois = new ObjectInputStream(in);
}
catch (Exception e)
{
System.out.println(e.toString());
}
this.start();
}
public void run()
{
int i = 1;
readAnObject(i);
i++;
readAnObject(i);
}
public void readAnObject(int i)
{
Object readObject = null;
try
{
readObject = ois.readObject();
DefaultTreeModel model = (DefaultTreeModel)readObject;
DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
System.out.println("On read " + i + ", the root had " + root.getChildCount() + " children.");
}
catch (Exception e)
{
System.out.println(e.toString());//An (irrelevant?) error is thrown here when the first client is run.
}
}
}
Client.javaimport java.io.*;
import java.net.Socket;
import javax.swing.JTree;
import javax.swing.tree.*;
public class Client
{
private final String SERVER = "MyComputer";//replace with the name of the computer being used as the server
private final int PORT = 5000;//ensure this is the same as the PORT specified in Server.java
private ObjectOutputStream oos = null;
private Socket sock = null;
public static void main(String[] args)
{
new Client();
}
public Client()
{
try
{
sock = new Socket(SERVER, PORT);
OutputStream out = sock.getOutputStream();
oos = new ObjectOutputStream(out);
}
catch (Exception e)
{
System.out.println(e.toString());
}
JTree tree = new JTree();
TreeModel model = tree.getModel();
DefaultMutableTreeNode anotherNode = new DefaultMutableTreeNode("AnotherNode");
DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
int i = 1;
writeTreeModel(model, i);
i++;
root.add(anotherNode);
writeTreeModel(model, i);
}
private void writeTreeModel(TreeModel model, int i)
{
DefaultMutableTreeNode root = (DefaultMutableTreeNode)model.getRoot();
System.out.println("On write " + i + ", the root had " + root.getChildCount() + " children.");
try
{
oos.writeUnshared((Object)model);//have also tried oos.writeObject((Object)model) here
oos.flush();//have experimented with where to put this
}
catch(Exception e)
{
System.out.println(e.toString());
}
}
}
To test this program:
1. Run Server.java
2. Run Client.java - the first run produces a (possibly irrelevant) SocketException
3. Run Client.java again
On step 3, this is what happens:
1. The client creates a new sample JTree instance.
2. The JTree's model is retrieved.
3. The number of children of the root of the model is displayed (3).
4. The model is written to the server.
5. The server receives the model with the correct number of children of the root, as displayed by its output (3).
6. A new node is added to the root node of the model in the client.
7. The number of children of the root of the model is displayed (4).
8. The model is written to the server.
9. The server receives the model with the incorrect number of children of the root, as displayed by its output (still 3 instead of 4).
Do you have any idea as to why this problem is occurring?
Thanks. :)