Java ClassCastException with two identical classes in different packets sent over the network

I got the following problem, my project consists of two packages (Client and Server) where each one has a class Package

. Now I want to send this class over the network via ObjectOutputStream

/ ObjectInputStream

like this:

//Client - this is in package client
ObjectOutputStream out = new SocketOutputStream(socket.getOutputStream);
Package package = new Package();
out.writeObject(package);

//Server - this is in package server
ObjectInputStream in = new SocketInputStream(socket.getInputStream);
Object o = in.readObject();
if(o instanceof Package) ... //do something important

      

So the problem is in the last line where I get a ClassCastException. The reason, obviously, is that it takes a full path to determine the type of the object, so it client.Package

doesn't server.Package

. The problem is that I cannot put the client package on the server or vice versa.

So here's the real question: can I determine the type of the class without importing the package class from the package (client / server)? Or is it possible to send an object over the network without class information?


Edit: The package class looks like this:

public class Package implements Seriablizable {
    private static final long serialVersionUID = 5050301321863757269L;

    public String objectName;
    public Object[] parameters;
    public Class[] parameterTypes; //parameter types
}

      


Thanks for the help :)

+2


source to share


4 answers


When you declare two classes with the same name in different packages, they are fundamentally different classes. This is why you get an exception when you try to apply from one type to another.

The problem is that I cannot host the client package on the server or vice versa.

There is no way to convince the Java type system that both classes are the same. They are different.

The simplest solution is to create a third package that contains the classes that are needed on both the client and server side. Place the generic package (or packages) in a JAR file and add it to the client and server side classpath.

There are other alternatives such as:

  • using a different marshalling / unbinding mechanism (JSON, XML, custom), or

  • using the available hooks in the Java serialization library for type conversion (see @EJP's answer),

but (in my opinion) this problem boils down to a design error and the best approach is to fix this error soon rather than document it.

If you are passing objects from java client to java server via Java serialization, you must use the same classes on both sides. If this is not possible for a reasonable technical reason (as opposed to a design flaw), then this is most likely a good reason NOT to use Java serialization.




To answer your "real" questions:

Q: Can I determine the class type without importing the package class from the package (client / server)?

Strictly yes, but it won't help you.

  • You can refer to a class with its fully qualified name; eg.

    if (o instanceof com.acme.WeaselTrap)
    
          

  • You can get the actual type of the object Class

    .

    Class<?> clazz = o.getClass();
    
          

But once you get there, you still have the problem that the two types with the same name in different packages are fundamentally different.

(Of course, if your code can handle other classes, you can simplify your life by changing the class names so that the simple names are different.)

Q: Or is it possible to send an object over the network without class information?

Don't use Java serialization.

+2


source


The reason is obviously because it takes a full path to determine the type of the object, so client.Package is not a server. Package. The problem is that I cannot put the client package on the server or vice versa.

You just have to do just that, or put it in a third package available to both the client and the server.



Either implement writeReplace()

or readResolve()

inside classes, but that means that the class that does this must be aware of another class in another package, which is probably also messing up your package problem in a different way.

+2


source


Shouldn't your instance be a package not a package? Since this is the name of the class.

You can send the object back and forth as xml or json. The data can be sorted and not sorted by all the classes you want.

For example: Marshall / Unmarshall JSON for Java class using JAXB

0


source


The reason it doesn't work is because you probably haven't implemented the Java serialization mechanism in your class. As described here , all you have to do is implement your java.io.Serializable class. Even if the absolute paths are different, if the code is the same in client.Package and server.Package, this will work fine. Note that if you have any structures in the package class that are not native Java types, they will also need to implement java.io.Serializable.

0


source







All Articles