Search code examples
javasocketsoopobjectinputstream

java.lang.ClassCastException when receiving object with readObject()


I have a bean class on a Client side that stores user input data and send it through a socket to server. Server has identical bean class.

Server receives object, but when I try to assign what was received to an instance of the bean class, it results in following error:

java.lang.ClassCastException: ie.gmit.sw.client.methods.Client cannot be cast to ie.gmit.sw.server.methods.Client

Class with an error:

public class DriveableImpl implements Driveable{

    private Client client; 
    private ObjectOutputStream out; 
    private ObjectInputStream in; 

    public DriveableImpl() {
        client = new Client(); 
    }

    // Method that receives connection socket and open in/out streams for current session
    @Override
    public void connect(Socket socket){
        try {
            out = new ObjectOutputStream(socket.getOutputStream());
            in = new ObjectInputStream(socket.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public boolean login() throws Exception {

        // Program crash here
        client = (Client) in.readObject();
        System.out.println(client.toString());

        return false;
    }
}

I use InvocationHandler to invoke methods implemented in class above:

public class MethodInvoker implements InvocationHandler{

    private Object returnObject = null; // object that will hold any returns from invoked methods
    private final Driveable userInterface; 


    protected MethodInvoker(Driveable ui) {
        this.userInterface = ui;
    }
    public Object invoke(Object proxy, Method method, Object[] args)
                  throws IllegalAccessException, IllegalArgumentException,
                  InvocationTargetException{

        System.out.println("BEFORE");
        returnObject = method.invoke(userInterface, args);
        System.out.println(method.getName());
        System.out.println("AFTER");

        return returnObject; // could problem be possibly here?
    }
}

I am really not sure what's going on here, as it works in simple design of a Client-Server app. I am posting, in my opinion, program parts that are relevant to an error, but I will modify post if any requests occur.

Thank you!


Solution

  • Note the Serialization Error:

    It clearly states that you have 2 different classes (maybe they look exactly the same) but they are in different packages:

    ie.gmit.sw.**client**.methods
    ie.gmit.sw.**server**.methods
    

    This means, that from the point of view of Java they're completely unrelated

    ie.gmit.sw.client.methods.Client cannot be cast to ie.gmit.sw.server.methods.Client
    

    That's the reason of why you have a class cast exception

    In Java the Same Class means that it resides in the same package and has the same name. So you should have the same class in both server and client. There are two ways to achieve this:

    • Just put the same class twice - once in client and once in a server. In your case it means - rename the package to be something common. This is a bad approach because of code duplication

    • Place the objects that will pass the serialization into the third "common" module (jar will be produced out of it) and when you run the client and server make them dependent on this module. So physically you'll have only one copy of class "Client".