2 Replies Latest reply on May 28, 2010 8:50 PM by Andrew Rubinger

    Wire Protocol for Archive Serialization

    Andrew Rubinger Master

      Use Case:  Send an Archive<?> over a network or serialize to disk.

       

      I had a look and wanted to note some thoughts.

       

      At first glance, we think of the process being:

       

      1. Export as ZIP
      2. Write to Stream
      3. Import from ZIP

       

      This may fine for archive contents, however Archive<?>s have more internal state than simply the payload.  Archives have a name, an associated Domain/Configuration/ServiceLoader/ClassLoader etc.

       

      Also we should make the Serialization protocol of the contents more configurable than simply ZIP.  Perhaps in CPU-bound environments the user would like to write uncompressed bytes.  Or maybe if going over a network they'd like a more compact BZIP.

       

      Simply marking everything as Serializable doesn't really cut it either.  The deal with wire compatibility is that it must be consistent between patch and minor releases, and changes to the structure of the implementation classes make the default form brittle.  It's easy to keep binary (API) compatibility but fail the serialization contract.

       

      Some questions:

       

      1. Do we bother sending along the archive's Configuration?  If not, we can assign it ShrinkWrap.getDefaultDomain().getConfiguration() upon deserialization.  If so, we need to make the Domain and all other types in the graph Serializable with back-compat protocol as well.
      2. If we *do* send along the domain, some configurable elements may no longer be available.  For instance JVM1's classpath may have user-defined extension types available which are not present on JVM2.
      3. How do we handle the nestedArchives Map in MemoryMapArchiveBase ?  I think we recurse into them in order to write these out.

       

      Other observations:

       

      • We don't need to make ArchivePath Serializable.  This is essentially a wrapper around String which provides some convenience, so we should just send the String and make a new ArchivePath from it on the other end.
      • I don't much relish the idea of sending along an Archive with Configuration that isn't present in any Domain within the remote (receiving) JVM.

       

      As a general rule, the fewer types we make Serializable, the easier maintenance becomes.  The trick is for us to find a consistent way of sending all state over the wire in some contracted form, then reading it back into the proper types.

       

      S,

      ALR

        • 1. Re: Wire Protocol for Archive Serialization
          Andrew Rubinger Master

          Thought out loud a bit with our resident marshalling lead:

           

          (06:11:59 PM) ALR@Freenode: dmlloyd: If you'd like to ensure my understanding of the complexities of serialization are complete, I'd appreciate it: http://community.jboss.org/thread/152542
          (06:13:33 PM) dmlloyd: what's the use case for making Archive serializable?
          (06:14:07 PM) ALR@Freenode: Remote deployment
          (06:14:18 PM) dmlloyd: so an Archive isn't really an archive
          (06:14:33 PM) ALR@Freenode: It's a VFS
          (06:14:34 PM) dmlloyd: it's a complete platform independent deployment description
          (06:14:40 PM) dmlloyd: == too big of a cookie
          (06:14:48 PM) dmlloyd: you will get a tummyache
          (06:15:05 PM) ALR@Freenode: I think the tummyache is lessened if I don't send along its associated configuration.
          (06:15:20 PM) dmlloyd: if an archive *is* just an archive then you should just treat it as one - have a way to write it as a zip and read it as a zip.
          (06:15:24 PM) ALR@Freenode: The configuration stuff is for things like "what ExecutorService do I use for exporting" etc
          (06:15:52 PM) ALR@Freenode: dmlloyd: I have that.  The only other state besides content and configuration is "name".
          (06:15:56 PM) ALR@Freenode: Which is easy enough.
          (06:16:05 PM) ***dmlloyd nods
          (06:16:05 PM) ALR@Freenode: I could send the name and the contents and be done with it.
          (06:16:28 PM) dmlloyd: that seems adequately unambitious
          (06:16:47 PM) ALR@Freenode: dmlloyd: You think it's acceptable to lose the state of the Configuration if it's noted in the JavaDocs in the Serialization section?
          (06:17:15 PM) dmlloyd: yeah - well, mixing configuration with the archive is possibly a red flag of mixed concerns
          (06:17:26 PM) ALR@Freenode: dmlloyd: Kinda need it.
          (06:17:58 PM) dmlloyd: archive being a data view of what's being deployed, configuration being a mutable program of how it's deployed
          (06:18:12 PM) ALR@Freenode: Configuration and deployment aren't really related.
          (06:18:22 PM) ALR@Freenode: Configuration right now is mostly for the ExecutorService used to export.
          (06:18:56 PM) dmlloyd: once you have links to stuff like ExecutorService (which doesn't have a sane serialized equivalent) that's the indication right there
          (06:19:00 PM) ALR@Freenode: Arguably that could be part of the exporter.
          (06:19:22 PM) ALR@Freenode: But the API for export is a wrapper around the archive, so they get linked.
          (06:19:34 PM) ALR@Freenode: archive.as(ZipExporter.class).exportZip();
          (06:19:42 PM) dmlloyd: probably having a serialized view of the archive isn't the best way to accomplish remote deployment
          (06:19:47 PM) ALR@Freenode: I might need to think on this more.
          (06:20:00 PM) ALR@Freenode: dmlloyd: The other way to accomplish it is:
          (06:20:00 PM) dmlloyd: maybe better to have a RemoteDeployment serializable thing which contains the archive bytes
          (06:20:08 PM) ALR@Freenode: 2 arguments:
          (06:20:10 PM) ALR@Freenode: ZIP and name.
          (06:20:13 PM) dmlloyd: sure
          (06:20:45 PM) ALR@Freenode: Hmm.  archive.as(Serializable.class)
          (06:21:02 PM) ALR@Freenode: RemoteDeploymentWrapper implements Serializable


          S,

          ALR

          • 2. Re: Wire Protocol for Archive Serialization
            Andrew Rubinger Master

            https://jira.jboss.org/browse/SHRINKWRAP-178

             

            We'll leave configuration/domain etc out of scope.  The true use case is simply to support remote deployment, which only requires a name and contents.  This keeps our wire protocol thin.

             

            Usage:

             

            final String name = "serializedArchive.jar";
            final ZipSerializable archive = ShrinkWrap.create(JavaArchive.class, name).addClass(SerializationTestCase.class).as(
                  ZipSerializable.class);
            final ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            final ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(archive);
            out.flush();
            out.close();
            final ObjectInputStream in = new ObjectInputStream(new ByteArrayInputStream(byteOut.toByteArray()));
            final ZipSerializable roundtrip = (ZipSerializable) in.readObject();

             

            S,

            ALR