ossgang / ossgang-commons

Apache License 2.0
4 stars 0 forks source link

Files I/O serialization API #45

Open andreacalia opened 4 years ago

andreacalia commented 4 years ago

Often in our tests we want to create serialized version of some inputs or results of a real call to test/mock (e.g. LSA optics or settings). Dealing with standard serialization Java API for file reading is very cumbersome and prone to errors... we could have a simple and flexible API for the easy cases (write and read from classpath).

Another open question is if we can (or should) get around the fact that every object needs to extend Serializable. Probably is a good idea to keep it but to be discussed :slightly_smiling_face:

As a starting point I paste here some code extracted from my latest attempt. To be improved (and re-designed) a lot !

private static void writeObject(Object inputData, String path) {
        boolean wasCreated = false;
        Path filePath = null;
        for (String prefix : Arrays.asList("src/test", "accsoft-steering/src/test")) {
            LOGGER.info("Creating file {}/{} ...", prefix, path);
            filePath = Paths.get(prefix, path);
            try (FileOutputStream fileOutputStream = new FileOutputStream(filePath.toFile());
                 ObjectOutputStream objectOutputStream = new ObjectOutputStream(fileOutputStream)) {
                objectOutputStream.writeObject(inputData);
                objectOutputStream.flush();
                wasCreated = true;
                LOGGER.info("... success!");
                break;
            } catch (FileNotFoundException e) {
                LOGGER.error("Cannot create {}/{}: {}", prefix, path, e.getMessage(), e);
            } catch (Exception e) {
                LOGGER.error("Error writing to {}/{}: {}", prefix, path, e.getMessage(), e);
            }
        }
        if (!wasCreated) {
            LOGGER.error("Could not create file {}", path);
            System.exit(-1);
        }

        LOGGER.info("Checking created file is ok");

        try (FileInputStream fileInputStream = new FileInputStream(filePath.toFile());
             ObjectInputStream objectInputStream = new ObjectInputStream(fileInputStream)) {
            Object serializedData = objectInputStream.readObject();

            if (inputData.equals(serializedData)) {
                LOGGER.info("File content are ok!");
            } else {
                LOGGER.error("File content is not equal to the source!\nSource:\n{}\nSerialized:\n{}", inputData, serializedData);
                System.exit(-3);
            }
        } catch (Exception e) {
            LOGGER.error("Cannot verify if the created file is ok: {}", e.getMessage(), e);
            System.exit(-2);
        }
    }
    private static <T> T readObject(String path) {
        try {
            InputStream inputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(path);
            ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
            return (T) objectInputStream.readObject();
        } catch (Exception e) {
            throw new RuntimeException("Cannot read file " + path, e);
        }
    }
michi42 commented 4 years ago

I fully agree that the Java API is cumbersome ... but I'm wondering, should we use this for anything else than tests - and even there? Sure, Java serialization is convenient, but as far as I know it is discouraged to use it for persistent storage, because it is not guaranteed that future versions will be backwards compatible (and changes to the objects serialized break it as well). Also, it is a very opaque binary file format, so it is not easy to tell what is in such a file, and Git may not do well with it :-)

So I'm wondering ... shouldn't we rather try to use gson to serialize pure "data" objects, when possible? Sure that's more work initially, but wouldn't it be more maintainable on the longer term? (Maybe we could create another project, like ossgang-testing, which would depend e.g. on gson and could use either gson or Java Serialization through a common API?)

Happy Easter!