1

I have two simple applications: client and server. Client encrypts (simple AES) custom object and sends it through TCP socket, as bytes, to the server. Server decrypts those bytes and calls the method that recreates this object, like this:

private static Object getObjectFromBytes(byte[] credentials) throws IOException,      ClassNotFoundException{

    ByteArrayInputStream bis = new ByteArrayInputStream(credentials);
    ObjectInput in = null;
    Object credentialsObj = null;

    try {

        in = new ObjectInputStream(bis);
        credentialsObj = in.readObject(); 

    } finally {
      bis.close();
      in.close();
    }
    return credentialsObj;
}

On the client side, when I'am encrypting this object, it is of type mds.hm5.client.ITU_Credentials. On the server side, when I'm decrypting it and converting back to object, it should be mds.hm5.tokenservice.ITU_Credentials. Instead I'am getting the following exception:

java.lang.ClassNotFoundException: mds.hm5.client.ITU_Credentials

He is looking for this object by the old classpath. Why is it happening and how should I fix it?

Additional information:

Here is how I convert this object to byte array on the client side:

private static byte[] getBytesFromObject(Object credentials) throws IOException{

    ByteArrayOutputStream bos = new ByteArrayOutputStream();
    ObjectOutput out = null;
    byte[] newBytes = null;

    try {

      out = new ObjectOutputStream(bos);   
      out.writeObject(credentials);
      newBytes = bos.toByteArray();

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
      out.close();
      bos.close();
    }
    return newBytes;
}   

The reason why I use generic type Object is because I am going use those methods to convert/encrypt/decrypt multiple types. Is it the proper way?

5
  • Haw you in fact validated that your Class exists in given location ? Commented Nov 19, 2012 at 21:43
  • I have a copy of this class in both locations. Commented Nov 19, 2012 at 21:51
  • And who is 'he', anyway? Commented Nov 20, 2012 at 1:58
  • You would be happier if you avoided Java serialization and used SOAP or Jackson or something. Commented Nov 20, 2012 at 1:59
  • @bmargulies By 'he' I mean Java compiler - I guess. I wasn't sure so I wrote 'he'. I'am sorry, I'am still a beginner in those things. Commented Nov 20, 2012 at 9:05

4 Answers 4

3

On the client side, when I'am encrypting this object, it is of type mds.hm5.client.ITU_Credentials.

So that's what it is in the serialized stream.

On the server side, when I'm decrypting it and converting back to object, it should be mds.hm5.tokenservice.ITU_Credentials.

No it shouldn't. It should be the same as when you serialized it [unless you have taken certain magic steps, which clearly you haven't. Without those magic steps there is no magic, and nothing to connect mds.hm5.client.ITU_Credentials with mds.hm5.tokenservice.ITU_Credentials whatsoever]. You have two different classes with the same name and different packages, one in each location. They aren't the same.

He is looking for this object by the old classpath.

You are confused between CLASSPATH and package name. They aren't the same thing. It is looking for this object by its actual package name. What else can it possibly do?

Sign up to request clarification or add additional context in comments.

1 Comment

Exactly! I thought classpath and package are the same thing but now I got it. I created a special package that I will use to store classes that are shared between my applications.
2

The object output stream doesn't serialize the class itself but only its state (the field values). The receiver needs the class file on it's classpath.

It is possible to transfer the class too. You'll have to find (or write) a classloader that can load the class from your connection. If you have an URL for your classfile then you could use the URLClassloader. Then you don't have to add the class to your classpath.

4 Comments

I'am not sure If I understand your answer correctly but I do have a copy of ITU_Cardentials class on both sides: server and client. (sorry for spelling credentials wrong everywhere)
If both ITU_Credential classes have the same version, then it should work. Then you should be able to serialize an instance on the client, send the bytes and de-serialize it to a new instance on the server.
What do you mean "to have the same version"? I tried adding version ID to both and it didn't work. I also re-imported this class from client application again to make sure they are the same. I just got it to work by creating a package on my server app called mds.hm5.client and putting this class there - is that the way? Does this class always has to have the same classpath to be able to serialize it and deserialize it?
@Booyaches If you just got it to work by putting the class into that package, obviously it wasn't there beforehand. When you say 'classpath', I strongly suspect you mean 'package'. Classes don't have classpaths. A class is only 'the same' if it is the same binary .class file, compiled from the same source code, loaded by the same classloader.
0

Your client neeeds to have in its classpath the .class files that define the object. What you are doing is serializing/deserializing the instance, not the class.

Comments

0

Late, but it may be useful for someone in the future: I wanted to send an object Message whose package was entities in the client side, but in the server side this Message class was not nested within a entities package, so this Exception was thrown. It may be dumb but I spent many hours figuring out this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.