This forum has been archived. Please start a new discussion on GitHub.

Dynamic Ice: Using serialised Ice 3.4.2 data in Ice 3.5.0

Hello all,

I have a lot of stored data from an IceStorm-using system where I serialised all of the published messages using Base64 by subscribing a "Blobject" to each IceStorm topic with the following body:
public boolean ice_invoke (byte[] inParams, ByteSeqHolder outParams, Current current) {
        logger.trace (current.operation, DatatypeConverter.printBase64Binary (inParams));
        return true;

So what I now have is lots of log files from a recent experiment, all full of tuples of the form: (topic name, op name, Base64-encoded). I now need to re-publish all of that recorded IceStorm data back through the system.

Unfortunately, I've since upgraded my desktop machine to Ice 3.5, and I note in the Ice 3.5 release notes that there's a specific warning about dynamic Ice: namely, that the parameters are now "Ice Encapsulations". And indeed, when I try to do something like the following, I get an Ice.EncapsulationException:
publisher.ice_invoke(opName, Ice.OperationMode.Normal, DatatypeConverter.parseBase64Binary(str), null);

Is there any easy way to convert those Ice 3.4.2 bytes into an Ice 3.5.0 encapsulation? As an alternative, I can downgrade my desktop to Ice 3.4.2, but I'd rather not do that unless I have to.

Thanks for any suggestions,



  • p.s. -- I just did a small test, and it did work to explicitly unserialise the bytes using the appropriate stream helper class and then to use Ice.OutputStream to create a new encapsulation for use in the ice_invoke. But I'm not excited about doing that manually for every argument of every message that was published; that's what I'd hoped to avoid by saving each message as bytes in the first place. (And if I'm going to deserialise, I might as well just publish everything in the normal way in any case ...)
  • benoit
    benoit Rennes, France

    You just need to wrap your data within an encapsulation. An encapsulation contains the encoding version (1.0 for you, encoded on 2 bytes), the size of the data (encoded on 4 bytes, little endian) and the data. So something like the following should do the job:
    // C# 
    byte[] data = DatatypeConverter.parseBase64Binary(str);
    byte[] encaps = new byte[data.Length + 6];
    encaps[0] = 0x01;
    encaps[1] = 0x00;
    byte[] sz = BitConverter.getBytes(data.Length + 6);
        encaps[2] = sz[0];
        encaps[3] = sz[1];
        encaps[4] = sz[2];
        encaps[5] = sz[3];
        encaps[2] = sz[3];
        encaps[3] = sz[2];
        encaps[4] = sz[1];
        encaps[5] = sz[0];
    System.Buffer.BlockCopy(data, 0, encaps, 6, data.Length);
    publisher.ice_invoke(opName, Ice.OperationMode.Normal, encaps, null);

  • Thanks for the help! I had to modify the sample a bit -- it seems that the size is actually the first four bytes, and then the encoding is the next two? Anyway, here's my current Java implementation, which is now working great.
    byte[] bytes = DatatypeConverter.parseBase64Binary(str);
    byte[] encapsBytes = new byte[bytes.length + 6];
    // First four bytes: size
    ByteBuffer bb = ByteBuffer.allocate(4);
    System.arraycopy(bb.array(), 0, encapsBytes, 0, 4);
    // Next two bytes: encoding version (1.0)
    encapsBytes[4] = 0x01;
    encapsBytes[5] = 0x00;
    // Finally, the data
    System.arraycopy(bytes, 0, encapsBytes, 6, bytes.length);
    if (publisher != null) {
        publisher.ice_invoke(opName, Ice.OperationMode.Normal, encapsBytes, null);
    Thanks again,

  • benoit
    benoit Rennes, France

    Yes of course, the size is encoded first (as documented here), sorry for this oversight. I'm glad to hear it's working now.