Client Services

Setting up advanced client services in a jQM app.

Using a REST Service

A client REST service is an imported service from Create new > Backend Services that integrate the app with Appery.io backend services or external REST APIs:

  • API Express.
  • Database.
  • Server Code.

To learn more about API integrations go to the Using APIs in an App page. The rest of this section will cover using and editing an imported service in an app.

Settings Tab

Settings view allows you to set the:

  • Name – a service name.
  • URL – service URL to an Appery.io backend service.
  • Method – type of request:
  • Get – requests data from a specified resource.
  • Post – submits data to be processed to a specified resource.
  • Put – uploads the specified data (a complete replacement of data).
  • Patch – updates data (applies partial modifications to a resource).
  • Delete – deletes data from the specified resource.
  • Data Type – format of the data returned by the service:
  • JSON – JavaScript Object Notation: text-based open standard, designed for human-readable data exchange between the browser and server.
  • JSONP- JSON with padding: provides a method to request data from a server in a different domain.
  • XML – Extensible Markup Language: a set of rules for encoding documents in a format that is both human-readable and machine-readable.
  • Settings – the settings service can be selected from the drop-down list.
  • Security Context – a generic security service running JavaScript code before or after the REST service execution.
  • Content Type – when you use the POST, PATCH, and PUT methods, you can specify how the data should be encoded when submitting it to the server. A list of name/value pairs depends on the value you set to this parameter:
  • JSON: application/json application/javascript text/javascript
  • XML: application/xml text/xml application/xhtml+xml application/atom+xml
  • x-www-form-urlencoded: application/x-www-form-urlencoded
  • data: application/octet-stream

Request Tab

To add request headers (Headers tab), input parameters (Query String tab), and set default values, if needed.

Response Tab

Define output headers (Headers tab) and parameters (Body tab).

Test Tab

To test the service and create a service response based on the test results.

Echo Tab

To get data from the service without invoking it.

Adding Service to Page

Once a service has been defined, it can be added and mapped to one or more pages. To add a service to a page:

  • Go to the page where you need to use this service.
  • Switch to the Data view by clicking the DATA tab.
  • Add a datasource, select Service, and then the service you’ve created.
  • Click the Add button. A service instance will then be added to the page.

By default, the service instance is named restserviceX. You can change it to a more meaningful name by setting its name property.

Request Parameters

Request view allows you to define the request parameters and headers required by the service to be invoked. Every service can define a different number of request parameters. Some parameters are required; others may be optional. Some services don’t require any request parameters at all.

To create, edit, or delete request parameters, open Request view, and switch to the Query String tab.

Query Parameters

To create a new parameter, enter its name and click Add. To create a new parameter, enter its name and click Add. When you use the service on a page, you can use the default values, or you can map page component properties to the parameters instead.

Import Query String

You can add a set of request parameters by importing a query string. To do this, click Import and enter a query string in the newly-appeared window. Click Import to add request parameters based on the provided data. The imported query string should be composed as a series of field-value pairs as in the following:

param1=value&param2=value

Request Headers

Some services require one or more request parameters to be sent as Header. Header parameters should be added on the Request > Headers tab.

Import Header Requests

You can add a set of request headers at once by using the Import feature. Headers should be specified as field-value pairs. Use line break as a separator between pairs as follows:

header1: value
header2: value

Request Body

When you use POST, PUT or PATCH methods, the new Body tab appears in Request view. Its type is based on the Content Type chosen in the REST Service settings. If Content Type is set to Data, the Request Body contains a single parameter which you can’t modify. When adding the service to a page, you can map binary data (e.g. files) to this parameter.

Default Request Paramater Value

You are not required to map every service input parameter to an element on the page. It’s possible to set a default value for an input parameter. You can also use JavaScript to provide a default value. Click “JS” and provide a default value or expression that will calculate value.

return "12345";
var currentDate = new Date();
return currentDate.getDate();
return Apperyio('input_field').val();

If you set default values during service creation, then those values automatically copied to the service instance mapping.

Using Settings Service

