Data Persistence on the Client Side When Using a Structured Mobile Business Object

Use custom coding so that structured mobile business object (MBO) data persists on the BlackBerry device.

By default, data does not persist to the client side when you use an MBO of the structured type because the data resides in the RAM memory. This means that every time you exit the device application or restart the device, the data is lost. Data persistence is useful when you want to preserve the state of data, for example, if you have to exit the mobile application while inputting a long list of data, you would want the data to persist on the file system so that you can continue inputting the data when you restart the application or device.

You can achieve data persistence on the client side by creating a custom coded subclass that implements data Persistence.

The following example uses a local MBO (LocalMyObjectWithSimpletype) to persist the structured MBO data, but you can use a database, file, or something else. The workflow is similar no matter what method you choose to use.

The basic flow for creating data persistence for a structured MBO is:
  1. Create the local MBO (LocalMyObjectWithSimpletype). The mobile application project used in this example contains the GetMyObject MBO with a single operation, insertMyObjectWithSimpleType. Its parameter is a structured type—MyObjectWithSimpleType. So on the device side, to call the operation, a list of MyObjectWithSimpleType type instance needs to be passed as the input parameter. The list is the data that needs to be persisted.
  2. Create a new device application in the Device Application Designer and drag and drop the GetMyObject MBO onto the Flow Design page.
  3. Use the Mobile Business Object References dialog to add the local MBO (LocalMyObjectWithSimpletype) as a Mobile Business Object Reference for the GetMyObject MBO.
  4. In the Device Application Designer preferences for Device > BlackBerry, select the Generate custom subclass for all option. You must restart Sybase Unwired Workspace for this to take effect.

    Another option, since you are customizing only the BOBCUIDefinition, is go to the Device Application Designer properties view, select the Device tab, and set the "Generate a custom coding subclass" platform property to true. This way, a BOBCUIDefinitionCustom.java file is generated as a subclass for the custom coding.

  5. Use the Generate Device Application wizard to generate the device application code.
  6. Locate the generated custom subclass in the generated custom folder, and write the SPMBOModel subclass that provides the persist implementation, as shown in this example:
    class CustomSPMBOModel extends SPMBOModel
    {    
        public CustomSPMBOModel(String id) 
        {
            super(id);
        }
        
        /**
         * Override to provide persistent function, in this case, 
         * we use client only mbo to persist the data. 
         * User can also use their own persist mechanism.
         * @return <description>
         */
        protected Vector readPersistentData()
        {
            ObjectList persistData = 
                      LocalMyObjectWithSimpletype.findAll();
            if(persistData!=null&&persistData.size()>0)
            {
                ObjectList data = new ObjectList();
                int size = persistData.size();
                for(int i = 0; i<size; i++)
                {
                    LocalMyObjectWithSimpletype persistObj = 
                   (LocalMyObjectWithSimpletype)persistData.
                                                  elementAt(i);
                    MyObjectWithSimpletype obj = 
                                      new MyObjectWithSimpletype();
                    data.addElement(obj);
                    obj.setBooleanType(persistObj.getBooleanType());
                    obj.setDecimalType(persistObj.getDecimalType());
                    obj.setDoubleType(persistObj.getDoubleType());
                    obj.setFloatType(persistObj.getFloatType());
                    obj.setIntType(persistObj.getIntType());
                    obj.setStringType(persistObj.getStringType());
                }
                return data;
            }
            return null;
        }
        
        /**
         * Persist the structure mbo data to a local MBO
         * @return <description>
         */
        protected void doPersist(Object mbo, String operationName)
        {
            if(operationName.equals(CREATE_OP))
            {
                MyObjectWithSimpletype rawObj = 
                                   (MyObjectWithSimpletype)mbo;
                LocalMyObjectWithSimpletype persistObj = 
                                   new LocalMyObjectWithSimpletype();
                persistObj.setBooleanType(rawObj.getBooleanType());
                persistObj.setDecimalType(rawObj.getDecimalType());
                persistObj.setDoubleType(rawObj.getDoubleType());
                persistObj.setFloatType(rawObj.getFloatType());
                persistObj.setIntType(rawObj.getIntType());
                persistObj.setStringType(rawObj.getStringType());
                persistObj.create();
            }
            else if(operationName.equals(DELETE_OP))
            {
                MyObjectWithSimpletype rawObj = 
                                   (MyObjectWithSimpletype)mbo;
                LocalMyObjectWithSimpletype persistObj = 
                                   findPersistObj(rawObj);
                if(persistObj!=null)
                {
                    ((LocalMyObjectWithSimpletype)persistObj).delete();
                }
            }
            else if(operationName.equals(UPDATE_OP))
            {
                MyObjectWithSimpletype rawObj = 
                                   (MyObjectWithSimpletype)mbo;
                LocalMyObjectWithSimpletype persistObj = 
                                   findPersistObj(rawObj);
                if(persistObj!=null)
                {
                    persistObj.setBooleanType(rawObj.getBooleanType());
                    persistObj.setDecimalType(rawObj.getDecimalType());
                    persistObj.setDoubleType(rawObj.getDoubleType());
                    persistObj.setFloatType(rawObj.getFloatType());
                    persistObj.setIntType(rawObj.getIntType());
                    persistObj.setStringType(rawObj.getStringType());
                    persistObj.update();
                }
            }
        }
        
        private LocalMyObjectWithSimpletype findPersistObj
        (MyObjectWithSimpletype rawObj)
        {
             Query q = new Query();
             CompositeTest ct = new CompositeTest();
             ct.setCompositionType(CompositeTest.AND);
             ct.add(
                 new AttributeTest(
                      "IntType",
                      rawObj.getIntType().toString(),
                      AttributeTest.EQUAL));
             ct.add(
                 new AttributeTest(
                     "BooleanType",
                     rawObj.getBooleanType().toString(),
                     AttributeTest.EQUAL));
             ct.add(
                 new AttributeTest(
                     "DecimalType",
                     rawObj.getDecimalType().toString(),
                     AttributeTest.EQUAL));
             ct.add(
                 new AttributeTest(
                  "DoubleType",
                  rawObj.getDoubleType().toString(),
                  AttributeTest.EQUAL));
             ct.add(
               new AttributeTest(
                 "FloatType",
                 rawObj.getFloatType().toString(),
                 AttributeTest.EQUAL));
             ct.add(
               new AttributeTest(
                 "StringType",
                 rawObj.getStringType().toString(),
                 AttributeTest.EQUAL));
             q.setTestCriteria(ct);
                
             ObjectList result = 
                    LocalMyObjectWithSimpletype.findWithQuery(q);
             if(result!=null&&result.size()>0)
             {
                 return (LocalMyObjectWithSimpletype)result.
                                                   elementAt(0);
             }
             return null;
        }
    }
    
    
    
    
    
  7. Register the subclass to the MBOModelFactory to replace the default SPMBOModel. You can do this by overriding the super init() function in the BOBCUIDefinitionCustom class, as shown in this example:
    public class BOBCUIDefinitionCustom extends BOBCUIDefinition
    {
        // customize BOBCUIDefinition
        
        public void init()
        {
            super.init(); 
            MBOModelFactory.getInstance().regMBOModel(
                MBO_PERSISTSAMPLE_MYOBJECTWITHSIMPLETYPE,
                new CustomSPMBOModel(
                    MBO_PERSISTSAMPLE_MYOBJECTWITHSIMPLETYPE));
        }
    }

    The constant MBO_PERSISTSAMPLE_MYOBJECTWITHSIMPLETYPE is the MBO ID defined for MyObjectWithSimpleType, and you can find it in the super class BOBCUIDefinition.

  8. Regenerate the device application and launch the application.