0

I am working in an Android App and I need to send serialized objects (mainly from a Client class) between the Android Client and a Java Server.

I am using ObjectInputStream and ObjectOutputStream to send the objects through a web socket, but when reading the object in the server it seems like it is trying to cast it as the Client class from the Android package instead of the server package.

Here is a simplified code of what I am calling in my main Activity in Android:

package com.example.razer.clienttest;
import android.os.AsyncTask;
import android.widget.Toast;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class MessageSender extends AsyncTask<Void,Void,Void> {

    ClienteFree cliente = new ClienteFree();
    String test = "Testing this crap";
    static String ip = ""; //This is where I'm putting my IP

    @Override
    protected Void doInBackground(Void...voids){
        try{
            Socket s = new Socket(ip,7000);
            OutputStream os = s.getOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(os);
            //oos.writeObject(test);
            oos.writeObject(cliente);
            oos.flush();

            InputStream is = s.getInputStream();
            ObjectInputStream ois = new ObjectInputStream(is);
            //String Test2 = (String) ois.readObject();
            ClienteFree cliente2 = (ClienteFree)(ois.readObject());

            is.close();
            ois.close();
            os.close();
            oos.close();
            s.close();
        }catch(Exception e){
            System.out.println(e);
        }
        return null;
    }
}

And my server implementation:

import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.List;

public class Server {

    static List<ClienteFree> clientes = new ArrayList<ClienteFree>();
    ClienteFree client = new ClienteFree("Null","Null","Null","null");
    String Test = "Testing this crap again";

    public static final int PORT = 7000;
    public static void main(String[] args) throws IOException, ClassNotFoundException {
            try {
                new Server().runServer();
            } catch (Exception e) {
                e.printStackTrace();
            }
    }

    public void runServer() throws Exception {

        ServerSocket serverSocket = new ServerSocket(PORT);
        System.out.println("Server up and ready for connection...");
        Socket socket = serverSocket.accept();
        System.out.println("Connection succesful");

        ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
        ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());

        //String Test2 = (String) ois.readObject();
        client = (ClienteFree)(ois.readObject());
        //System.out.println(Test2);
        doSomething(client);

        //oos.writeObject(Test);
        oos.writeObject(client);
        oos.flush();    

        ois.close();
        oos.close();
        socket.close();
        serverSocket.close();
    }

    private void doSomething(ClienteFree client){
    clientes.add(client);
    System.out.println(client.getName());
    client.setName("Poncho");
    }
}

The error shows that the server is trying to find the class in the Android package com.example.razer.clienttest.ClienteFree (my android package) instead of the server one. Does anybody know how to solve this issue or the correct way to send objects between Android and Java servers if the object will contain lists of Observable type objects within it?

I have tried serializing the Client objects to a MySQL database from my server using the SQL libraries and it worked, but I haven't found a proper way to do it in Android.

This is the error I'm getting:

Server up and ready for connection...
Connection succesful
java.lang.ClassNotFoundException: com.example.razer.clienttest.ClienteFree
    at java.net.URLClassLoader.findClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
    at java.lang.ClassLoader.loadClass(Unknown Source)
    at java.lang.Class.forName0(Native Method)
    at java.lang.Class.forName(Unknown Source)
    at java.io.ObjectInputStream.resolveClass(Unknown Source)
    at java.io.ObjectInputStream.readNonProxyDesc(Unknown Source)
    at java.io.ObjectInputStream.readClassDesc(Unknown Source)
    at java.io.ObjectInputStream.readOrdinaryObject(Unknown Source)
    at java.io.ObjectInputStream.readObject0(Unknown Source)
    at java.io.ObjectInputStream.readObject(Unknown Source)
    at Server.runServer(Server.java:54)
    at Server.main(Server.java:15)

Thank you!

Flavio501
  • 19
  • 4

1 Answers1

1

The class you sent does not exist on the CLASSPATH at the receiving end.

You can't deploy a similar class in a different package and expect it to be the same as the original class in the original package. It isn't.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Oh, so even if the classes are defined exactly the same way in both the Android app and the Java server, they are not considered the same class if they are not located in the same package? If I create a package (e.g. com.package.shared) in both the client and server and place my class in that package would it be enough or is there some other considerations I'm missing? Sorry for the noobness, I'm new to Android programming and have never faced an issue like this before. – Flavio501 May 17 '18 at 20:38
  • It has to be the same class name in the same package with the same `serialVersionUID` and satisfying the 'Object Versioning' chapter of the Object Serialization Specification. This is most easily accomplished by ensuring that it is always exactly the same .class file at both ends, by copy. You can accomplish that via a shared project in your IDE. – user207421 May 18 '18 at 06:56