The Settings service allows you to save app information such as API keys and URLs into a settings file, and then reference the data from anywhere in the app. This also allows you to make changes in one place rather than having to replace the same value everywhere in the app.

New Settings Service

To create a new Settings service, from Project view > CREATE NEW > Service, check Settings(REST Settings), and click Create Service.

To create a parameter, enter its name and click Add.
It’s basically a properties file with key/value entries. You can also specify an optional description.

Using Settings Values

You can use the values from a Settings service in defining a REST service as well as JavaScript.

Using Values In REST Service

  1. When defining a REST service set the Settings property to the Setting service’s name.
  2. To refer to a value in the settings file use {name}, for example: {url}.

Using the values in the Request tab:

Using Values In JavaScript

The Settings service is a hash that can be set in runtime. For example, if the service is called AppSettings and has airport_code key then you can set it like this via JavaScript:

AppSettings.airport_code = "SFO";

You can read the values similarly:

var airport_code = AppSettings['airport_code'];

Or:

var airport_code = AppSettings.airport_code;

Plugins

Most plugins use a Settings service to keep data, (such as API keys) in one centralized place. When creating a new plugin you can keep this data in a Settings service as well.

Using Generic Service

A Generic service is used to extend the standard REST service. It still has inputs and outputs (as standard service), and it can be mapped, but the actual service implementation, or what it does is up to you. For example, the service can access local browser databases such IndexedDB, SQLite, or do calculations.

Creating Generic Service

A Generic service can be created via CREATE NEW > Service > Generic (custom JavaScript implementation).
A new service will be created. Custom implementation can be added by clicking Add custom implementation.
Choose between using an existing JavaScript file or creating a new one.
Default or custom implementation can be opened by clicking Open implementation.
If you create a new JavaScript file, there’s default implementation code that can be edited by the user.

Request and Response Parameters

Request Parameters

As with the standard REST service, the Generic service also has a Request and Response tabs. Any input/output parameters needed for custom implementation can be specified there. Input parameters can be accessed by settings.data..
For example, a specified parameter with someParameter name and some_value value.
This parameter can be accessed from the custom implementation JavaScript file with the following code:

settings.data.someParameter

The following custom implementation will simply log the input parameter:

Appery.CacheData = Appery.createClass(null, {
 
    init: function(requestOptions) {
        this.__requestOptions = $.extend({}, requestOptions);
    },
 
    process: function(settings) {
        if (this.__requestOptions.echo) {
            settings.success(this.__requestOptions.echo);
        } else {
            console.log(settings.data.someParameter);
        }
        settings.complete('success');
    }
 
});

In the example above, someParameter value was specified in the Request tab. It is also possible to pass this value from the page via components mapping.

For example; there’s a Textarea component on the page where the user must input something. The following mapping will pass the someParameter with the value typed in the Textarea to the custom implementation code:

It doesn’t matter where the parameter value comes from; it can be accessed by settings.data.

Response Parameters

To create the mapping with the results data, the Response tab must contain at least one parameter. Lets say your custom implementation must return the username:

It’s possible to map the response to the component:

The result can be specified in the implementation using the settings.success method. The parameter mapped to the page, the response parameter, and the parameter specified in the custom implementation must have the same name. In this case, it’s name:

settings.success({"name":"Dan"});

📘

Note

The response value must be always specified in JSON format.

Custom implementation for the example above:

Appery.CacheData = Appery.createClass(null, {
 
    init : function(requestOptions) {
        this.__requestOptions = $.extend({}, requestOptions);
    },
 
    process : function(settings) {
        settings.beforeSend(settings);
        if (this.__requestOptions.echo) {
            settings.success(this.__requestOptions.echo);
        } else {
            console.log('Default implementation is used. Please define your own.');
            settings.success({"name":"Dan"});
        }
        settings.complete('success');
    }
 
});

Any number of parameters can be returned and mapped. The following screenshots show the implementation with name and age parameters in the response.

The Response tab with two parameters:

Mapping two response values to different components:

The implementation code in the case of two response values:

