Search code examples
blackberryantjava-meintellij-ideablackberry-simulator

Blackberry Unit testing is throwing an exception when I'm legally persisting an Object


I've been experiencing a problem that's just been driving me up the wall.

Within this blackberry app, I have a class that I'm trying to have persist. It implements net.rim.device.api.util.Persistable. Now for some reason, when I do this:

Persistent Object store = PersistentStore.getPersistentObject(M3Session.ID);

the JVM spases out and complains that class net.rim.device.api.util.Persistable cannot access its superinterface net.rim.vm.Persistable...

I have no idea what I'm doing wrong. the net_rim_api.jar is in my class path as it should be, and I'm building my project using this ant script.

I'm using Intelij 11 Community edition as my IDE if that helps.

This is the class that I'm having persist:

package com.transcel.m3.ir;

/**
 * Created with IntelliJ IDEA.
 * User: Marc Byfield
 * Date: 9/10/12
 * Time: 11:24 PM

 */

import net.rim.device.api.system.Application;
import net.rim.device.api.util.Persistable;
import net.rim.device.api.util.StringUtilities;

import java.util.Date;

public class M3Session implements Persistable {

    private String key;
    private long timeCreated;
    public final static long TIMEOUT = 1200000L;
    static String ApplicaitonID = Application.getApplication().getClass().getName();
    static String STORE_NAME = "session_store";
    public final static long ID = StringUtilities.stringHashToLong(ApplicaitonID + STORE_NAME);


    public String getKey() {
        return key;
    }

    public void setKey(final String key) {
        this.key = key;
        Date newTime = new Date();
        this.timeCreated = newTime.getTime();
    }

    public boolean equals(final Object o) {
        if (this == o) return true;
        if (!(o instanceof M3Session)) return false;

        final M3Session m3Session = (M3Session) o;

        return !(key != null ? !key.equals(m3Session.key) : m3Session.key != null);

    }

    public int hashCode() {
        return key != null ? key.hashCode() : 0;
    }

    public String toString() {
        return "M3Session{" +
                       "key='" + key + '\'' +
                       ", timeCreated=" + timeCreated +
                       '}';
    }

    public boolean isValid() {
        return key.length() != 0 && !hasExpired();

    }

    private boolean hasExpired() {
        Date newTime = new Date();
        return newTime.getTime() - this.timeCreated >= TIMEOUT;
    }

    public M3Session(final String key) {
        this.setKey(key);
    }
}

And this is the class that's using it:

package com.transcel.m3.api;

/**
 * @Author Marc Byfield
 * Date: 9/10/12
 * Time: 11:05 AM
 */

import com.transcel.m3.ir.M3Session;
import com.transcel.m3.ir.User;
import com.transcel.m3.transport.M3Connector;
import com.transcel.m3.transport.Operations;
import net.rim.device.api.system.PersistentObject;
import net.rim.device.api.system.PersistentStore;
import org.json.me.JSONObject;

import java.io.IOException;
import java.util.Hashtable;


public class Authentication implements Runnable {

    private M3Session session;
    private static PersistentObject store;
    private User user;

    public Authentication(String user, String pass) {
        store = PersistentStore.getPersistentObject(M3Session.ID);
        this.user = new User(user, pass);
        session = (M3Session) store.getContents();
        if (session == null || !session.isValid()) {
            login(user, pass);
        }
    }

    public M3Session getSession() {
        return session;
    }


    private void login(String username, String pass) {

        Hashtable user = new Hashtable(2);
        user.put("username", username);
        user.put("password", pass);

        String result;
        try {
            result = M3Connector.sendRequest(Operations.LOGIN, user);
            JSONObject sessionJSON = new JSONObject(result);
            if (sessionJSON.has("session_key")) {
                session = new M3Session(sessionJSON.getString("session_key"));
                synchronized (store) {
                    store.setContents(session);
                    store.commit();
                }
            } else {
                synchronized (store) {
                    store.setContents(null);
                    store.commit();
                }
            }

        } catch (IOException ioe) {
            synchronized (store) {
                store.setContents(null);
                store.commit();
            }
        }
    }


    public void run() {
        if (!session.isValid())
            login(user.getPhoneNum(), user.getPass());
        try {
            wait(M3Session.TIMEOUT);
        } catch (InterruptedException ie) {
            this.login(user.getPhoneNum(), user.getPass());
        }
    }
}

Hope this helps


Solution

  • I'm glad to see someone who is using IDEA and unit testing while BlackBerry development!

    If you look inside net_rim_api.jar you won't find any net.rim.vm.* classes (virtual machine classes, as well you could touch sometime with classes that have native calls inside) that's why you are getting this issue. The working approach that I'm using - faking RIM api by creating own classes that have same contract as RIM classes and pass it test classpath instead of original RIM library. This is quite big overhead but it works. Maybe we could write some tool that doing this in automatic way (will think about it, maybe opensource).

    I should also warn you about Persistable interface. If you ever change that class you will have problems with updates. It's safer to convert data into Hashtable or JSON/XML and store it with Persistable.