简体   繁体   中英

serialization objects in java

Is there a way to get around during the serialization of the object full match / repetition of the way? For example:

on the client -

com.example.myProjectOne.model.MyClass

on the server side -

com.example.notMyProject.entity.MyClass

I get -

java.lang.ClassNotFoundException: com.example.myProjectOne.model.MyClass

with the full coincidence of the names of all work packages

public class Server implements Runnable {

private SettingsConnection settingsConnection;
private OnReceiveObject onReceiveObject;
private Serializer serializer;

/**
 * @param remoteServerAddress - address remote server
 * @param inputPort - the port on which the is server
 * @param outputPort - the port which used for send
 * @param password - the password which should to be same on the client side and the server side
 * @param handler - defines the name of the method, which should to be called, after received the data on server side
 */
public Server(String remoteServerAddress, int inputPort, int outputPort, String password, OnReceiveObject handler) {
    settingsConnection = new SettingsConnection();
    settingsConnection.setAddressRemoteServer(remoteServerAddress);
    settingsConnection.setInputPort(inputPort);
    settingsConnection.setOutputPort(outputPort);
    this.onReceiveObject = handler;
    serializer = new Serializer();
    new Thread(this).start();
}

public void sendData(Serializable object, String callBackFunction) {

    Container container = new Container();

    try {
        container.setData(serializer.serialize(object), container.getInitVector()));
        container.setHandler(callBackFunction);
        InetAddress ipAddress = InetAddress.getByName(settingsConnection.getAddressRemoteServer());

        try (Socket socketConnectionToSever = new Socket(ipAddress, settingsConnection.getOutputPort())) {
            OutputStream outputStream = socketConnectionToSever.getOutputStream();
            if (outputStream != null) {
                outputStream.write(serializer.serialize(container));
                outputStream.flush();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

@Override
public void run() {

    final ExecutorService asyncTakesCode = Executors.newCachedThreadPool();

    Runnable threadTaskServer = new Runnable() {
        @Override
        public void run() {
            try {
                ServerSocket serverSocket = new ServerSocket(settingsConnection.getInputPort());
                while (true) {
                    Socket connectionSocketClient = serverSocket.accept();
                    asyncTakesCode.submit(new ThreadTaskClient(connectionSocketClient));
                }
            } catch (IOException e) {
                System.err.println("Unable to process client request");
                e.printStackTrace();
            }
        }
    };

    Thread threadServer = new Thread(threadTaskServer);
    threadServer.start();
}

private class ThreadTaskClient implements Runnable {
    private final Socket connectionSocketClient;

    private ThreadTaskClient(Socket connectionSocketClient) {
        this.connectionSocketClient = connectionSocketClient;
    }

    @Override
    public void run() {

        InputStream inputStream = null;
        try {
            inputStream = connectionSocketClient.getInputStream();
        } catch (IOException e1) {
            e1.printStackTrace();
        }

        try {
            Object o = serializer.deserialize(IOUtils.readFully(inputStream, -1, false));
            if (o instanceof Container) {
                Container container = (Container) o;
                Serializable remoteObject = (Serializable) serializer.deserialize(container.getData()));
                String callBackFunction = container.getHandler();
                onReceiveObject.processRemoteObject(remoteObject, callBackFunction);
            }
        } catch (IOException | ClassNotFoundException e) {
            e.printStackTrace();
        } finally {
            try {
                connectionSocketClient.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

If you're using java's serialization, the classes must match both ends.

Include your class in the server side's classpath.

If you can't do that, you could make it work by effectively creating an alias of your class name for the other class:

package com.example.myProjectOne.model;

public class MyClass extends com.example.notMyProject.entity.MyClass {
}

There are a few caveats of course, for example the would only work if the two classes share the same non-transient instance field names and types.

Yes, you can. You have to extend the default ObjectInputStream and override the resolveClass method (maybe others, not sure).

So, for example:

ObjectInputStream ois = new ObjectInputStream( lis ) {
        protected Class<?> resolveClass(ObjectStreamClass osc) throws IOException, ClassNotFoundException {
            if (osc.getName().contains("some.package.element")) {
                try {
                    Field nameField = osc.getClass().getField("name");
                    nameField.setAccessible(true);
                    nameField.set(osc, osc.getName().replace("some.package.element", "another.package.element"));
                    nameField.setAccessible(false); // hack because "name" is private
                } catch (NoSuchFieldException | IllegalAccessException e) {
                    // ...
                }
            }
            return super.resolveClass(osc);
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM