6 Replies Latest reply on Aug 29, 2004 11:54 PM by Tom Elrod

    DataOutput vs. ObjectStream for Marshaller interface

    Tom Elrod Master

      In the remoting refactor, will be introducing a Marshaller interface. Would like the main method of this interface to have the following signature:

      public void write(Object dataObject, DataOutput output) throws IOException

      so that the marshaller will marshal the dataObject to the DataOutput. Would like to use DataOutput type since is an interface and allows for a little more freedom if a custom DataOutput implementation is desired.

      The problem is that many implementations of Marshaller will need an OutputStream instead. A simple example would be something like:

      public class SerializableMarshaller implements Marshaller
      {
      public void write(Object dataObject, DataOutput output) throws IOException
      {
      ObjectOutputStream oos = new ObjectOutputStream(output);
      oos.writeObject(dataObject);
      oos.flush();
      }
      }

      Since ObjectOutputStream requires OutputStream, would have to either do a cast if instance of ObjectStream or change parameter type to something like DataOutputStream (in which case, might was well be OutputStream).

      Don't really like either approach, but what I am stuck with due to the weird io package heirarchy.

      Any ideas?

        • 1. Re: DataOutput vs. ObjectStream for Marshaller interface
          Scott Stark Master

          I would say the signature should be:

          public void write(Object dataObject, ObjectOutput output) throws IOException;

          The transport layer providing the stream to the marshalling layer will have to be able to support the additional writeObject(Object obj) method. If a transport has no stream capable of decomposing an Object, then use of this method by a Marshaller would just result in an exception.

          • 2. Re: DataOutput vs. ObjectStream for Marshaller interface
            Tom Elrod Master

            Ok. I agree with:

            public void write(Object dataObject, ObjectOutput output) throws IOException;

            Eventhough I would rather use an interface instead of an abstract class, would still be able to over write all the methods of ObjectOutput for a custom implementation.

            Am not sure what you mean by "support the additional writeObject(Object obj) method". Do you mean to add a method to Marshaller interface like:

            public void write(Object dataObject, ObjectOutput output)

            If so, I don't think this is really a good idea. The reason is that since ObjectOutput has the extra writeObject(Object obj) method, would really be moving the actual marshalling of the obj to the ObjectOutput implementation that is passed to the marshaller, thus making the Marshaller meaningless (could do the same thing without using a Marshaller at all and get same results). Can still acheive streaming using the OutputStream, so will not impact performance.

            • 3. Re: DataOutput vs. ObjectStream for Marshaller interface
              Scott Stark Master

              The java.io.ObjectOutput type is an interface, not an abstract class. The Marshaller interface needs to be:

              pubic interface Marshaller
              {
               public void write(Object dataObject, ObjectOutput output);
              }
              


              so that a marshaller that uses object serialization simply uses output.writeObject. In fact, since the transport layer has an ObjectOutput stream, if there is no Marshaller for the {transport, type} key, it could just default to ObjectOutput.writeObject(). If the transport does not have a valid implementation of this method it would fail and a Marshaller is needed.

              A Marshaller would use ObjectOutput.writeObject it the mapping of the dataObject was to a serializable object. This will be true for non serializable objects when the underlying transport stream supports object serialization.


              • 4. Re: DataOutput vs. ObjectStream for Marshaller interface
                Tom Elrod Master

                My bad. When I said that I agree, meant with

                public void write(Object dataObject, OutputStream output);

                So meant ok with OutputStream, but not ObjectOutput (sorry, will teach me not to post so late at night :)

                I don't want ObjectOutput passed to Marshaller because I don't want it to ever call output.writeObject(dataObject). The reason is this would mean that the transport is now responsible for the marshalling (or at least providing the marshalling mechanism it wants to use via the ObjectOutput). I think there should always be a default Marshaller that can handle marshalling for a transport, even if it is just a SerializableMarshaller which would do like the code I posted earlier.

                Maybe code would help illustrate the problem a little better if used ObjectOutput.

                public class SerializableMarshaller implements Marshaller
                {
                public void write(Object dataObject, ObjectOutput output) throws IOException
                {
                output.writeObject(dataObject);
                output.flush();
                }
                }

                //transport code
                ...
                OutputStream output = socket.getOutputStream();
                ObjectOutputStream oos = new ObjectOutputStream(bufos);
                serializableMarshaller.write(dataObject, oos);


                Is the ObjectOutputStream (oss) in the transport code that is actually doing the marshalling of the dataObject to the socket's OutputStream. Would have just as well not even called serializableMarshaller.write() and moved that code into the transport.

                In the end, is just bytes getting written to the socket's output stream, so to me makes more sense to have these bytes written by the marshaller. Is still possible for the marshaller to stream bytes by just writing a block of bytes at a time as it does the marshalling (which is what ObjectOutputStream does, which is made even more efficient when the stream that it is writing to is a buffered stream).

                Maybe I am missing some critical point here. Please let me know if I am.


                • 5. Re: DataOutput vs. ObjectStream for Marshaller interface
                  Scott Stark Master

                  If your doing java serialization as the wrire format then the transport should be providing an ObjectOutput view of its stream. The addition of the writeObject is a simple extension to the other typed methods provided by the DataOutput interface. I think your getting hung up on the notion of the marshaller. A marshaller does not have to take an object down to a raw byte array. It simply needs to 'write' it to the transport stream. Writing an Object implies letting the java serialization decomposition of the object take over. If the transport layer has a stream that supports this then that should be the source of the ObjectOutput. I still need marshallers to deal with the mapping of non-serializable types like javax.transaction.Transaction.

                  If a transport does not implicitly support the ObjectOuput view, then its a trival wrapper to support the writeObject call using the standard ObjectOutputStream:

                  class ObjectOuputWrapper extends SomeOutputStream
                   implements ObjectOuput
                  {
                   public void writeObject(Object x) throws IOException
                   {
                   ObjectOutputStream oos = new ObjectOutputStream(this);
                   oos.writeObject(x);
                   oos.flush();
                   }
                  }
                  




                  • 6. Re: DataOutput vs. ObjectStream for Marshaller interface
                    Tom Elrod Master

                    Think we are looking at it a little differently, but see now where you are coming from. You are just wanting to have the marshaller be responsible at a high level to ensure all the items within the payload can be marshalled correctly, Transaction for example. I was looking at it from a little lower level where marshaller would be completely responsible for ALL the marshalling down to the bytes.

                    I think either will work equally well in regards to behaviour and performance. Just comes down different view point then. I will update to new signature you suggested.

                    Thanks for you time and input. Is very appreciated.

                    -Tom