Page 1 of 612345...Last »

Getting Started with Custom Business Logic (mBaaS server code)

The goal of this post is to let you quickly become familiar with Backendless custom business logic feature. At the end of the instructions provided below you will have a Backendless application with a custom API event handler published into production – that is running on our servers.

Using Code Generator

  1. Login to Backendless console and create a new application called OrderManagement. You can use an existing application, however this guide assumes that certain data tables are created, which may conflict in an existing app. Use caution if you decide to use an existing app.
  2. Click the Data icon to navigate to the Data/Schema browser section of the console:
  3.  Click the “plus” icon in the lower left corner of the screen to add a new table. The reason a table should be created first is because one of the next steps will be registering an event handler for this table. Name the table “Order”.
  4. Click Save to create the table. Select “Yes” in the popup to modify the table schema. Click “Add Column” and enter “customername” in the “Name” field as shown below:
  5.  Click Save to add the column.
  6. Click the Business Logic icon to navigate to the custom business logic section:
  7.  The Business Logic section contains three tabs: Code Generation, Debug and Production. Each tab represents a state of the code and displays a “model” of the code available in the corresponding state. A modelis a collection of event handlers and timers.
    • Code Generation – a state containing a model created by the developer and lists the event handlers and timers for which the code should be generated.
    • Debug – displays a model recognized by coderunner, a special utility used for local debugging of custom business logic.
    • Production – contains a model deployed into the backend for production purposes. This is the currently active model in the application.
  8. While in the “Code Generation” tab, click the Data Tables event handler category as shown in the image above then click the “Add Event Handler” button.
  9. In the “New Data Event Handler” popup, select the “Order” table in the Context drop down:
  10. Click “Save” to create the handler. The system adds a new handler to the code generation model and automatically creates the place holder source code reflecting the event handler. Additionally, the code generator automatically creates the code which represents the records of the referenced table(s) as Java classes. For instance, for the “Order” table, the generated code includes Order.java which is referenced in the event handler methods:
  11. Click the “Download Code” button located under the source code tree. Backendless generates a zip file with the same name as the name of the application.

Customizing and Running Code

  1. At this point the generated file contains a complete project with all the necessary dependencies and source code which can be easily modified. Expand the zip file and open the project in IDEA or Eclipse.
  2. Download Backendless CodeRunner for Java unzip the file into a directory. The directory where you unzip the file will be further referenced as [backendless-coderunner-home] in this guide. The CodeRunner SDK distribution has the following structure:where:
      • /bin – contains utilities for debugging and deploying custom code.
      • /classes – directory which СodeRunner uses by default when it looks for custom business logic code to debug or deploy.
      • /libs – contains a Java library which must be imported when developing custom business logic. The library is automatically included into the project when using code generator. Additionally, any JAR dependencies for the code in /classes should be placed into this directory.
  3.  Return to the IDE and configure the output directory for the compiled code to be [backendless-coderunner-home]/classes.
  4. Open OrderTableEventHandler.java and modify as shown below (adding two lines of code into the beforeCreate method):
  5. Compile the code and make sure [backendless-coderunner-home]/classes contains the following directory structure:
  6.  Return to Backendless Console and switch to the Manage > App Settings section. At the very top of the section where it shows Application ID and secret keys, you will find “Code Runner Secret Key”. The key must be used for debugging custom code locally. The CodeRunner secret key uniquely identifies your backend application and is used to link CodeRunner from your local environment with Backendless. Copy the secret key into clipboard using the Copy button.
  7. Open a command prompt window and change the current directory to  [backendless-coderunner-home]/bin
  8. Run the CodeRunner script with the secret key obtained in step 6 as the script’s argument. For instance, on a Linux system, the command to run coderunner is:
  9. Once coderunner starts, it should produce the following output:
  10. At this point CodeRunner is connected to Backendless and the code is ready for local debugging. Return to Backendless Console. The Debug tab shows the events which are available in the debug model:
  11.  To test the code you must issue an API request to store an object in the Order table. You could write a client application using any programming language of your choice:
    Java – Create object using Backendless SDK for Java
    Objective-C – Create object using Backendless SDK for iOS
    JavaScript – Create object using Backendless SDK for JavaScript
    ActionScript – Create object using Backendless SDK for Flex/AIR
    C#/VB – Create object using Backendless SDK for .NETor with REST – Create object using REST API
  12. This guide uses the REST API to create an API request to store an object. The REST request with the curl utility is:

    The APP-ID and REST-SECRET-KEY values must be obtained from the Manage > App Settings screen in Backendless Console:
  13. Run the curl command in a separate command prompt window. Once the API call completes, notice the following output in the coderunner window. The output comes from the custom code you developed:
  14. To make sure the custom code has executed properly, return to Backendless Console and switch back to Data section. Select the Order table and check the object stored in the table:

