4 Replies Latest reply on Jan 4, 2006 9:41 AM by tom.elrod

    Serialization/Marshalling problem

    timfox

      I'm obviously doing something wrong but can't work it out, perhaps one of you guys can help me out.

      I am attempting to send an Invocation (actually an org.jboss.aop.joinpoint.MethodInvocation) from client to server using remoting.

      I'm just using Client.invoke to send the response:

      InvocationResponse response = (InvocationResponse)client.invoke(mi, null);
      


      Where mi is the MethodInvocation.

      When the invocation reaches the ServerInvocationHandler - the argument values have been lost, actually the MethodInvocation has the correct number of arguments but the argument values are either null, (if the argument represents an Object not representing a primitive type), or a Long, Boolean etc. initialised with the default value of the corresponding primitive type.

      The MethodInvocation definitely has the correct argument values on the call to Client.invoke.

      I am using the "invocation" data type and InvocationMarshaller/UnMarshsaller, and JavaSerializationManager.

      I'm working from HEAD.

      In order to work around this problem instead of sending the MethodInvocation itself in the call to Client.invoke() I created a simple serializable object which contains the methodHash, argument array, and metadata for the invocation.

      In the ServerInvocationHandler I then create a new MethodInvocation based on the data passed in the simple serializable object.

      When I try this I get the following exception on the client side:

       [junit] 10:53:23,488 ERROR [SocketClientInvoker] Got marshalling exception,
      exiting
       [junit] java.net.SocketException: Software caused connection abort: recv fai
      led
       [junit] at java.net.SocketInputStream.socketRead0(Native Method)
       [junit] at java.net.SocketInputStream.read(SocketInputStream.java:129)
       [junit] at java.io.BufferedInputStream.fill(BufferedInputStream.java:183
      )
       [junit] at java.io.BufferedInputStream.read(BufferedInputStream.java:201
      )
       [junit] at java.io.ObjectInputStream$PeekInputStream.peek(ObjectInputStr
      eam.java:2133)
       [junit] at java.io.ObjectInputStream$BlockDataInputStream.peek(ObjectInp
      utStream.java:2423)
       [junit] at java.io.ObjectInputStream$BlockDataInputStream.peekByte(Objec
      tInputStream.java:2433)
       [junit] at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:
      1245)
       [junit] at java.io.ObjectInputStream.readObject(ObjectInputStream.java:3
      24)
       [junit] at org.jboss.remoting.serialization.impl.java.JavaSerializationM
      anager.receiveObject(JavaSerializationManager.java:102)
       [junit] at org.jboss.remoting.marshal.serializable.SerializableUnMarshal
      ler.read(SerializableUnMarshaller.java:50)
       [junit] at org.jboss.invocation.unified.marshall.InvocationUnMarshaller.
      read(InvocationUnMarshaller.java:48)
       [junit] at org.jboss.remoting.transport.socket.SocketClientInvoker.trans
      port(SocketClientInvoker.java:246)
       [junit] at org.jboss.remoting.RemoteClientInvoker.invoke(RemoteClientInv
      oker.java:112)
       [junit] at org.jboss.remoting.Client.invoke(Client.java:244)
       [junit] at org.jboss.remoting.Client.invoke(Client.java:207)
       [junit] at org.jboss.jms.client.stubs.ClientStubBase.invoke(ClientStubBa
      se.java:100)
       [junit] at org.jboss.jms.client.stubs.ConnectionStub$sendTransaction_N49
      


      and the following exception on the server side:

      10:53:23,473 ERROR [ServerThread] failed
      java.lang.IllegalStateException: unread block data
       at java.io.ObjectInputStream$BlockDataInputStream.setBlockDataMode(ObjectInputStream.java:2261)
       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1305)
       at java.io.ObjectInputStream.defaultReadFields(ObjectInputStream.java:1845)
       at java.io.ObjectInputStream.readSerialData(ObjectInputStream.java:1769)
       at java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:1646)
       at java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1274)
       at java.io.ObjectInputStream.readObject(ObjectInputStream.java:324)
       at org.jboss.remoting.serialization.impl.java.JavaSerializationManager.receiveObject(JavaSerializationManager.j
       at org.jboss.remoting.marshal.serializable.SerializableUnMarshaller.read(SerializableUnMarshaller.java:50)
       at org.jboss.invocation.unified.marshall.InvocationUnMarshaller.read(InvocationUnMarshaller.java:48)
       at org.jboss.remoting.transport.socket.ServerThread.processInvocation(ServerThread.java:268)
       at org.jboss.remoting.transport.socket.ServerThread.dorun(ServerThread.java:330)
       at org.jboss.remoting.transport.socket.ServerThread.run(ServerThread.java:188)
      


      Any ideas?







        • 1. Re: Serialization/Marshalling problem
          timfox

          An update on this:

          Kabir has fixed a problem in the serialization of MethodInvocation objects that was causing the null arguments.

          However, now we still get the "unread block data" exception.

          FWIW on the client side we get the following warning too:

           [junit] 16:00:53,285 WARN [MarshalFactory] Could not find marshaller for da
          ta type 'invocation'. Object in collection is null
          


          I don't know if it is related

          • 2. Re: Serialization/Marshalling problem

            Don't worry about warning. Just saying that could not find marshaller/unmarshaller for 'invocation' type within its local registry (and would have to try loading it, which it should have done).

            I will take a look at the code to see what I can see. You wouldn't happen to have a simple test example that I can run to reproduce?

            • 3. Re: Serialization/Marshalling problem
              timfox

              Looking at the code for MarshalFactory I can see the invocation marshaller/demarshaller isn't one of the default ones.

              I have explictly added the Marshaller/demarshaller to get rid of the warning. I'm not really sure what difference it makes using these marshallers, it seems to work ok without them anyway.

              On the serialization problem, this is me being a dumb arse.

              I was writing more in my writeExternal than I was reading in my readExternal. Hence the exception "unread block data". :)

              • 4. Re: Serialization/Marshalling problem

                You don't have to explicitly add the invoker marshaller programmatically if don't want to. Can just use something like the following configuration:

                 <invoker transport="socket">
                 <attribute name="dataType" isParam="true">invocation</attribute>
                 <attribute name="marshaller" isParam="true">
                 org.jboss.invocation.unified.marshall.InvocationMarshaller
                 </attribute>
                 <attribute name="unmarshaller" isParam="true">
                 org.jboss.invocation.unified.marshall.InvocationUnMarshaller
                 </attribute>
                 </invoker>
                


                This lets remoting know that you want to use the data type 'invocation'. It will try to find it in the statically loaded registry of marshallers/unmarshallers. When it does not find it pre-loaded, it will see the attributes to use to load them on the fly and add to the registry (is where the warning comes in, since it does not find it the first time in the default, pre-loaded registry). I changed the log message to be at info instead of warn, since is acceptable that does not find in the default, pre-loaded registry the first time.