Creating, Implementing, and Testing Services
Thing services are functions that a Thing can perform. Services are used internally in the ThingWorx Platform and by mashups, and they can be reached from any external source with appropriate access. You can define services on the following ThingWorx entities only:
• Things
• Thing Templates
• Thing Shapes
• Resources
• Authenticators
Services are implemented through JavaScript, SQL, or Java.
|
Java is available for extensions only.
|
A service can be invoked through a URL, a REST client solution, or by another service in ThingWorx.
Create custom services for your model in ThingWorx to meet the requirements of your project.
Best Practices for Creating and Implementing Services
Use the following best practices while creating and implementing services:
• Define naming conventions for your services. Keep the following points in mind:
◦ Provide a logical, meaningful name and description to the service.
◦ Use a standard nomenclature across services. For example, prefix the service name with a verb and a description of the service. Some examples of verbs are below:
Verb
|
Description
|
Get
|
Retrieve values from the database.
|
Set
|
Set the value of database entries.
|
Query
|
Return a group of records from the database.
|
Add
|
Add records to the database.
|
Update
|
Update records in the database.
|
Delete
|
Delete records in the database.
|
Validate
|
Validate records in the database.
|
Purge
|
Purge records in the database.
|
Create
|
Create a set of records in the database.
|
Import
|
Import data to the database.
|
Export
|
Export data from the database.
|
Parse
|
Parse data.
|
For example: A service that retrieves historical data, getHistory is the recommended name, instead of History.
◦ Avoid ambiguous names.
◦ Avoid long service names wherever possible.
• Group common properties and services in a single entity, preferably a Thing Shape.
• Whenever possible, implement services on Thing Shapes.
|
It is recommended that you use Thing Shapes to define properties and services. If you define properties and services on a Thing Template, it is difficult to move their definitions to a Thing Shape.
|
• Design services for different layers such as a user interface, business logic, and data retrieval. The services in different layers have different responsibilities. The following image provides an example of the responsibilities in different layers:
• While writing a service, try to reuse the available snippets from the ThingWorx code snippet library. If you are not sure how to use any of the code snippets, test them before using them in your service.
• While creating your service with output set to JSON, note the following:
◦ If the properties have values as null or undefined, then they are not returned in the result.
For example:
var test = {
test1: "aaa",
test2: 123,
test3: null,
test4: undefined
};
var result = test;
Output: {"test1": "aaa", "test2": 123}
◦ If the property is a JSON object, and it is set to null, then it is returned in the result.
For example:
var test = {
test1: "aaa",
test2: 123,
test3: null,
test4: undefined,
"line_categories": [ null ]
};
var result = test;
Output: {"test1": "aaa", "test2": 123, "line_categories": [ null ]}
• If you expect your service to take a long time to complete, ensure that the user is not able to trigger the service more than once at the same time.
• If the service is based on an event trigger in a mashup, use the ServiceInvokeCompleted event to allow data flow in a solution.
• To refresh data in mashups, it is recommended to use an Auto Refresh widget or the GetProperties service.
If a mashup uses the GetProperties service and the browser supports WebSockets, then the browser automatically receives values of updated properties in real time from the server. In this case, there is no need to use the Auto Refresh function. This capability is available only if you select the Automatically update values when available check box from the service properties panel.
If you are using the Auto Refresh function, PTC recommends setting the Auto Refresh function to a minimum of 15 seconds to avoid taxing your system.
| Do not use a server-side delay service, as it can lead to other services being blocked. This can result in a solution crash. |
• For simple conversions at runtime, it is recommended to use the Expression widget rather than services.
For example, if you are displaying the temperature in °C and you want the user to be able to see it in °F, use the Expression widget.
• Add checks to your code to avoid the possibility of the end user receiving an error.
For example, if your code needs a couple of input parameters to run, create checks to ensure that those input parameters are not null when the service is executed.
• If your solution will be localized and if there is text in the UI elements that changes dynamically based on the result of services, ensure that you do not hardcode text values in your services that will be displayed in the mashup. This is because the result of the services returning the text needs to be localized. This also makes it easier to maintain and modify the UI text in the future.
• A possible result of the execution of services can be the creation of ghost entities. Ghost entities are created dynamically via code/scripting, rather than from the ThingWorx Composer. Creating ghost entities is a bad practice. For more information, see
Creation and Deletion of Ghost Entities.
• The default script timeout setting on the ThingWorx Platform is 30 seconds. If a script runs longer than the default setting, the ThingWorx Platform terminates the execution. The ThingWorx administrator can configure the script timeout in the basic settings section of the platform-settings.json file.
Best Practices for Testing Services
Use the following best practices while testing services:
• Test your service incrementally, as you build it. Use script logger messages, if appropriate.
| Any service with an infinite loop can bring down the ThingWorx server. |
• While testing a service, check logs for error messages. This is particularly useful for services in subscriptions. The following log files are useful:
◦ ErrorLog.log – Provides detailed stack tracing for errors
◦ ScriptErrorLog.log – Provides service context information (stack error line number)
Errors are logged in this file only if you select the Enable Script Stack Tracing check box in the Configuration tab of the LoggingSubsystem subsystem.
| The above files are available in the ThingworxStorage/logs folder. You need access to the ThingWorx server to read these files. |
• If the service is called from a mashup, test it in the Composer and in the mashup.
• If user inputs are required for the service to execute, you can use the Validator function.
• Use the Developer Tools that are available in browsers to check the result of a service. This is useful when you want to debug a sequence of services that executes in a mashup. This tool displays the service results in the context of that specific execution.
Tips
• If you want to search for services, do not open the entity in Edit mode. Use the Preview link to the left of the name of the entity to open the entity in View mode.
Other Considerations
• Security—To enhance security, use service overrides to deny permissions on critical services available on the ThingWorx Platform.
• Upgrades—Use good coding practices and do not create large monolithic services.
• Concurrency patterns—ThingWorx Thing services are not run in isolation by the application engine. As such, Thing Model property changes made in one service are instantly visible in all other concurrently running services. If two services are trying to write the same property at the same time, both writes will be successful. The property value will end up in whatever state was executed last, which may be different than the order in which the writes were submitted to the server. In fact, in general, concurrent access to most data and resources within the ThingWorx Platform behaves in a last-write-wins fashion. Application developers and architects should consider these behaviors when authoring applications.