Search code examples
javamultithreadingsocketsserversocketobjectoutputstream

ObjectOutputStream not updating


I'm working on a server, where the serverclass creates a new thread for each connected client, and when the client is connected, the ObjectOutputStream won't refresh on serveral connected clients. It is stuck on the last connected clients OutputObjectStream

This is the server init function

    private void init(Server s)
    {
    ServerSocket server = null;
    Socket c = null;
    ServerThread tmp = null;
    try
    {
        this.db = new Database();
        server = new ServerSocket(6789);
        System.out.println("Listening on 6789");
        while(true)
        {
            c = server.accept();
            tmp = new ServerThread(c, s);
            clients.add(tmp);
            new Thread(tmp).start();
        }
    }catch(IOException | SQLException e)
    {
        e.printStackTrace();
        System.exit(1);
    }   

This is the ServerThread constructor and run function:

    package server;

import java.io.EOFException;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;

import scripts.Response;

import com.sun.rowset.CachedRowSetImpl;

public class ServerThread implements Runnable
{
public static ObjectOutputStream output;
private static ObjectInputStream input;
private Socket client = null;
private Server server = null;
private Response line = null;
private String usr;

public ServerThread(Socket c, Server server) throws IOException
{
    this.client = c;
    this.server  = server;
    this.output = new ObjectOutputStream(client.getOutputStream());
    output.flush();
    output.reset();
    this.input  = new ObjectInputStream(client.getInputStream());
}

public void run()
{
    try
    {               
        System.out.println("Client connected");

        write(new Response("200","Time to login"));
        while((line = (Response)input.readObject()) != null)
        {
            read_code(line);
        }
    }catch(EOFException e){
        System.out.println("EOFException, probably end of stream");

    }catch(IOException e)
    {
        e.printStackTrace();
        Thread.currentThread().interrupt();
    }catch(ClassNotFoundException cnfe)
    {
        cnfe.printStackTrace();
    } catch (SQLException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
}

public void alert_user(String q) throws IOException
{
    System.out.println("In thread "+q);
    write(new Response("404", "You are being alerted!"));
}

private void read_code(Response response) throws IOException, SQLException
{
    HashMap tmp_response = response.extract_map();
    switch ((String)tmp_response.get("code"))
    {
        case "420":
            usr_login(tmp_response);
            break;
        case "430":
            select_query((String)tmp_response.get("to_select"), (String)tmp_response.get("table"), (String)tmp_response.get("rest"));
            break;
        case "431":
            /**
             * server.alertUsers(ArrayList<String> usernames); if there is users that has to be alerted
             */
            insert_query((String)tmp_response.get("table"), (ArrayList<String>)tmp_response.get("columns"), (ArrayList<String>)tmp_response.get("values"));
            break;
        default:
            System.out.println("Unrecognized command");
    }
}

private void usr_login(HashMap tmp_response) throws IOException
{
    String usr = (String) tmp_response.get("username");
    String pass = (String) tmp_response.get("password");
    boolean login = server.query_login(usr, pass);
    System.out.println(login);
    if(login)
    {
        write(new Response("9001", "Login Successfull!"));
        this.usr = usr;
    }else
        write(new Response("8999", "Login Unsuccessfull!"));
}

private void insert_query(String table, ArrayList<String> columns, ArrayList<String> values) throws IOException, SQLException
{
    CachedRowSetImpl rows = server.insert_query(table, columns, values);
    write(new Response("3", rows));
}

private void select_query(String to_select, String table, String rest) throws SQLException, IOException
{
    CachedRowSetImpl rows = server.select_query(to_select, table, rest);
    write(new Response("2", rows));
}

private void write(Response resp) throws IOException
{
    System.out.println(output.toString());
    System.out.println(client.toString());
    output.reset();
    output.writeObject(resp);
    output.flush();
}

public String get_user()
{
    return usr;
}

}

So when I try to print out the objects, I get this

    Client connected
    java.io.ObjectOutputStream@3933c336 (New client (1) connected)
    Client connected
    java.io.ObjectOutputStream@5adada9e (New client (2) connected)      
    java.io.ObjectOutputStream@5adada9e (Sending to first client)

EDIT Why won't the ObjectOutputStream refresh, and use the outputstream it was assigned to from the beginning, and not the latest one?

EDIT Forgot to add the write function, and where it is printed

EDIT Added whole ServerThread class


Solution

  • This is a case of static-confusion.

    The keyword static in Java denotes a component (variable or method) that is completely independent from the instances of this class. For variables this means that there is only one copy of the variable for all instances to share, instead of a seperate copy for each instance (i.e. non-static variables).

    Because the instances share the static variable, its value is always the same for all instances. If you change the value in one instance, it will also change in all other instances.


    In your case you used static for the ObjectInputStream and the ObjectOutputStream so that they cannot be changed: the keyword final makes a variable unchangeable. Note that this only makes assignements impossible, not changing the internal values of the assigned object (e.g. via a setter). It just prevents you from making a new object and putting it into the final variable.