views:

713

answers:

4

Is it possible to serialize an object into a string or a byte array using either the J2ME or BlackBerry APIs?

Thanks.

+1  A: 

Java ME, unfortunately, doesn't have any built-in APIs for serialization, so you'll have to invent something yourself.

Malcolm
Understood, thanks.
DanG
+1  A: 

If your goal is to serialize an object or object graph for persisting to flash memory, you can use the PersistentStore class. Many of the native object types such as Boolean, Byte, Character, Integer, Long, Object, Short, String, Vector, Hashtable are implicitly persistable.

Marc Novakowski
But how do I encrypt that data?
DanG
Are you trying to serialize for local persistence? If so, you can protect access to data stored in the BlackBerry PersistentStore. Or do you have some other use case where you actually need a byte array?
octo
I'm trying to serialize for local persistence. I'm aware of protecting access to the data stored in PersistentStore, but I'm writing a medical app and must use encryption. Do you have any ideas how to elegantly implement this?
DanG
For encryption of sensitive data within your object, you could use the AESEncryptorEngine and AESDecryptorEngine classes.
Marc Novakowski
Understood, is it possible to encrypt the data without encrypting/decrypting the object fields individually?
DanG
I don't think so - it's possible that the protected access mode on the Persistent Store encrypts the data automatically, but none of the RIM documentation I have seen says for sure.
Marc Novakowski
A technical guy over at RIM confirmed that Protected Access does not encrypt anything. Thanks.
DanG
+1  A: 

You are stuck with creating your own serialization process for your classes. It wouldn't be too difficult to create your own base class and then use somesort of reflection to automatically serialize your properties.

    ByteArrayOutputStream baos = new ByteArrayOutputStream();

    DataOutputStream outputStream = new DataOutputStream(baos);
    try {
        // serialize your object - 
        outputStream.writeInt(this.name);
        // Then push the player name.
        outputStream.writeUTF(this.timestamp);
    }
    catch (IOException ioe) {
        System.out.println(ioe);
        ioe.printStackTrace();
    }


// Extract the byte array
byte[] b = baos.toByteArray();
yamspog
Except J2ME doesn't support reflection.
Marc Novakowski
I like your idea of using DataOutputStream though, even if you couldn't do it automatically via reflection.
Marc Novakowski
+2  A: 

The way I handle the object serialization case is by implementing my own infrastructure for handling everything. You don't have reflection in this API, but you do have "Class.forName()" which is better than nothing. So here's what I do...

First, this is the interface that I have every serializable object implement:

public interface Serializable {
    void serialize(DataOutput output) throws IOException;
    void deserialize(DataInput input) throws IOException;
}

The serialize() method writes the object's fields to the DataOutput instance, while the deserialize() method sets the object's fields from the DataInput instance. (these are both plain top-level interfaces used by the data-oriented I/O streams, which allows me to have more flexibility) Also, any class implementing this interface needs to have a default no-arguments constructor. Of course if you want your serialized class to be robust against change, you may want to choose your underlying data formats accordingly. (for example, I implemented a serializable hashtable as an underlying container to handle these cases)

Now, to actually serialize a class implementing this interface, I have a method that looks something like this:

public static byte[] serializeClass(Serializable input) {
    ByteArrayOutputStream buffer = new ByteArrayOutputStream();
    DataOutputStream output = new DataOutputStream(buffer);
    try {
        output.writeUTF(input.getClass().getName());
        input.serialize(output);
    } catch (IOException ex) {
        // do nothing
    }
    return buffer.toByteArray();
}

And to deserialize:

public static Serializable deserializeClass(byte[] data) {
    DataInputStream input = new DataInputStream(new ByteArrayInputStream(data));
    Object deserializedObject;
    Serializable result = null;
    try {
        String classType = input.readUTF();
        deserializedObject = Class.forName(classType).newInstance();
        if(deserializedObject instanceof Serializable) {
            result = (Serializable)deserializedObject;
            result.deserialize(input);
        }
    } catch (IOException ex) {
        result = null;
    } catch (ClassNotFoundException ex) {
        result = null;
    } catch (InstantiationException ex) {
        result = null;
    } catch (IllegalAccessException ex) {
        result = null;
    }
    return result;
}
octo
Thanks. Do you have a fully working class file I could see?Also, do you know if its possible to use the JSR172 routines for webservices to generate all of this information? (I'm using webservices to pass the data to/from the server and storing the objects via PS as well).
DanG
All the code for a far more complex version of this is available here:http://logicmail.sf.net/Just dig through the SVN browser to "org/logicprobe/LogicMail/". The "util" package has the infrastructure code, and the "conf" package has some classes I've implemented this on. I've hand-coded all of it, starting with RMS and moving to PS, so I can't speak for code generation. But I handle all manner of data types.
octo
Thanks, there is some really good stuff in there. You've done A LOT of BB development.
DanG