1

Im currently working on a simple server - client structure for future projects. I decided it would be the best to create my own data-package with custom header-information such as local/public ip, a time stamp etc. The following is the class i came up with:

public class DataPackage {
    private Object object;
    private Date time;
    private long timeMs;
    private boolean responded;
    private String publicIp;
    private String internalIp;
    private int hash;

    public DataPackage(Object object) {
        this.object = object;
        this.responded = false;
        this.time = Calendar.getInstance().getTime();
        this.timeMs = System.currentTimeMillis();
        this.publicIp = this.generatePublicIp();
        this.internalIp = this.generateInternalIp();
        this.hash = System.identityHashCode(this);
    }

    private String generatePublicIp() {
        try {
            URL whatismyip = new URL("http://checkip.amazonaws.com");
            BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));

            return in.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String generateInternalIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

}

(I removed the getters and setters)

I decided to use an object so i can send anything in the class. It compiles well but if i try to send a simple string, packaged in the class, i get a NotSerializableException. Are there any attributes or fields which cant be converted to a stream or should i change the class to be generic? Im NOT an expert in streams and networking, so im thankfull for every bit of help and explanation i can get.

NOTE: Im not a native english speaker to please excuse any spelling/grammar issues.

Peter
  • 15
  • 2

3 Answers3

1

You should implement Serializable interface in order for the class to be transferred over network.

Change first line of your class to :

import java.io.Serializable;
public class DataPackage implements Serializable{
Avinash Sagar
  • 527
  • 4
  • 10
0

java.io.NotSerializableException is thrown when your object is not serializable that means your object or any non-transient property of that object does not implement the Serializable interface. And in your case, DataPackage is not Serializable. Serializable is a marker interface which basically tells JVM that any instance of the Serializable type can be serialized. Here you can go through the docs of Serializable and NotSerializableException.

Amit Bera
  • 7,075
  • 1
  • 19
  • 42
0

Your class should implement the Serializable interface.

Also note that each property of your class, in your case object should also implement this interface in order for serialization to work properly.

So I would consider making this class generic to force object to implement Serializable interface.

EDIT : for example if you try to serialize a DataPackage that contains a ByteBuffer(which is not Serializable) like this : new DataPackage(ByteBuffer.allocate(1)), you will get an Exception.

try this :

    import java.io.Serializable;

    public class DataPackage<T extends Serializable> implements Serializable{
    private T object;
    private Date time;
    private long timeMs;
    private boolean responded;
    private String publicIp;
    private String internalIp;
    private int hash;

    public DataPackage(T object) {
        this.object = object;
        this.responded = false;
        this.time = Calendar.getInstance().getTime();
        this.timeMs = System.currentTimeMillis();
        this.publicIp = this.generatePublicIp();
        this.internalIp = this.generateInternalIp();
        this.hash = System.identityHashCode(this);
    }

    private String generatePublicIp() {
        try {
            URL whatismyip = new URL("http://checkip.amazonaws.com");
            BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));

            return in.readLine();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    private String generateInternalIp() {
        try {
            return InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return null;
    }

}

In this way you can be sure that the objects you are trying to send are all serializable.

If you dont want to use generics than make object of type Serializable like this :

import java.io.Serializable;

        public class DataPackage implements Serializable{
        private Serializable object;
        private Date time;
        private long timeMs;
        private boolean responded;
        private String publicIp;
        private String internalIp;
        private int hash;

        public DataPackage(Serializable object) {
            this.object = object;
            this.responded = false;
            this.time = Calendar.getInstance().getTime();
            this.timeMs = System.currentTimeMillis();
            this.publicIp = this.generatePublicIp();
            this.internalIp = this.generateInternalIp();
            this.hash = System.identityHashCode(this);
        }

        private String generatePublicIp() {
            try {
                URL whatismyip = new URL("http://checkip.amazonaws.com");
                BufferedReader in = new BufferedReader(new InputStreamReader(whatismyip.openStream()));

                return in.readLine();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        private String generateInternalIp() {
            try {
                return InetAddress.getLocalHost().getHostAddress();
            } catch (UnknownHostException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
            return null;
        }

    }