Defining an Application Configuration File
Creating and Importing Application Configuration File¶
When non-default behaviors are expected, you need to define offline application settings in an application configuration file, and configure the mobile services based on those settings.
Create an application configuration (.ini) file (Application Configuration File) that includes the defining queries and other application-specific information.
Send the application configuration file to an administrator of the mobile services.
The administrator imports the .ini file and configures various offline settings that support the offline application. See Defining Applications and Defining Offline Application Settings in the cockpit online help.
A defining query is a read query that targets the OData service associated with the offline store and retrieves a subset of the endpoint data. You can define multiple defining queries for each endpoint.
Defining queries retrieve data from the OData service that is sent to the client, either during initialization of the offline store or during a download.
Defining queries are set up in both the application source code and in the application configuration files. In the source code, use the
addDefiningQuery method from the
OfflineODataProvider class with a name and a query. The example below demonstrates how the defining queries retrieve all information for one event.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
// Expand is needed to create a many-to-many relationship between Event and Feature // since there is no referential constraint defined on the relationship. // Data sharing should be enabled as all users see the same information offlineODataProvider.addDefiningQuery( new OfflineODataDefiningQuery("Events_10000", "/Events?$filter=EventID eq 10000L&$expand=Features", false)); // One-to-many relationship between Event and Session is built via // referential constraint. Data sharing should be enabled offlineODataProvider.addDefiningQuery( new OfflineODataDefiningQuery("Sessions_10000", "/Sessions?$filter=EventID eq 10000L", false)); // Data sharing should be enabled offlineODataProvider.addDefiningQuery( new OfflineODataDefiningQuery("Tracks_10000", "/Tracks?$filter=EventID eq 10000L", false)); // User Specific data; data sharing should be off offlineODataProvider.addDefiningQuery( new OfflineODataDefiningQuery("UserSessionAgendas", "/UserSessionAgendas?$filter=EventID eq 10000L", false)); // Data sharing should be enabled. offlineODataProvider.addDefiningQuery( new OfflineODataDefiningQuery("Features", "/Features", false));
In the application configuration file, reference each query using the same name as the one written in the source code (the first parameter to the
OfflineODataDefiningQuery constructor), as shown in the following example:
1 2 3 4 5 6 7 8 9 10 11
[defining_query] name=Events_10000 is_shared_data=Y download_interval=10 track_deltas=AUTO delta_token_lifetime=36000 [defining_query] name=UserSessionsAgendas is_shared_data=N ...
In the example, the defining query
Events_10000 is declared as sharable, which means that the event and related features can be accessed by all users.
Usually, you'll specify defining queries before the opening offline store for the first time, but they can also be added afterwards if appropriate.
Keep the following in mind when writing defining queries:
Currently, only defining queries where the resource path identifies an entity set or entity type instance (a single entity) are supported.
Shared defining query names must be unique, and must be identical on both the client and server. Otherwise, expected settings will not be applied to the correct defining query and the query will be using the default settings instead.
If you are using a mix of delta enabled and non-delta enabled defining queries, and you are using referential constraints to build relationships, the dependent entity in a relationship cannot be in a delta enabled defining query if the principal entity is in a non-delta enabled relationship. For example, say you have two defining queries,
Sessions(based on the sample metadata). Since there is a referential constraint between them and no expands are specified, the mobile services automatically use the referential constraints to build relationships. The events are the principal entities and the sessions are the dependent entities. If the
Eventsdefining query is not delta enabled, then the Sessions defining query must not be delta enabled. However, if the
Eventsdefining query is delta enabled, the Sessions defining query may or may not be delta enabled.
If you are not using deltas, you can use the same entity sets in more than one defining query, but you cannot perform a selective download of one of those defining queries without the others.
If you are using a mix of delta enabled and non-delta enabled defining queries, you cannot use the same entity set in both a delta enabled and a non-delta enabled defining query, either directly referenced in the resource path or through an
Using Defining Queries to Build Entity Relationships¶
To build relationships in your application, you can use
$expand in queries, referential constraints, or a combination of the two.
$expandin queries to build relationships between entity sets only if you are not tracking deltas, or if you are tracking deltas using the mobile services. You cannot use
$expandin queries if you are tracking deltas using the OData service.
If you are tracking deltas using the OData service and require entity relationships in the offline store, you cannot use
$expandin queries but instead must have associations with referential constraints. Ensure that each defining query references a single entity set. The mobile services detect the associations with referential constraints and use the constraints to build the relationships between the entity sets selected in your defining queries.
For example, the sample metadata document has an association between
Event_Session_One_Many0, which defines a referential constraint. If you specify two defining queries,
/Sessions, the server uses the referential constraint defined in the association
Event_Session_One_Many0to build the relationship between the
Sessionsentity sets in the offline store.
Combining referential constraints and
When you use an $expand to build relationships between two top-level entity sets, an association set is implicitly referenced. For example,
the Event_Session_One_Many0Setassociation set. The mobile services allow you to mix referential constraints and
$expandto build relationships.
Consider the following example, which uses entity sets from the sample metadata:
Relationships between events and sessions are computed using
$expand and relationships between events and track are computed using referential constraints.
However, you cannot mix referential constraints and
$expand for the same implicitly referenced association set. In the example below, relationships between events in Canada and their sessions are built using
$expand, where the
Event_Session_One_Many0Set association set is implicitly referenced. Although there is an association
Event_Session_One_Many0 with referential constraint between the
Session entity type, the referential constraint will not be used by the second and the third defining query to build other relationships since the referential constraint also implicitly references the same association set. As a result, relationships between events in the US and their sessions are not built. Hence, only for events in Canada one can use the
Sessions navigation property to get associated sessions. For events in the US, one must use the
EventID property in a filter to get the associated sessions.
1 2 3 4
~/Events?$expand=Sessions&$filter=Country eq 'CAN' ~/Events?$filter=Country eq 'US' ~/Sessions ~/Tracks
This is not an exhaustive list of ways to build relationships. The choice of defining queries is highly dependent on the needs of the offline application.
The table below lists parameters that can be used to configure defining queries in an application configuration file.
|name||Valid String||(Required) Name of the defining query.endpoint data.|
|is_shared_data||N or Y||Whether the data is shared among different clients or users.
The default value is N.
|refresh_interval||NNN||The interval time, in minutes, between downloads of the shared data.
The default is 15 minutes.
|track_deltas||AUTO or ALWAYS or NEVER||How to track OData deltas.
The default value is AUTO.
|delta_token_lifetime||NNN||The time, in minutes, until the OData delta token expires. While a token is valid, only changed data is downloaded to the offline store. When the delta token expires, the entire data set is replaced.
The default is 72000 minutes (50 days).
Performance Improvement with Delta Tracking and Caching¶
You can use delta change tracking (short as delta tracking) and data caching to significantly improve the performance of the mobile services.
OData delta tracking is a method by which a client obtains changes from an OData service without downloading the entire data set. Set up the
track_deltas parameter in your application configuration file to track deltas when you configure your defining queries. If your OData service supports the delta query protocol to track changes, the provided delta links automatically track changes and you don't need to configure delta tracking. When possible, use an OData service that supports delta query protocol.
Delta tracking sends only changed data to the client, rather than the entire data set. This significantly decreases the load on the back end and is especially useful when performance is critical.
If your OData service does not support delta tracking, the default delta tracking setting in the application configuration file tracks deltas using the mobile services. This improves performance on the client, while tracking deltas using the OData service improves performance over the entire network.
If your OData service has limited support for delta tracking, for example, deltas expire after a set period of time, using the ALWAYS setting for delta tracking in the application configuration file helps fill the missing delta tracking functionality.
If all or most of your data is continuously changing so that you expect to be downloading the full data set during every download, enabling delta change tracking does not improve performance. For example, if you download the temperature value for sensors in 1000 offices, using delta tracking does not decrease the amount of data downloaded during a download and turning off delta tracking may increase performance.
To minimize the load on the OData service and possibly improve performance, cache data that is shared by numerous users on the mobile services. For example, cache data from a query that returns the same results to multiple users. Do not cache data from a query that returns different results to each user. Set up the
is_shared_data parameter to cache data when you configure your defining queries in your application configuration file.
Application Configuration File¶
Use the application configuration file to configure OData endpoints and defining queries that determine the data that populates the client database (the offline store) when it is created. Use the cockpit to import the application configuration file.
An application configuration file consists of one or more OData endpoints, each of which can be optionally followed by one or more defining queries.
Each application configuration file represents a single application. All settings have default values, so an application configuration file is required only for non-default behaviors.
An endpoint is defined as follows:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
[endpoint] name=YourConnectionName prepopulate_offline_db=Y|N|SHARED-ONLY prepopulate_offline_db_interval=NNN indexed_type=<namespace>.<entity type name1>: Property1A [ASC|DESC][, Property1B [ASC|DESC], …] indexed_type=<namespace>.<entity type name2>: Property2A [ASC|DESC][, Property2B [ASC|DESC], …] defining_query_format=application/json;q=1,application/atom+xml;q=0.5 delta_query_format=application/atom+xml offline_db_collation=UTF8BIN case_sensitive_offline_db=Y|N json_datetimeoffset_in_utc=Y|N local_change_expiry=NNN allow_omitting_max_length_facet=Y|N content_id_header_location=mime|operation max_delta_resends=NNN
The table below lists parameters that can be used to configure endpoints in an application configuration file.
|name||Valid String||(Required) The name of the endpoint, which is the same as Connection Name in the cockpit.|
|prepopulate_offline_db||Y or N or SHARED-ONLY||The type of data that is included in the initial database.
The default value is Y.
|prepopulate_offline_db_interval||NNN||If a download requires a new database, the shared data is refreshed based on the interval specified, in minutes. This option applies only when prepopulate_offline_db is set to Y or SHARED-ONLY and there is at least one defining query with is_shared_data=Y.
The default is 1440 minutes (one day).
|indexed_type||The left-side value is the entity type name and the right-side value is a comma-delimited list of properties, each of which can optionally be suffixed with ASC or DESC. Each indexed_type creates an index on the client database. Defining indexes can improve client query performance. However, defining too many indexes can slow the performance of downloads and updates. Specify multiple indexed_type entries by listing one entry per line.
Specify either the primitive property name, or a complex type path expression that ends with a primitive property.
|defining_query_format||atom or json or any valid value||The format to use when communicating with the OData service. This property applies only when the offline store is making initial requests or non-delta requests to the OData service.
The default is
|delta_query_format||atom or json or any valid value||The format to use when communicating with the OData service. This property applies only when the offline store is making delta requests to the OData service.
The default is
|offline_db_collation||Any collation supported by UltraLite||The collation for the database.
The default is
|case_sensitive_offline_db||Y or N||Whether the database is case sensitive.
The default value is
|json_datetimeoffset_in_utc||Y or N||Whether the OData service specifies or accepts the ticks portion of a JSON-formatted
The default value is
|local_change_expiry||NNN||In some cases, local changes may remain in the offline store after it has been uploaded to the back end. To prevent this, specify a life span, in hours, for local data. When this option is omitted from the configuration file, local changes never expire.
|allow_omitting_max_length_facet||Y or N||When enabled, allows default
The default value is
Note: This feature is intended only for development purposes as it does not provide fine-tuned control over the values chosen. In a production environment, ensure
|content_id_header_location||mime or operation||In a batch request, the header section of the OData change set to put the
The default value is
|max_delta_resends||NNN||When multiple defining queries are delta enabled, the delta requests are automatically sent to the back end repeatedly until all delta responses are empty, to ensure data consistency. Use this option to configure the number of times a delta link is sent during a download.
The default value is 5.
|batch_all_defining_queries||Y or N||If
The default is
|refresh_in_order||Y or N||Whether to download data in the order in which the defining queries appear in the configuration file. If
The default value is
|check_repeatable_requests||Y or N||To enable repeatable requests, set:
If using an OData service that supports repeatable requests (such as Netweaver gateway), you do not need to enable check_repeatable_requests. When implemented in the OData service, protection is provided from all comunication errors. Whereas if you enable check_repeatable_requests, you are only protected against communication errors between the client and the mobile services. Communication errors between the mobile services to the OData service can still lead to issues. However if you are using an OData service without repeatable requests enabled you must enable check_repeatable_requests. See Repeatable Requests for additional details.
The default value is
|repeatable_requests_lifetime||NNN||Repeatable requests require space in your database tenant to track which requests have received responses. Set repeatable_requests_lifetime to control how long, in minutes, responses are saved.
The default value is 72000 (50 days). This setting needs to be large enough to handle devices that sit idle for some time.
For example, if a communication error occurs at the end of a Friday, you'd want to keep the saved responses until at least the following Monday (3 days). For example:
batch_all_defining_requests=N, multiple defining queries can be grouped into one batch request as instructed in a
[defining_query_group] section. For example:
1 2 3 4
[defining_query_group] defining_queries=req1,req2,req3 [defining_query_group] defining_queries=req4,req5,req6
|defining_queries||Comma-separated list of definined queries names||Defining queries that are specified in the same defining_query_group are sent in one batch request.|
defining_query_groupis defined, you cannot set
batch_all_defining_queriesis set to Y, then all the defining queries are executed in a batch.
- Defining queries not belonging to any group are executed individually if
batch_all_defining_requestsis set to N.