[java] [Solved] Java String Troubles

Started by
2 comments, last by Stelimar 15 years, 5 months ago
I've been doing some networking stuff in Java lately, and I made a simple chat server where multiple users can register, login and chat with each other. Now I am trying to add the ability to notify users when someone else has logged in, and send the newly logged in user a list of all users currently logged in. The client then keeps a list of all users logged in. The following is the function called when a user logs in:

	public void loggedIn(User user) {
		//Notify all clients that the user logged in
		int userID = user.id;
		SocketChannel userSocket = user.getSocket();
		String[] params = new String[3];
		params[0] = Integer.toString(user.id);
		params[1] = user.name;
		params[2] = STATUS_LOGGED_IN;
		ModuleCommand command = new ModuleCommand(null,this.id,this.id,USER_STATUS,params);
		broadcast(command);
		//Send the user all other users currently logged in
		ListIterator i = users.listIterator();
		params[2] = STATUS_PREVIOUSLY_LOGGED_IN;
		while (i.hasNext()) {
			user = (User) i.next();
			if (user.id != userID) {
				params[0] = Integer.toString(user.id);
				params[1] = user.name;
				command.parameters = params;
				command.socket = userSocket;
				cHandler.sendCommand(command);
			}
		}
	}


The operation of my sockets are based on this tutorial. My problem is that the usernames that are sent are all the same. For example, if user1 logs in, then user2 logs in, then the server will send a "user1 logged in" command both times (I hope that makes sense). However, if I add a simple System.out.println(user.name) somewhere inside of the while loop, then the server sends the correct usernames. I'm thinking this has something to do with the fact that Java stores references to objects in variables rather than the objects themselves, and since the code which actually sends the command to the client is running in a separate thread, the string gets changed before the request is actually processed. However I can't for the life of me figure out an easy way to simply copy a string (and I don't even know for sure if that will fix it). I've tried changing
params[1] = user.name;

to
params[1] = String(user.name);

but I get the error "cannot find symbol : method String(java.lang.String)" which really confuses me, because the Java API reference lists String(String original) as a constructor. Any help would be greatly appreciated. -Stelimar [Edited by - Stelimar on November 19, 2008 11:24:31 PM]
Advertisement
You will need to create a new object with the original string passed in.
params[1] = new String(user.name);
It's because you're using the same "params" array for both calls. Presumably your broadcast method does it's actualy work in a seperate thread...

You need to ensure the params is not modified before that thread finishes with it, and the simplest way would be to use a different array for each call:

	public void loggedIn(User user) {		//Notify all clients that the user logged in		int userID = user.id;		SocketChannel userSocket = user.getSocket();		String[] params = new String[3];		params[0] = Integer.toString(user.id);		params[1] = user.name;		params[2] = STATUS_LOGGED_IN;		ModuleCommand command = new ModuleCommand(null,this.id,this.id,USER_STATUS,params);		broadcast(command);		//Send the user all other users currently logged in		ListIterator i = users.listIterator();		while (i.hasNext()) {			user = (User) i.next();			if (user.id != userID) {				String[] params2 = new String[3];				params2[0] = Integer.toString(user.id);				params2[1] = user.name;				params2[2] = STATUS_PREVIOUSLY_LOGGED_IN;				command.parameters = params2;				command.socket = userSocket;				cHandler.sendCommand(command);			}		}	}


By the way, the use of a string array for passing parameters seems rather, un-Javaish. The normal pattern would have a strong-typed sub-class of "ModuleCommand" for each different type of command you can send...
I don't know why I thought of the String being changed but not the Array/ModuleCommand (both of which I needed to create new instances of). Thanks for the help, and the suggestion about handling the parameters. I got it working now =)

This topic is closed to new replies.

Advertisement