Blog

How to load objects from an mBaaS storage using Data Retrieval API

by on January 23, 2015

Loading data objects from the Backendless persistent storage is a fundamental operation a large majority of the online/mobile applications require. Backendless Data Retrieval API is simple, yet very powerful. As you will learn in the course of this series, the API provides the following capabilities:

All the features listed above are based on the core data loading API. Consider the example below, but make sure your Backendless backend contains some data. The example in this post (as all the other related posts highlighting the data retrieval features) will use the Restaurant To-Go App schema. You can populate the backend with data using the import feature:

  1. Download the file from the URL below:
    https://backendless.com/documentation/samples/restaraunt-app-tables-with-data.zip
  2. Follow the instructions on how to import schema/data into a Backendless application. You will need to import the file from step above.

The sample code below will be fetching data from the following table:

Additionally, the example below will be using the code generated by Backendless.  To get the code make sure to follow the instructions describing how to generate client-side code based on the backend’s database schema.

    Asynchronous API (applies to Android and plain Java):

    private static void fetchingFirstPageAsync() throws InterruptedException
    {
        long startTime = System.currentTimeMillis();
        final CountDownLatch latch = new CountDownLatch( 1 );
        AsyncCallback<BackendlessCollection<Restaurant>> callback=new AsyncCallback<BackendlessCollection<Restaurant>>()
        {
            @Override
            public void handleResponse( BackendlessCollection<Restaurant> restaurants )
            {
                System.out.println( "Loaded " + restaurants.getCurrentPage().size() + "restaurant objects" );
                System.out.println( "Total restaurants in the Backendless storage - " + restaurants.getTotalObjects() );
                Iterator<Restaurant> iterator=restaurants.getCurrentPage().iterator();
                while( iterator.hasNext() )
                {
                    Restaurant restaurant=iterator.next();
                    System.out.println( "Restaurant name = " + restaurant.getName() );
                }
                latch.countDown();
            }
            @Override
            public void handleFault( BackendlessFault backendlessFault )
            {
            }
        };
        Backendless.Data.of( Restaurant.class ).find( callback );
        latch.await();
        System.out.println( "Total time (ms) - " + (System.currentTimeMillis() - startTime ));
    }

    Synchronous API (Applies only to Java):

    private static void fetchingFirstPage()
    {
        long startTime = System.currentTimeMillis();
        BackendlessCollection<Restaurant> restaurants = Backendless.Data.of(Restaurant.class).find();
        System.out.println( "Loaded " + restaurants.getCurrentPage().size() + "restaurant objects" );
        System.out.println( "Total restaurants in the Backendless storage - " + restaurants.getTotalObjects() );
        Iterator<Restaurant> iterator = restaurants.getCurrentPage().iterator();
        while (iterator.hasNext())
        {
            Restaurant restaurant = iterator.next();
            System.out.println("Restaurant name = " + restaurant.getName());
        }
        System.out.println( "Total time (ms) - " + (System.currentTimeMillis() - startTime ));
    }

    Complete project source code is available in the Backendless GitHub repository.
    Restaurant class:

    #import <Foundation/Foundation.h>
    @class BackendlessUser;
    @class Location;
    @interface Restaurant : NSObject
    @property (nonatomic, strong) NSDate *created;
    @property (nonatomic, strong) NSDate *updated;
    @property (nonatomic, strong) NSString *ownerId;
    @property (nonatomic, strong) NSString *name;
    @property (nonatomic, strong) NSString *objectId;
    @property (nonatomic, strong) NSString *cuisine;
    @property (nonatomic, strong) NSMutableArray *locations;
    @property (nonatomic, strong) BackendlessUser *owner;
    -(void)addToLocations:(Location *)location;
    -(void)removeFromLocations:(Location *)location;
    -(NSMutableArray *)loadLocations;
    -(void)freeLocations;
    @end

    Asynchronous API:

    -(void)fetchingFirstPageAsync {
        NSDate *startTime = [NSDate date];
        [[backendless.persistenceService of:[Restaurant class]] find:[BackendlessDataQuery query]
         response:^(BackendlessCollection *restaurants) {
             NSArray *currentPage =[restaurants getCurrentPage];
             NSLog(@"Loaded %d restaurant objects", [currentPage count]);
             NSLog(@"Total restaurants in the Backendless starage - %@", [restaurants getTotalObjects]);
             for (Restaurant *restuarant in currentPage) {
                 NSLog(@"Restaurant name = %@", restuarant.name);
             }
             NSLog(@"Total time (ms) - %g", 1000*[[NSDate date] timeIntervalSinceDate:startTime]);
         }
         error:^(Fault *fault) {
             NSLog(@"Server reported an error: %@", fault);
         }];
    }

    Synchronous API:

    -(void)fetchingFirstPage {
        @try {
            NSDate *startTime = [NSDate date];
            BackendlessCollection *restaurants = [[backendless.persistenceService of:[Restaurant class]] find:[BackendlessDataQuery query]];
            NSArray *currentPage =[restaurants getCurrentPage];
            NSLog(@"Loaded %d restaurant objects", [currentPage count]);
            NSLog(@"Total restaurants in the Backendless starage - %@", [restaurants getTotalObjects]);
            for (Restaurant *restuarant in currentPage) {
                NSLog(@"Restaurant name = %@", restuarant.name);
            }
            NSLog(@"Total time (ms) - %g", 1000*[[NSDate date] timeIntervalSinceDate:startTime]);
        }
        @catch (Fault *fault) {
            NSLog(@"Server reported an error: %@", fault);
        }
    }

    Complete project source code is available in the Backendless GitHub repository.
    Restaurant class:

    import Foundation
    class Restaurant : NSObject {
        var objectId : String?
        var created : NSDate?
        var updated : NSDate?
        var ownerId : String?
        var name : String?
        var cuisine : String?
        var locations : [Location] = []
        var owner : BackendlessUser?
    }

    Asynchronous API:

        func fetchingFirstPageAsync() {
            print("\n============ Fetching first page using the ASYNC API ============")
            let startTime = NSDate()
            let query = BackendlessDataQuery()
            backendless.persistenceService.of(Restaurant.ofClass()).find(
                query,
                response: { ( restaurants : BackendlessCollection!) -> () in
                    let currentPage = restaurants.getCurrentPage()
                    print("Loaded \(currentPage.count) restaurant objects")
                    print("Total restaurants in the Backendless starage - \(restaurants.totalObjects)")
                    for restaurant in currentPage as! [Restaurant] {
                        print("Restaurant name = \(restaurant.name)")
                    }
                    print("Total time (ms) - \(1000*NSDate().timeIntervalSinceDate(startTime))")
                },
                error: { ( fault : Fault!) -> () in
                    print("Server reported an error: \(fault)")
                }
            )
        }

    Synchronous API:

        func fetchingFirstPage() {
            print("\n============ Fetching first page using the SYNC API ============")
            Types.tryblock({ () -> Void in
                let startTime = NSDate()
                let query = BackendlessDataQuery()
                let restaurants = self.backendless.persistenceService.of(Restaurant.ofClass()).find(query)
                let currentPage = restaurants.getCurrentPage()
                print("Loaded \(currentPage.count) restaurant objects")
                print("Total restaurants in the Backendless starage - \(restaurants.totalObjects)")
                for restaurant in currentPage as! [Restaurant] {
                    print("Restaurant <\(restaurant.ofClass())> name = \(restaurant.name), cuisine = \(restaurant.cuisine)")
                }
                print("Total time (ms) - \(1000*NSDate().timeIntervalSinceDate(startTime))")
                },
                catchblock: { (exception) -> Void in
                    print("Server reported an error: \(exception as! Fault)")
                }
            )
        }

    Asynchronous API:

    var APP_ID = "YOUR-APP-ID";
    var SECRET_KEY = "YOUR-SECRET-KEY";
    var VERSION = "v1";
    function handleResponse(restaurants){
        console.log("Loaded " + restaurants.data.length + "restaurant objects");
        console.log("Total restaurants in the Backendless storage - " + restaurants.totalObjects);
        for(var i = 0; i < restaurants.data.length; i++) {
            console.log("Restaurant name = " + restaurants.data[i].name);
        }
        console.log("Total time (ms) - " + ((new Date()).getMilliseconds() - startTime ));
    }
    function handleFault(backendlessFault){
        console.log( "Server reported an error - ");
        console.log(backendlessFault.message);
        console.log(backendlessFault.statusCode);
    }
    function fetchingFirstPageAsync(){
        try{
            var callback = new Backendless.Async(handleResponse, handleFault);
            Backendless.Persistence.of(Restaurant).find(callback);
        }
        catch(e){
            throw e.message;
        }
        finally{
            console.log("============ Fetching first page using the ASYNC API ============");
        }
    }
    Backendless.initApp( APP_ID, SECRET_KEY, VERSION );
    fetchingFirstPageAsync();
    var startTime = (new Date()).getMilliseconds();
    Synchronous API:
    var APP_ID = "YOUR-APP-ID";
    var SECRET_KEY = "YOUR-SECRET-KEY";
    var VERSION = "v1";
    function fetchingFirstPageAsync(){
        var startTime = (new Date()).getMilliseconds();
        var restaurants = Backendless.Persistence.of(Restaurant).find();
        console.log("============ Fetching first page using the SYNC API ============");
        console.log( "Loaded " + restaurants.data.length + "restaurant objects" );
        console.log( "Total restaurants in the Backendless storage - " + restaurants.totalObjects);
        for(var i = 0; i < restaurants.data.length; i++) {
            console.log("Restaurant name = " + restaurants.data[i].name);
        }
        console.log("Total time (ms) - " + ((new Date()).getMilliseconds() - startTime ));
    }
    Backendless.initApp( APP_ID, SECRET_KEY, VERSION );
    fetchingFirstPageAsync();

    The example demonstrates the usage of the data loading API in its most basic form. The highlighted lines show the actual API. It returns a collection of objects. Notice that the collection is strongly-typed – you do not need to perform any additional unmarshalling of data. Also, the same data object that is saved on the backend is automatically morphed into the client-side type. In other words, the same restaurant object can arrive as a Java POJO to Android/Java application or an Objective-C or Swift object to an iOS app.

    The code produces the following output:

    ============ Fetching first page using the SYNC API ============
    Loaded 4 restaurant objects
    Total restaurants in the Backendless storage - 4
    Restaurant name = Cantina Laredo
    Restaurant name = Buca Di Bepo
    Restaurant name = McDonald's
    Restaurant name = Endless Sweets
    Total time (ms) - 275
    ============ Fetching first page using the ASYNC API ============
    Loaded 4 restaurant objects
    Total restaurants in the Backendless storage - 4
    Restaurant name = Cantina Laredo
    Restaurant name = Buca Di Bepo
    Restaurant name = McDonald's
    Restaurant name = Endless Sweets
    Total time (ms) - 122

    As you can see, the example above prints out the names of the restaurants. The code implies that the results are paged (see the getCurrentPage call).

    Enjoy!