Local Debugging

  1. Now that you confirmed that the custom code is plugged into the API invocation chain, it is important to establish a connection between the coderunner process and the IDE debugger. CodeRunner is automatically configured to accept remote debugging connections on port 5005. To connect to the process, use the remote debugging facility in the IDE. For example, in IntelliJ IDEA, select “Run” from the main menu and then select “Edit Configurations”. Click the “plus” icon to add a new configuration. Select “Remote” from the list and enter “ordermanagement” into the name field as shown below:
  2. Click OK and launch the debugger. Once the debugger is attached to the coderunner process, you can establish breakpoints in the code and re-run the client application. Usually debugging takes more time than the duration of the timeout on the client-side. You should expect that the client application (or even the curl request) will receive a timeout, but you should still be able to continue the debugging of your custom code.

Deploying Code to Production

Deploying code to production can be done using the deploy.sh utility available in the [backendless-coderunner-home]/bin directory. To run the deployment script, it is necessary to use CodeRunner secret key – the same key used for the debugging purposes:

  1. Navigate to the Manage > App Settings screen in Backendless Console and copy the CodeRunner Secret Key.
  2. In a command prompt window change the current directory to [backendless-coderunner-home]/bin.
  3. Run the following command:

    where XXXX-XXXX-XXXX-XXXX is the CodeRunner secret key.
  4. Once the deployment script runs, it should produce the following output:

  5.  Once the code is deployed to production, it is immediately plugged into your application. You can verify the production deployment in Backendless Console. Open the Business Logic section and click the Production tab. Since the deployment in this guide includes only one event handler for the Data Service, you will see it in the “Data Tables” category:
  6. An event handler running in production can be disabled by clicking the checkbox in the “Enable” column.

This concludes the Quick Start. You can try repeating the process for other event handler or timers. If you run into any problems or have any questions, do not hesitate contacting us at http://support.backendless.com.

Backendless is out of Beta with a ton of new features – custom business logic, code generation, validators, etc.

It feels amazing to begin writing this post. I have been waiting for a long time to say it and I finally can – Backendless goes out of Beta! And boy, aren’t we doing it with quite a bang. Over the weekend we pushed a new release with a ton of fixes and some amazing functionality. It took us quite a while to get to this point, but I am quite sure the wait was worth it. The new release includes support for custom business logic, code generation, data validators, multi-environment (dev, test, stage, prod) support and many more. Please see below for details:

Server-side Data Validators

As the name suggests, this feature can validate values in the data and user objects entering the Backendless system. As objects/users are created or updated, Backendless can automatically verify and validate the properties and return an error if the validation fails. You can configure validators using Backendless Console. For example, the image below shows the User Properties screen. Each user property can be configured with a built-in or custom validator. A custom validator is a regular expression entered by the application developer:

Similarly, validators can be assigned to data table columns. To configure a data validator select a table in the Data section of the console, then click the “Table Schema and Permissions” button. All columns (except for relations) include the Validator column as shown below:

Localization

Backendless Console is now available in 9 languages: English, Spanish, Portuguese, Italian, French, Japanese, Korean, Russian and Chinese. Language is selected automatically based on the user’s locale or defaults to English if a translation is not available:

Code Generation