Appery.CacheData = Appery.createClass(null, {
 
    init: function(requestOptions) {
        this.__requestOptions = $.extend({}, requestOptions);
    },
 
    process: function(settings) {
        if (this.__requestOptions.echo) {
            settings.success(this.__requestOptions.echo);
        } else {
            settings.success({"name":"Dmitry","Age":"22"});
        }
        settings.complete('success');
    }
 
});

Response parameters will automatically be parsed and associated by names with the mapped parameters.

Settings

Class settings contain a few methods that work the same as that of a common REST Service. In the example above there are Before send method called firstly and lastly called the Complete method. These events are exactly the same that can you can see from the visual builder.
If you need you can implement a GenericService implementation that will return Error in some cases.

Appery.CacheData = Appery.createClass(null, {
 
    init: function(requestOptions) {
        this.__requestOptions = $.extend({}, requestOptions);
    },
 
    process: function(settings) {
        if (this.__requestOptions.echo) {
            settings.success(this.__requestOptions.echo);
        } else {
            settings.error(null, null, "Error occured");
        }
        settings.complete('error');
    }
 
});

In this case service will call Error event and then Complete the event. When you are mapping to an Error event there are 3 parameters available – jqXHR, textStatus and errorThrown.

You can list this parameters separated by a comma as following:

settings.error(null, 'textStatus here', "Error occured");

Using Local Storage

With the help of local storage any data can be saved and loaded from any service. The first service can save data into the local storage, and the latter can load this data and use it.

Using local storage:

Appery.CacheData = Appery.createClass(null, {
 
    init: function(requestOptions) {
        this.__requestOptions = $.extend({}, requestOptions);
    },
 
    process: function(settings) {
        if (this.__requestOptions.echo) {
            settings.success(this.__requestOptions.echo);
        } else {
            // save JSON data to local storage
            // could be saved from a another (previous) service invocation.
            localStorage.setItem("cacheddata", JSON.stringify({
                'name': 'joe'}));
 
            // load JSON data from local storage
            var cdata = localStorage.getItem("cacheddata");
 
            // pass the JSON to the service, for output mapping
            settings.success(JSON.parse(cdata));            
        }
        settings.complete('success');
    }
 
});

Executing Another Service

Executing Another Service Within A Generic Service

Custom implementation allows you to support service calls from the JavaScript code. This is handy when you need to do some checks or advanced logic before calling the REST service.

Lets say there is a standard REST service that creates a new object in the todo collection.

The following custom implementation simply invokes calling the add_todo_object service and passes some parameters to it, it can be easily extended with any logic you need:

Appery.CacheData = Appery.createClass(null, {
 
    init: function(requestOptions) {
        this.__requestOptions = $.extend({}, requestOptions);
    },
 
    process: function(settings) {
        if (this.__requestOptions.echo) {
            settings.success(this.__requestOptions.echo);
        } else {
            //Some operations can be performed before the service call
 
            add_todo_object.execute({data:{"priority":"High","taskName":"Buy a car"}});                                       
        }
        settings.complete('success');
    }
 
});

Using a Generic Security Context Service

A Generic Security Context service is used to wrap REST service calls. The user is able to run any JS code before or after REST service execution.

Creating Service

To create a Generic Security Context service go to the Create new > Service > Generic Security Context radio and click Create Service.

You can enter a name parameter (name is a binary string that labels a security principal [i.e., user or service program]), and an (optional) Default value (a string that is used, for example, for tests or as static values).

You can add custom implementation by clicking Add custom implementation, enter the name for JS file, or select an existing JS file, and confirm.

Open the JavaScript file. You should see something like:

Where the Token is the name of JavaScript:

var CustomContext = $t.createClass(SecurityContext, {
 
invoke: function(service, settings)
 
{ //Do any logic before call
 
CustomContext.$super.invoke.call(this, service, settings);
 
//Do any logic after call }
});

This is needed before executing for checking/editing/adding parameters.
An example of the JavaScript for the custom implementation:

For the services that need additional options, on the Settings tab for the Security Context menu item, you should choose your Generic Security Context.

You can create as many Generic Security Context services as you need. They may be used for authorization, validation, service debugging, etc.