Using Services
What is a Service
A service is an operation that allows Volt to communicate with other systems. Using a service you could call external applications like a servlet, web service or REST API. You can also communicate internally with any Volt application on the same server. Services can return a single item or a list of items. Services can be used to search, retrieve, update, create or delete.
Services are specific to a form, remember that an application can contain multiple forms. When deployed, a form can only reference services that it has registered.
In this example there is only one form, Form 1 and it has one service registered. Additional forms would appear as links in the Services section. And each form will show the services that it has registered.
Selecting a Service
The first step to configuring a service is to select the service that you want to use. The service may be a globally available service, another Volt application or a custom service that you (or your organization) have created. Regardless of the type of application the selection is made from the same screen.
Click on the Settings tab.
Under Services on the left side of the screen, select the form on which you want to register your service.
Any global and custom services that you may have installed will appear in the General Service Catalog.
You can also select Volt Applications to create a service that will inspect an existing Volt application. All the applications that you have permission to see will appear in the result list.
The list can be filtered by typing in the Search Terms field and clicking Search. When querying other Volt applications you will see many different types of services, I will define a few of them:
AppName / Form Name / Delete – Will delete the record that matches the search criteria.
AppName / Form Name / Retrieve – Will return the record that matches the search criteria.
AppName / Form Name / Search – Will return all the records that matches the search criteria.
AppName / Form Name / Submit (S_Submit) / Create – Will create a new form record with all the data specified.
AppName / Form Name / Submit (S_Update) / Update – Will update the specified record that matches the search criteria with all the data specified.
AppName / Form Name / Table / Search – Will return all the rows of a table within the specified form that matches the search criteria.
AppName / Form Name / Table / Retrieve – Will return the single row of a table within the specified form that matches the search criteria.
Mapping Inputs
Every service can be filtered by defining input assignments.
On the left-side is a list of all the fields in your form that you could use as an input. You can also change the View to Advanced to see additional field properties or Constant to specify a hard-coded value.
On the right-side is the list of search-able targets that the service.
To create an assignment, select an item from the left-side and the corresponding item from the right-side and click the assignment button in the middle. There are a few things that you should understand about defining inputs:
A service can have any number of inputs
The assignments that you create must be of the same data type
When multiple inputs are defined they will be applied as an AND relationship, which means that the results must match all the specified criteria.
If the form item that is assigned as an input is empty then it is not applied to the service.
Every target also has a Search operator that can be used to change how the inputs are interpreted. If you want to apply a search operator create an assignment that links the input with the target and the operator. To apply the operator you will have to set the View to constant and then type the operator keyword in the editable field.
Search Operators | Description |
equals | Equal to |
notequals | Not equal to |
lt | Less than |
lte | Less than or equal to |
gt | Greater than |
gte | Greater than or equal to |
endswith | The target ends with |
startswith | The target starts with |
contains | The target contains |
Mapping Outputs
Every service returns some type of feedback. The items returned by a service call can be linked to items in your form to either render the results, or affect the behavior of the form.
On the left-side is a list of the items that the service returns.
On the right-side is a list of the items in your form to which you can link the output.
To create an assignment, select an item from the left-side and the corresponding item from the right-side and click the assignment button in the middle. There are a few things that you should understand about defining outputs:
The assignments that you create must be of the same data type
The assignments must be the same structure, if a list is returned then you can only link it to list items (dropdown, table, radiolist or checklist).
If you change the view to Advanced then you will see additional properties that can be used in your assignment. You can set the value, an item's validity or the invalid message. A common example of this would be to perform a search (where only one record is allowed) and then create an output assignment between Found No Matches and a field's Valid property.
Triggering Services
Services can be triggered from almost anywhere within a Volt application. I have described a few of the most common places.
From a Button Click
This is the simplest mechanism for triggering a service.
Create a button.
Edit the properties of the button.
On the Advanced tab check the Call a service when clicked check box and then select the service from the drop down.
If you have not created a service yet, you can also create one by clicking the Add/Edit Service Configuration link.
When the value of a field changes
Triggering a service when the value of a field changes is also a very common use case. For example you may want to validate field content as soon as it is entered, giving the user immediate feedback rather then waiting till they try to submit.
Open the properties for the item from which you want to trigger the service.
Click the Events tab.
Click the onItemChange event.
Select the Call a Service check box and select the service from the drop down list.
When a new form is loaded
You may want to call a service to populate the form when it is loaded for the first time. For example you might want to pre-populate information about the current user by calling a LDAP service. The danger in simply calling a service like this in the Form onLoad event is that it will get called in every stage so the original information would get replaced with the user that opened the form in the later stage. To avoid this you should use:
Open the Form Properties.
Click the Advanced tab.
Click the Call a service to pre-populate check box and select the service from the On display of new form drop down list. This will only trigger the service when a new form is created and ignore it on loads in a subsequent stage.
If you want to call a service on every subsequent load of a form (but not when it is created) then you could use the On re-load of existing form dropdown list.
Pre-populating Dropdown Choices
You may want to pre-populate drop down choices from a service.
Open the properties for the drop down item whose choices you want to get from a service.
Under Set Options click the Edit button.
Change the option type from Default to Use a Service.
Select the Service from the list.
Using JavaScript
You can trigger a service call at anytime with JavaScript. The syntax will change depending on where you are placing the code. I will show an example of the call and then explain how it may change depending on the context.
form.getServiceConfiguration("<Service ID>").callService(); |
The call itself is pretty straightforward, all you need to know is the ID of the service that you want to trigger. The service ID can be found on the Settings tab, under the Services section on the left navigation section – click on the link that matches the form where the service was created. A Service Configuration dialog will appear, the ID is on the Details tab.
If you are triggering a service at the item, page or form level the call is:
form.getServiceConfiguration("<Service ID>").callservice(); |
If you are triggering a service in the app onStart the call is:
app.getForm('<Form ID>').getServiceConfiguration("<Service ID>"); |
When another service finishes
You may encounter a situation where you need to call a second service after you have received the result of the first service. Because the service calls are asynchronous, occur at the same time, you have to register a listener that will alert the application when the service completes.
The basic structure of the listener is:
Every listener that you create will follow this exact same structure. The only changes that are required are the <Service ID> and the code that you want to execute when the service completes.
When a form is loaded one of the things that we do is look for all the listeners that may have been setup so you are free to place them where you like. There are multiple places where you can put this listener but there are positives and negatives of each. I will share my experience and you can decide which works best for you.
Application OnStart
The form keyword does not exist at this level, therefore you have to explicitly retrieve the form for which you want to reference:
The onStart event is executed for every form within an application. If you try to retrieve a service that does not exist then you will get an error. Therefore when implementing the listener here you must confirm that the form exists before trying to retrieve the service:
Form onLoad
The form onLoad is only called when that form is loaded, so you won't have to worry about checking to see if the form exists which simplifies the code you have to write.
The form object exists, which also simplifies the code you have to write.
In an Item
The form key word exists and the listener will only get loaded within the scope of this form and item.
The negative is that you have to remember to disconnect the event otherwise a new listener will get added every time the event is triggered throughout the form's life cycle. The call changes slightly (note the new variable hdl and the disconnectEvent at the end):