Backendless’ mission is to simplify, optimize and speed up software development process. What could do it better than automatic code generation? Our console now includes the Code Generation section which makes it trivially easy to start working on a backendless app. Currently we support code generation for Android, iOS and JavaScript, but the list of frameworks and client-types we will support will be growing. What does the generated code do? Take a look at the screenshot below. It is a screenshot for the Android code generator built-into Backendless Console:

For each feature selected in the code generation screen Backendless creates a project with the source code and all required dependencies. You can run the project without any changes at all. The code generated for “Registration and Login” creates a registration form based on the user properties defined in the application. For Data Management, the code is a class library which can be used to build data-driven apps on top of Backendless. There is also a cool CRUD (Create, Retrieve, Update, Delete) demo project which demonstrates how to use the generated code for all Data Service API calls.

Custom Business Logic

This is big, bold and beautiful. Yes, now you can override Backendless services with you own custom application logic on the server side. The programming language in which you would need to developer custom logic is Java, and we are working on adding JavaScript, C#/VB, PHP, Python and Ruby to the list. There are two types of code blocks you can implement – service handlers and timers. A service handler plugs into API processing chain and for every single API call, you can inject a “before” and “after” handler. A timer is a program, which Backendless runs accordingly to a schedule you define. To make it easier to develop custom business logic we also built a specialized code generator. Using the code generator, a developer can focus entirely on what’s important – adding business logic. One of the most amazing features is we support local debugging. Once you complete the implementation of your Backendless event handler or timer, it can be debugged on the developer’s computer with a special utility called CodeRunner™. Even though the code (and the Java debugger) are local, CodeRunner plugs it into the Backendless API processing chain located in the cloud. Finally, once the code is ready, it can be pushed into the production environment where it is deployed to and runs on the Backendless servers.

For more information about Backendless custom business logic, see the Server-side code quick start guide.

Multi Environment Support (Dev, Test, Staging, Prod)

Most applications go through some well-known phases – development, testing, staging, and production. Each of these phases requires a corresponding backend environment where the application runs. The environments are isolated from each other, and an application migrates from one phase/environment to the next. Backendless now supports such migration. The concept of “environment” is represented through application versions. When you create a version, simply call it “dev” or “dev-v1”, “testing” or “production”. Deployment is available on Manage > Versioning screen. Simply click “Deploy” for the version you want to deploy and select the destination environment:

Relation Auto Load

Backendless supports relational object storage. For example, an object Person may have a related property “address” which references an Address object. When a client application loads a Person from the Backendless data storage, the “address” property is not initialized by default. There are ways to load related objects. You can enumerate all the relations in a “find” API call and Backendless returns them with the parent object. Or you could use a separate API call to load related properties. In addition to these options we added another alternative. Now the data browser in Backendless Console includes the “auto load” checkbox for all relations:

This checkbox is available for all relation properties. For the relations with selected “auto load”, Backendless automatically includes the related objects into query results. This option works recursively – any “auto load” relations in the child relations are also automatically included into the query results.

Application Reset

During the development and testing process an application may get “polluted” with dummy or testing data. Occasionally a complete (or partial) reset may be required. To do this in Backendless navigate to your application home (click the home icon in the upper left corner) and use the Reset App button:

Backendless Plus Enhancements

Backendless Plus is a subscription package, which can be added to any application to enhance its functionality, user and developer experience. In this release we made Backendless Plus even better with the following functionality:

  1. Script-level access for all console APIs. Backendless Console is a powerful tool, which is a frontend for one’s backend. There are many functions in console, which could be useful from the automation perspective. For example, configuring backend, setting up permissions and importing data are just a few tasks that can be done in a script.
  2. Custom business logic execution time. By default any custom business logic code has a limit of 5 seconds for the duration of time the code can run. Once Backendless Plus is added to an application, the limit is extended to 20 seconds.

Assigning Roles to Users

A user may belong to one or more roles. A role carries permissions for each available API operation. At the very minimum a user belongs to either AuthenticatedUser or NotAuthenticatedUser system roles. Custom roles may be assigned to a user account via an API call and now with Backendless Console. When you navigate to the Users table in the Data Browser screen, you can select one or more user and click the User Roles button. The user interface makes it trivially simple to assign roles to the selected user accounts:

