Persistent Persistable Objects

Extended RIM JDE API has very powerful feature – Persistent objects. This allows you just to mark any class as “implements Persistable” and be able to hibernate any instance of this class to  internal BB Persistent storage using net.rim.device.api.system.PersistentObject class.

That’s cool, but there are some restrictions. As soon as you modify you class in future program updates including private members changes, all persistent information will be lost. This is because of saved information is no more matching the new class structure.

Not so bad news at first look, but according to the best practice of storing objects (see an article)  we need to group objects into a single collection. And in case of changes in any object that is stored in such collection, all the collection will be invalidated and lost!

So what do do? How to save information between application updates? In my project I decided to implement custom serialization approach using PersistentObject  and collection of predefined types that will not be changed.

Let’s say class Person has 3 properties:

  • String FirstName;
  • String LastName;
  • Integer Age;

As soon as String and Integer are types that not to be changed in future updates we can serialize Person as a Vector of FirstName, LasttName, Age values. I prefer to use Hashtable against Vector, so that we can easily get properties by key but not position. This is important when we do not know how old was version of app that saved this information and we cannot replay on properties indexes.

As soon as Hashtable does not implement Persistable interface I used Custom class PHashtable as a wrapper of Persistable class LongHashtable with custom translation of String keys to long keys using StringUtilities.computeHashCode method.

Then I create a base object EntityBase which every new class should inherit in order to get ability to Persist it’s state. EntityBase has basic methods to Save and Delete itself and an Id property. All objects then will be placed into common PHashtable by their class name and then by their Id. So Id should be unique for every Class scope. One can simplify this mechanism not to use nested PHashtable objects but use complex keys like ClassName + “#” + Id, but I prefer this nesting to be able later get all objects of specific class.

Inheriting the EntityBase class will free us from routine work of implementing common serialization tasks of all classes. The only thing we need now is to implement 2 methods:

  • getProperties
  • setProperties

For our sample class listed above the implementation of these methods is:

public void setProperties(PHashtable properties) {
    super.setProperties(properties);
    FirstName = (String) properties.get("FirstName");
    LastName = (String) properties.get("LastName"); 
    Age = (Integer) properties.get("Age"); 
}
 
public PHashtable getProperties() {
    PHashtable properties = super.getProperties();
    properties.put("FirstName", FirstName);
    properties.put("LastName", LastName);
    properties.put("Age", Age);
 
    return properties;
}

Implementing objects with properties of some other Persistent classes is  less trivial but still simple. Let’s say we want to store information about person’s transport. So now in Person we have additional property Transport of class Car that extends EntityBase. We can use the sam—É Id for this Car object that we use for Person as soon as we require it to be unique only in class scope (Alternatively we can use some other calculated id like Id+”.Transport” or Id+”.Transport1″). And also we need to be sure that as soon as we save our Person to Persistens storage, the information abut it’s transport is also saved. And the same in case of Deleting the object.

So we are to implement 2 more methods:

public void Delete() {
    Transport.Delete();
    super.Delete();
}
 
public void Save() {
    if (Transport != null) Transport.Save();
    super.Save();
}

Also do not forget to load this this property from storage while Person initialization:

public Person(String Id) {
    super(Id, true); 
    Transport = new Car(Id);
}

Heh. That’s all. As soon as new properties are added to the person class or  removed. you do not need to worry. Only ensure that your getProperties method is ready  to receive null while fetching property value.

If need ed you can also save some class version information or other metadata to properties collection to use it for more intelligent version migration mechanism. let’s say that you had CarModel and CarColor stored in Person class and then you moved it to separate property transport of class Car(Model, Color). Then you can ensure to fetch this information in Person’s getProperties method and populate Transport.Model and Transport.Color properties.

You can download see the code of a sample application with EntityBase class implementation and some usage example.

Looking forward to your comments and suggestions.

BlackBerry JDE projects Build & Signing automation

Most projects sooner or later require build process automation. And blackberry JDE projects are not exception. But in case of JDE projects we need two things to automate: build and sign.

Build can be automated in many ways but the basis is to use “rapc.exe” command line tool which comes with JDE and can be located in bin folder. But this tool requires to specify full list of files needed to compile the project and it’s not very handy because somehow we need to get this list from *.jdp file.

Eventually there is a tool that already hadle this: RAPC ant task. You can use it as Ant task in your build automation script but also as a standalone commmand line tool.

I use it in standalone mode because automate builds under TFS using MSBuild. Sample:

Run the following command in the directory where HelloWorld.jdw exists:

java -jar anttask-rapc-1.8.jar -javahome="C:/jdk1.4.0"

-jdehome="C:/Program Files/Research In Motion/BlackBerry JDE 4.3.0" "HelloWorld.jdw"

As you can see this tool does all the dirty job by parsing *.jdw and *.jdp files and successfully compiles *.cod for us.

 

The next step is signing compiled *.cod files.

For a long time this was very difficult to automate becasue SignatureTool.jar tool required to enter validation password manually. One could automate it by automatic UI interaction but that was very unstable.

Using JDE 4.3.0 SignatureTool.jar it is now possible to specify password as a parameter (-p PASSWORD) as well as other parameters to do signing in quiet mode.

You can see Appendix A: Command line code signature requests of BlackBerry Signature Tool Developer Guide (Version 4.3.0)  for the full list of SignatureTool.jar comand line parameters but here’s the syntax to automate signing process:

java -jar "C:/Program Files/Research In Motion/BlackBerry JDE 4.3.0/SignatureTool.jar"

-javahome="C:/jdk1.4.0" -a -c "HelloWorld.cod" -p PASSWORD

Here’s my complete MSBuild project for this automation:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <JavaDir>"C:\Program Files\Java\jdk1.6.0"</JavaDir>
        <JDEDir>C:\Program Files\Research In Motion</JDEDir>
        <ProjectDir>.HelloWorld.jdw</ProjectDir>
        <SigningPassword>SecretWord</SigningPassword>
        <SourceDir>HelloWorld</SourceDir>
    </PropertyGroup>
    <Target Name="Building">
        <Delete Files="$(ProjectDir)/HelloWorld.cod;$(ProjectDir)/HelloWorld.cso" />
        <Exec Command="java -jar lib/anttask-rapc-1.8.jar -alx -javahome=$(JavaDir) -jdehome=&quot;$(JDEDir)\BlackBerry JDE $(Version)&quot; &quot;$(ProjectDir)\HelloWorld.jdw&quot;" />
        <Copy SourceFiles="$(SourceDir)/HelloWorld.cod;$(SourceDir)/HelloWorld.cso" DestinationFiles="..\build\$(Version)\HelloWorld.cod;..\build\$(Version)\HelloWorld.cso" />
        <Exec Command="java -jar &quot;$(JDEDir)\BlackBerry JDE 4.3.0\bin\SignatureTool.jar&quot; -a -c ..\build\$(Version)\HelloWorld.cod -p $(SigningPassword)" />
    </Target>
</Project>

BerryMore blog start

Hi dear all.

I’m going to start this blog to post some useful info that I was able to digg while developing for the Blackberry platform.

This will be more technical oriented site but I’ll also post some info related to user experience in BB world, new devices and software.

Thanks for the interest, and stay with this blog…

image