Search for answers or browse our knowledge base.
Stateful Services
Prerequisites
This tutorial assumes you have completed the entirety of the Introductory Tutorial and the App Component Tutorial. Please complete both tutorials if you have not done so already, then return to this page to learn how to use Stateful Services to improve them.
Overview
The App constructed in the Introductory Tutorial does not store any of the sensor information.
Events are received and processed by the Service and then discarded. There may be situations where storing the most recent sensor value for an engine may be useful. However, storing each event into the database as it arrives is a slow and inefficient solution that will not scale. In this Tutorial, you will learn to use the state properties of the Service to store sensor events in memory. Then, if necessary, the values stored in memory can be written to the database at an infrequent interval.
Part 1: Enhance the Component
1. Review Global State Variable Example
Recall that in the Introductory Tutorial, you introduced an AccumulateState task called SaveSpeed in the Inbound Service Event Handler SpeedEvent. The SaveSpeed task saves speed sensor readings in the speed Global State variable.
The SaveSpeed task also causes three Procedures to be generated: com.vantiq.engines.EngineMonitor.speedGet(), com.vantiq.engines.EngineMonitor.speedReset(), and com.vantiq.engines.EngineMonitor.speedUpdate(). These may be used to retrieve, reset and update the speed Global State variable.
2. Enhance the App Component
In the App Component Tutorial, some common tasks were used to create the FilterAndDiagnose App Component. Let’s add an additional task to the FilterAndDiagnose Component to save engine state whenever an unusual engine alert message is generated by the App Component.
Open the FilterAndDiagnose App Component by clicking on it from within the Project Contents tree:
From the Modifiers section of the palette, drag and drop an AccumulateState task over the link between the AddDiagnosis task and the Diagnosis connector. Select event as the Downstream Event and click OK.
Click the new AccumulateState task and rename it SaveAlertMessage.
Click the Click to Edit link to edit the configuration for the new SaveAlertMessage.
Enter lastAlert as the stateProperty property.
Click the “vailScript” link next to the procedure property. This allows you to write a VAIL Block code snippet for updating the Service’s Global State based on incoming events.
The following state-updating code tests to determine if the engine status alert message isn’t empty and, if so, creates a JSON object that contains four properties: systemId, lastAlert, temperature, and speed.
// Update the value of state using event.
var msg = event.alertMsg
if (msg != "") {
var newState = {systemId: event.systemId, lastAlert: msg, temperature: event.temperature, speed: event.speed}
state = newState
}
Click OK to complete editing the SaveAlertMessage task, then Save the component, which contains the new SaveAlertMessage task.
When an App Component is updated, the Service Event Handlers that use it must be resaved to include the Component changes.
Open the com.vantiq.engines.EngineMonitor Service, click on the Implement tab, then open the TemperatureEvent Event Handler in the Inbound section. The TemperatureEvent Inbound Event Type uses the FilterAndDiagnose App Component, so it needs to be updated. The easiest way to cause an update of the TemperatureEvent handler is to click the SensorReading task, make a small change to its name then change the name back to SensorReading, then save the event handler.
3. Test the New Global State
If you’ve imported the App Components completed tutorial, you will need to enable the two Sources, com.vantiq.engines.SpeedSensor and com.vantiq.engines.TemperatureSensor in order to begin the flow of simulated sensor events.
Click the Active Resource Control Center (lightning bolt) icon in the IDE Navigation Bar to display the Active Resource Control Center pane:
Activate the SpeedSensor and TemperatureSensor Sources by clicking their Active Slider. Once the Sources have been activated, the TemperatureEvent handler in the com.vantiq.engines.EngineMonitor Service will display badges as each of the tasks process sensor events:
To check that the lastAlert Global State is being correctly saved:
- click the State section in the Implement tab,
- open the Global State Type section,
- click the View (play icon) Action button next to the lastAlert variable. Select lastAlertGet as the Procedure.
Let the lastAlertGet Procedure run for a minute or so and observe the lastAlert JSON object that the SaveAlertMessage Component task is producing:
Part 2: Write State to the Database
1. Write System Status to the Database
As indicated in the Introductory Tutorial, the traditional approach of storing event data in a database is too slow and unnecessary for most purposes. In the engine status system modified in Part 1 above, processing sensor events and displaying them in the EngineMonitor Client is all accomplished by using in-memory state. However, there are circumstances where certain data need to be persistently stored on an infrequent basis.
As a persistent state example, we will create a mechanism to commit the last alert (lastAlert) Service State object to the database at a regular interval.
In the com.vantiq.engines.EngineMonitor pane, navigate to the Implement tab and click on the + button next to the Procedures header and select New Procedure.
Copy and paste the following code which retrieves the State object and updates the com.vantiq.engines.EngineLastAlert instance in the database for the matching systemId.
package com.vantiq.engines
PROCEDURE EngineMonitor.writeLastAlert()
var alertState = EngineMonitor.lastAlertGet()
if (alertState) {
UPSERT com.vantiq.engines.EngineLastAlert(alertState)
}
Click Save to save the Service. You will be prompted to repair the Service Interface because you have created a public Procedure that is not part of the Service Interface. Click Repair Interface.
Notice that when you saved the Service, the Procedure shows an error. That is because the com.vantiq.engines.EngineLastAlert Type does not exist yet. To create a new Type by that name, use the Add menu to select Type, then click the New Type button. Enter the following values as shown below:
- Name: EngineLastAlert
- Package: com.vantiq.engines
- Description: Last engine alert written periodically by the EngineMonitor Service
- Role: standard
Click OK to display the com.vantiq.engines.EngineLastAlert Type pane. In the Properties tab, add the following four properties using the Add Property button.
- Name: systemId, Type: String
- Name: lastAlert, Type: String
- Name: temperature, Type: Integer
- Name: speed, Type: Integer
Navigate to the Indexes tab and select Add Index. Select systemId as the key and check the Is Index Unique? checkbox.
Click OK to close the popup.
Navigate to the Natural Keys tab and click Edit Keys. Click the + button to add a key and select systemId and click OK.