Export Schema Only

Backendless Export module lets you export your application settings, data tables and geo points. We made an improvement in this release and now you can export only schema definition for your data tables:

Migrating from StackMob or Parse

The import module was also enhanced to simplify migration from StackMob (to be shut down on May 11th and Parse (no shut down notices have been published yet). To import the data, use the “single Zip file” link in the Manage > Import section of the console:

Users and Relations in Java/Android and iOS

Establishing relations between user objects and other entities in an application is a very common use case. This post describes various scenarios and shows sample code using Backendless SDK for Java/Android and Backendless SDK for iOS. Make sure the version of the client libraries are at least 1.5 for Backendless Java/Android and 1.11 for iOS.

  1. User to Object Relationship. In this scenario a property is added to a user. The value of the property is an object (or a collection of objects) from the Backendless data store. Consider the following code:
    Java:

    Objective-C:

    The code above initialized the app with app-id and secret key and logs in a user. Then a complex type (Address) is constructed and added as a property (“address”) to the user object. The user is saved using the “update” method in the User Service. Once the user is updated, you can see the relationship in Backendless Console (select your app, then Users and User Properties):

    Additionally, you can see the relation at the data level in Data browser. Click Data and navigate to the user object for which the code performed the update. You should be able to see the “address” column as shown below:

  2. Loading User Relations. Тhe login operation returns BackendlessUser object after validating login credentials. Even though a user may have related properties (relations), the returned BackendlessUser object does not automatically include them. Backendless requires a separate API call to load relations. For example, the following code loads the “address” relation created in the sample above:
    Java:

    Objective-C:

    As a result of the “loadRelations” operation, the same “user” instance is automatically updated and has the “address” property containing an array of Address objects. To load more than one relation, simply add the names of the related properties to the “rels” list. Alternatively, to load all available relations, use “*”:
    Java:

    Objective-C:

  3. Object to User Relation. This is similar to item (1), but the relationship goes in the opposite direction – from an object to a user account. Consider the following sample: a Java class which includes a field referencing a user:
    Java:

    Objective-C:

    Create an instance of Person, login a user and link the two together. Then save the instance of Person:

    Java:


    Objective-C:

    Once the call is complete, you will see the Person object in the Data browser and it will contain a link to the related Backendless User account:

Tizen integration with Backend as a Service

Tizen is an open source platform residing within the Linux Foundation. It includes an operating system which can run smartphones, tablets, netbooks, onboard devices in smart cars as well as smart TVs. We wanted to see what it would take to integrate a Tizen app with Backendless because the benefits of such integration would be huge. For instance, data can be easily shared between different implementations of an app: a Tizen version of the app can easily communicate with the one running on Android or iOS by the means of Backendless service APIs.

We put together two examples, which originally came from the Tizen SDK. The first app is a basic Todo implementation. The modified version stores the Todo tasks in the Backendless object storage. The video below reviews the integration and shows how the data can be exchanged between a JavaScript application and a Tizen app:

The modified source code of the app is available in the Backendless GitHub repository.

The second app uses the Backendless Geo Service API to store the device’s GPS coordinates in the remote storage. As the device moves around, the app automatically leaves a trail which can be retrieved with the API or managed directly in the Backendless Developer Console:

The source code for this example is also available in our GitHub repository.

Enjoy!

 

Securing access to your Backendless data

Our Data Service supports a very flexible security mechanism for restricting access to objects stored in Backendless. Security permissions apply to users and roles. A permission can either grant or reject an operation for a particular asset. In the context of Data Service, the asset is an object which your app can retrieve, update or delete. Permissions can be granted or rejected globally, where they apply to all tables and all objects in the data store. Additionally, every table may have its own permission matrix and owner policy – a special instruction whether object owners can or cannot retrieve/update/delete the objects they ‘own’. Finally, every object has its own Access Control List (ACL) which is a matrix of permissions for the operations applicable specifically to the object:

The security system is multi-layered. For an API call to retrieve, update or delete object(s), the system goes through several where each can trim the scope of the operations. The layered order of the decision making is important and consists of the following:

  1. ObjectACL for the user who makes the call
  2. ObjectACL for user-defined roles assigned to the user who makes the call.
  3. Table permissions for the User account
  4. Table permissions for the user-defined roles
  5. Owner Policy
  6. ObjectACL for system roles
  7. Table permissions for system-level roles
  8. Global user-defined roles
  9. Global system roles

Where:

  • “User-defined roles” – roles created by the application developer
  • “System roles” – roles built into Backendless (Authenticated User, NonAuthenticated User, SocialUser, etc)

Consider the following guide which illustrates the decision making process:

  1. Backend receives an API request to load data from a table (the Find operation). All objects become candidates for the retrieval. Backendless goes through the security permissions chain to determine which ones must be included.
  2. ObjectACL for the user who makes the call. Backendless checks if there are any restrictions for the user account at the object level. Any object in the collection with ACL which rejects access to the user is excluded from the result. To see or modify the permissions for a particular object, click the ‘key’ icon in the ACL column in the data browser in management console.
  3. ObjectACL for user-defined roles assigned to the user who makes the call. This is the same check as the one above, except Backendless looks into the permissions for the roles defined by the application developer. If the user belongs to any of the custom roles, Backendless checks if these roles are allowed to perform the current operation. In the screenshot below, only the “MyRole” role will be checked in this step, since this is the only custom role in the application:
  4. Table permissions for the User account. Every table in Backendless may have its own set of permissions for users and roles. At this point Backendless checks if the currently logged in user is allowed to run the current operation. For example, if the Find operation is denied for the user, no objects would be returned.
  5. Table permissions for the user-defined roles. This step is identical to the one described above with the exception that is checks custom roles for the table. Since this guide reviews the decision making process for the Find operation, Backendless checks the column for Find. If any of the custom roles deny access, the operation is rejected and no data is returned.
  6. Owner Policy. When a new object is created in Backendless, the system automatically links it with the account of the currently logged in user. You can see that information in the ‘ownerId’ column in any of your tables in the data browser.  With the association between objects and users, Backendless provides a way to control whether users can get access to the data they created. This is done through a concept we call ‘Owner Policy’. The policy is available on the ‘Schema and Permissions’ screen. Select a table in the data browser and click the ‘Table Schema and Permissions’ button in the upper right corner. Select the ‘Owner Policy’ menu item. Owner policy can be global (select ‘All Tables’ from the drop down in the upper right corner) or it could apply to a specific table.
    Granting a permission for an operation in Owner Policy, guarantees that the objects owned by the current user will be included in the resulting collection. Denying a permission, takes out the ‘owned’ objects from the collection of candidate objects to return. Consider the following:

    Granting Find permission in Owner Policy:

    Results in the following. The objects with bold border are guaranteed to be returned. All other objects will be subject to the subsequent permission checks.

    However, if the Owner Policy rejects a permission:
    The objects owned by the current user will be excluded from the resulting collection. All remaining objects will be decided by the subsequent permission checks.

  7. Object ACL for system roles. This check is identical to step 3 (Object ACL for custom roles). The difference is the system roles cover larger groups of users. For example, this step would make possible to restrict access to specific objects for all authenticated (or not authenticated) users, yet the object would be returned with a query made by the object’s owner if the Owner Policy (previous step) grants access.
  8. Table permissions for system roles. Identical to step 5, this checks if any of the system roles reject the operation at the table level.
  9. Global custom roles. Global policy applies to all tables and objects. By default all table level permissions inherit from the global policy. You can configure in the console at: Users > Security and Permissions. Create a new role and click it to configure the permission matrix:
  10. Global system roles. This is the same as the step above, but checks the built-in system roles (AuthenticatedUser, NonAuthenticatedUser, SocialUser, FacebookUser, TwitterUser).

As you can see the system is very rich and could get very complex. We plan to post a few scenarios showing how to configure the system. If you can think of any scenarios, post them in the comments and we will be happy to show how to handle it with Backendless.

Page 1 of 612345...Last »