Logi Info includes Process definitions, a special type of definition that lets you create subroutine-like tasks that can include conditional processing, branching, error handling, and other advanced features. This topic discusses Process definitions and tasks.
- About Process Definitions and Tasks
- Calling and Completing a Task
- If-Then Branching in a Task
- Setting Variables in a Task
- File System Interactions from a Task
- Exporting from a Task
- Using Local Data in Tasks
- SQL Database Interactions from Tasks
- Running Datalayer and Data Table Rows
- Sending Email from a Task
- Web Service Interactions
- Error Handling in Tasks
About Process Definitions and Tasks
Process definitions are similar to Report definitions and they're created and managed in Logi Studio in the same way. They contain element groups called Tasks, which are created in Logi Studio using elements in a manner similar to creating a Report definition. Unlike Report definitions, tasks run at the web server and don't present anything visual in the browser.
In the file system, Process definition files are physically stored in your application folder, as shown above, in the _Definitions_Processes folder. They're .lgx type files and use the same XML source code found in Report definition files.
In Logi Studio, Process definitions appear in the Application panel listed under the Processes folder, as shown above. You can add a new process definition by selecting and right-clicking the Processes folder and manage them in Studio like any other definition.
Each Process definition file contains one or more tasks. So, you may decide to use multiple Process definition files in your application. You may prefer to put all of your tasks in a single definition file, or to group tasks, by function for example, in separate Process definition files. The choice is to yours; the Logi Server Engine will include all Process definition files when it runs the application.
Tasks are created in a Process definition by adding a Task element to the definition root. The example shown above includes three tasks.
The top-to-bottom order of Task elements in a Process definition does not matter (a suggestion: alphabetical order makes them easier to find). However, within a task the position of its child elements is important because they're processed in a top-to-bottom sequence.
The example above shows some of the elements available for use in a task; they can perform a variety of operations. Some look similar to those used in Report definitions while other are unique to Procedure definitions.
Tasks can accomplish many things that cannot be done in a Report definition. For example,
- Direct interaction with the web server file system (to save, copy, or delete folders and files)
- Conditional processing using If-Then branching of processing flow
- Row-by-row processing of datalayer or data table contents
- "Write back" to databases, to insert and update records
- Generic and error-specific error handling (including SQL errors)
- Send email, SMS messages, and Twitter tweets
- Save file uploads and the state of super-elements
- Set and clear client-side cookies
- Create and manage Logi Scheduler tasks
- Terminate server session
and they can do many of the same things, such as exports, plug-in calls, database operations, and more.
When using Logi Security, the Task element's Security Right ID attribute, shown below, provides greater security control over the running of tasks.
The Unsafe Script Allowed attribute, pictured above, controls whether the Procedure.Script element throws an 'Unsafe class reference' error when accessing the file system object. To overcome this error when running a procedure, set the Unsafe Script Allowed attribute to 'True'. For more information about scripting objects and functions, see Work with Scripting.
Tasks are essential to use of the Logi Scheduler: when the Scheduler runs a scheduled event, it calls a Process task, which then runs the desired report and manages its output. For more information about this, see Introduction to Logi Scheduler.
You can use a Default Request Parameters element in a Process definition, as you would in a Report definition, and you can also use it within individual tasks. For more information, see the Using Request Parameters section in Pass Information.
Process definitions and tasks extend the capabilities of Logi Info apps in many ways, and provide with tremendous functionality. The remainder of this topic provides examples of some of these capabilities in use.
In order to use a task, you must call it, and when it completes, it needs to redirect processing to someplace else.
Calling a Task from a Report Definition
As Logi report developers, we're used to "calling" one report definition from another report definition, using links, buttons, or events. When doing that, we can pass information to the next report using Link Parameters and we know that User Input element values are POST'ed to the next report as Request variables. The same is true when calling a Process task from a report.
In the Report definition example shown above, an Action.Process element is used beneath a Label element to redirect processing to a task. The Action element's attributes identify the Process Definition File and the Task ID of the task to be called; these values can be selected from drop-down lists. A Link Parameters element can also be used beneath the Action element, if desired, to pass information to the task.
When processing is transferred to the task, the Link Parameters and any User Input element values will be available in the task as Request variables and can be used there via @Request tokens.
Calling a Task when a Report Loads
You can have a task run automatically when a Report definition loads.
This "onLoad event" behavior allows you to set variables, run procedures, and accomplish any
other initializations you might want to do, and then redirect the browser
back to the report definition.
As shown above, the Startup Process element is added to a Report definition, and its attributes are set to identify the desired Process Definition and Task ID for the "startup task".
Any Request variables in the query string used to call the report definition will automatically be available as Request tokens in the Process task called with this element. For example, the @Request.rdReport~ token will contain the name of the report definition specified in the URL. Note that any parameters set using Default Request Parameters element are not passed to the task.
You can use a Response element at the end of the startup task to redirect the browser to a specific report definition after the task completes but this is optional. Without one, the browser will be automatically redirected back to the original report definition.
The element's Condition attribute can be used to dynamically control when the Startup Process will be called.
Multiple Startup Process elements may be used to call different process tasks; they'll be run sequentially, one after the other.
Calling a Task from a URL
You can also call a process task directly from a URL, using the following syntax:
where rdProcess and rdTaskID are required and additional request variables, such as myParam, are optional.
This URL can be used, for example, with an Action.Link element, or even from an external application.
Calling a Task from Another Task
Under certain circumstances, you may want to transfer operations from one task directly to another task.
The Procedure.Process Task element lets you directly call another task, in the same or in a different Process definition. A child Link Parameters element can be used to pass values to the target task. This does not operate like a function - the designated task will be executed but operations will not "return" to the first task afterwards.
You can also use a more "manual" approach, with the Response.Link element:
In this case, you would use a Response.Link element, as shown above and, in its Target.Link child element's URL attribute, use the syntax shown in the previous section for calling a task from a URL. You can use @Request tokens right in the URL to forward request variables sent to the first task, so they'll be available in the second task, like this:
Recursion and nesting do not exist for tasks; one task just leads to another and the last task needs to handle redirection to a visible web page.
Calling a Task at Session Start
You can have a task run automatically when a user session begins (i.e., when the application is browsed by a user for the first time). This allows you to set variables, run procedures, and accomplish any other "startup" work you might want to do, and then redirect the browser to a report definition.
As shown above, the Startup Process element is added to the _Settings definition, and its attributes are set to identify the desired Process Definition and Task ID for the "startup task".
Any Request variables in the query string used to call the application will automatically be available as Request tokens in the Process task called with this element. For example, the @Request.rdReport~ token will contain the name of the report definition specified in the URL. Note that any parameters set using Default Request Parameters element are not passed to the task.
You can use a Response element at the end of the startup task to redirect the browser to a specific report definition after the task completes but this is optional. Without one, the browser will be automatically redirected to the application's default report definition.
The element's First Session Only attribute can be used to prevent the Startup Process from being called if the application is called recursively.
Multiple Startup Process elements may be used to call different process tasks; they'll be run sequentially, one after the other.
Completing a Task
When processing is transferred to a task and it completes, there is no "stack" to unwind, no built-in return path back to the calling Report definition. As the developer, you must explicitly transfer processing somewhere else after a task completes. If you don't, your user will be left looking at a blank browser screen!
Tasks use Response elements, as shown above, which end a task by redirecting processing, usually back to a Report definition. You can also redirect instead to another task, as discussed earlier. You should ultimately redirect to a visible page so the user sees something in their browser.
The Response.Raw element can be used to complete a task and gives you full control of the response. This can be especially useful when building a REST API call from a Process. Response.Raw responds with a value and optional response headers.
In the example above, the Response.Raw element is used to provide response values using @Procedure tokens. Its Response Header Params child element can be used to provide custom response headers and values. The Response.Raw element's attributes are:
Content Type - If left blank, the default content type is text/plain; charset=utf-8
Status Code - The HTTP response status code; if left blankt, the default value is 200
Status Description - The HTTP response status description; if left blank, the default value is OK
Value - The response value; @Procedure tokens may be used here.
Data validation provides a fine example of conditional branching within a task. Tasks are excellent places to do data validation if you can't, or don't want to, do it in a Report definition.
In the task example shown above, we introduce the Procedure.If element, which allows you to use conditional branching in your task. In the example, we want to validate a password entered by the user in a report definition. The Save button in the report calls this task and the Procedure.If element's Expression attribute uses an @Request token to access the password value. If the Expression attribute formula evaluates to True, then its child elements will be processed. If it evaluates as False, the child elements are ignored and the next sibling element down will be processed.
So, if the evaluation is True (the password is less than 8 characters long), we skip the Procedure.SQL element and run the Response.Report element. A further enhancement to this task would be to add a Link Parameters element beneath Response.Report to pass an error message back to the calling report.
If the evaluation is False, the password length is acceptable and the next sibling element, the Procedure.SQL element, is processed. Once it completes, processing goes on to the Response element at the end of the task to redirect processing elsewhere.
You can have multiple Procedure.If elements in a task and they can be nested. They're useful, of course, for many other purposes besides data validation and can be used any time you want to direct processing flow based on evaluation of an expression.
Several other elements are available for use in controlling conditional branching:
Procedure.Else - This element must be a sibling of, and immediately follow, a Procedure.If element. It identifies a conditional block of procedures that will be run if the Procedure.If element immediately above it evaluates to False. If the Else block ran, the token @Procedure.myProcedureID.rdReturnValue~ returns True, otherwise it returns False.
Procedure.Switch - This element works with one or more child Procedure.Switch Case elements to define conditional blocks of procedures to be run when a specified value matches. Use it when there are multiple conditional blocks defined and just one of them is to be run, based on the value of a variable. You can also use a child Procedure.Switch Else element, which runs its block of procedures if none of the previous Switch Case elements match the specified value.
In a task, you may need to have working variables that you can manipulate. For example, you may need to perform a calculation on a Request variable value. There are several ways to create these "local variables".
The Procedure.Set Procedure Vars element allows you to set variables and values that can be used for calculations, etc., within the scope of the task.
Variables are created using a child Procedure Parameters element, which defines name-value pairs, just like other parameters elements, as shown above. The values can be set using literals, tokens, or expressions prefaced with the "=" sign. The resulting procedure variables can be referenced anywhere in the task using this token:
@Procedure.<Procedure.Set Procedure Vars element ID>.<variable name>~
Session variables can be also used in the same way for this purpose:
In the example above, a Procedure.Set Session Vars element has been added. The new session variable it creates applies the DateAdd function to a date passed as a Request variable. Now, in the Procedure.SQL element, we can use the token @Session.newStart~ to update a database table with the new date.
Session variables set in tasks are, of course, globally available and can be accessed later in report definitions and other tasks.
Tasks can include Procedure elements that allow direct manipulation of files on the web server or on network-connected drives. To do this, of course, the account used by the web server to run your Logi application needs to have appropriate file access permissions. Here are the elements available for file system interactions:
Compresses the named file, using the .ZIP format. You must specify both the source and destination file names. Wild cards are allowed, see below. Specify a fully-qualified path and file name.
Compresses the named folder and its contents using the .ZIP format. Maintains the hierarchy of any sub-folders and files within it. You must specify both the source folder name and destination file name. Specify a fully-qualified path and folder name.
Copies a single file. You must specify both the source and destination file names. If it already exists, the destination file is overwritten without warning. Specify a fully-qualified path and file name.
Creates a new file system folder. No error occurs if the folder already exists. Specify a fully-qualified path and folder name.
Deletes a file. No error occurs if the named file does not exist. Specify a fully-qualified path and file name.
Deletes a folder and its contents. No error occurs if the specified folder does not exist. Specify a fully-qualified path and folder name.
Returns True and executes its child elements if the named file is found in the web server file system. Specify a fully-qualified path and file name.
The token @Procedure.<myProcedureElementID>.rdReturnValue~ will return True or False depending on file existence.
Returns True and executes its child elements if the named folder is found in the web server file system. Specify a fully-qualified path and folder name.
The token @Procedure.<myProcedureElementID>.rdReturnValue~ will return True or False depending on folder existence.
Procedure.Run Shell Command
Executes an OS command-line command or application and optionally passes in parameters. See special section below for more information.
Expands a compressed .ZIP file. If no destination folder is specified, the files are written to the application's rdDataCache directory. Wild cards are allowed for selectively identifying files to be uncompressed, see below. You must specify a fully-qualified path and compressed file name.
Expands a compressed folder and its contents. Maintains the hierarchy of any sub-folders and files within it. You must specify both the source file name and the destination folder name and they must include a fully-qualified path.
Allows you to update an XML file from a Process Task. Information about using this element is available in Procedure.XML Modifier.
You can use tokens, such as @Function.AppPhysicalPath~ and @Data.FileName~, to provide the part or all of the file or folder names required in these attributes. Valid characters that can be used in file and folder names are those allowed by the web server operating system.
The wildcards characters * and ? can be used where mentioned in the descriptions above. For example, to compress all
files in a folder, leave the Files To Compress attribute blank or enter *.* and to compress only XML files
that start with an S, enter S*.xml.
Using Procedure.Run Shell Command
The Procedure.Run Shell Command element allows you to run OS shell commands or applications from a task and handle their output.
Commands and applications launched using this element run synchronously and will block the processing of the rest of the task until they complete.
Here are the element's attributes:
(Required) Specifies a unique identifier for this element.
Error Output Filename
Specifies an method of handling error output from a shell command, as follows:
If left blank, the error output can be accessed using the token @Procedure.<myProcedureID>.ErrorOutput~.
Specifies the filename of a shell or application to execute, as follows:
Shell Command Parameters
Specifies a string of parameters for the shell command. In a command line, this is the typically the part of the command that goes after the actual command name. Begin the string with "/C" if using the Windows Command line. Examples, with parameter string highlighted in yellow:
powershell /C Test-NetConnection
Be sure to include any switches needed to suppress any prompts, such as "/Y" in the COPY example above. Otherwise, the task will "hang" indefinitely.
Standard Output Filename
Specifies a fully-qualified path and filename to be used to store the shell command's or application's "standard output". This is the output typically seen when running a shell command from a command prompt. Tokens may be used here.
Specifies the length of time, in seconds, to wait for an action to complete before a timeout error occurs. If set to 0, then the task will wait indefinitely until the request completes. Entering a value here is a good idea, to protect against the task "hanging", but be sure to allow enough time for the shell to launch, interpret and execute the command and any parameters, and return a result. You may wish to experiment with different values and you can enter decimal values less than a whole second, such as 0.001, if appropriate.
Specifies the fully-qualified path to the folder to be used as the context of the shell command or application. Tokens may be used here.
The following tokens are available for use with Procedure.Run Shell Command:
If the element's Error Output Filename attribute has been left blank, this token contains the shell command's or application's error output. If no error has occurred, this token will have no value.
Contains the "exit" or "return" code from the shell command or application, often 0 for success.
If the element's Standard Output Filename attribute has been left blank, this token contains the shell command's or application's standard console output. If there is no standard output, this will have no value.
Contains True if a timeout occurred; otherwise contains False.
USAGE EXAMPLE: RUN A WINDOWS BATCH FILE
In this example, we'll use Procedure.Run Shell Command to run a simple Windows batch file that will "ping" a web site and display some parameters. Here's the batch file contents:
echo %2 %3
As you can see, it expects three parameters.
In the task definition shown above, you can see how the Procedure.Run Shell Command element's attributes are configured. Note the use of a token in the Filename value, and that there are three separate parameters, separated by a space, in the Shell Command Parameters.
Link Parameters are used in our example to pass the four related Procedure tokens to the response report.
The results are displayed in the response report as shown above.
USAGE EXAMPLE: TEST A NETWORK CONNECTION
In this example, we'll use a Windows PowerShell command to retrieve information about the network:
In the task definition shown above, you can see how the Procedure.Run Shell Command element's attributes are configured. Note the use of the shell invocation in the Filename value, and that "/C" is added before the shell command in the Shell Command Parameters.
The results are displayed in the response report as shown above.
For purposes of illustration, let's make the command invalid by adding "x" to it, so the Shell Command Parameters value is "/C Test-NetConnectionx", and re-run the task:
Now we can see that the Exit Code, Standard Output, and Error Output values have changed.
USAGE EXAMPLE: RUN A LINUX COMMAND
In this example, we'll use the Linux "ps" command to display a formatted list of active processes:
In the task definition shown above, you can see how the Procedure.Run Shell Command element's attributes are configured. Note the use of the Linux "ps" command in the Filename value, and the "-ef" flags in the Shell Command Parameters.
The results are displayed in the response report as shown above.
USAGE EXAMPLE: RUN A LINUX COMMAND USING TOKENS
In this example, we'll use the Linux "cp" command to copy a file:
In the task definition shown above, you can see how the Procedure.Run Shell Command element's attributes are configured. Note the use tokens in the Shell Command Parameters value, which in its entirety is:
@Function.AppPhysicalPath~/test.txt @Function.AppPhysicalPath~/test.out -f
The ability to run shell commands can be dangerous, so use this element with care.
You can create tasks that include procedures that export reports or data. This is done in the task by running a "hidden instanced" of an existing Report definition and then exporting it or its data.
There is a difference between exporting reports from a Report definition and from a Process task. An export from a Report definition is written out as a temporaryfile in your application's rdDownload folder and then that file is opened for viewing in the user's browser. The temporary file is automatically deleted later. An export from a Process task is saved as a file in a location, and with a filename, you specify and it's not opened automatically in the browser. It's not considered a temporary file, so it's not deleted later automatically; you may have to manage it separately.
So, exporting from a Process task is useful when you need to save a file to the web server for later use, such as:
- Archiving data or reports
- Creating attachments to be sent with e-mails
- Building a custom Data Cache (XML export) that can be used later by your reports
More information about exporting can be found in our export topics.
As shown in the example above, an export procedure such as Procedure.Export PDF is added to a task, and its Filename attribute is set to the fully-qualified path for the export file, including the file name and extension. The account being used to run the Logi app must have Write permissions to the storage location (usually this is already in place if you're saving to any folder within your application folder), and the @Function token for the application path can be used here, as shown above.
The Target.PDF element can be used to specify the Report Definition File to be exported. If not specified, the "Current Report" definition - the one that called the task - will be exported. Why have an option? You may have created two similar definitions - one for browsing and one for exporting.
If you specify a table in the Target.PDF element's Data Table ID attribute, then just that table's data (without headers, footers, etc.) will be exported. See Logi Studio's Information Panel text for more information about other Target element attributes that are specific to different export types.
If the original report depended on Request variables to set queries, filtering, etc. then be sure to either set the Target element's Request Forwarding attribute to True, or to use Link Parameters, to ensure that the exported file is similarly configured.
The elements for exports to other formats (Word, Excel, CSV, etc.) operate in a similar fashion.
DevNet includes a sample application that demonstrates exporting using process tasks.
The Local Data element is available for use in Process definitions.
It operates in them in the same manner that it does when used in Report definitions and the data its datalayer retrieves can be accessed from any task in the Process definition using an @Local Data token. For a full explanation of this element, see our Datalayer Introduction document.
Tasks also provide the ability to interact with SQL databases, including the so-called "write-back" capability required to update databases. Both SQL Queries and Stored Procedures are supported, with special elements, and all valid SQL commands, including INSERT, UPDATE, and DELETE, can be used.
Using SQL Statements
Implementing a direct SQL statement in Process task is easy and tokens can be used to "parameterize" the statement:
In the example shown above, we see a task that includes the Procedure.SQL element. The complete SQL Command in the example is:
UPDATE Products SET UnitsInStock = @Request.inpHidden~ WHERE ProductID = @Request.ProductID~
Any valid SQL statement can be executed. The Handle Quotes Inside Tokens attribute handles tokens that might have embedded single quotes, such as the text Trail's Head. When set to True, token values in the SQL Command will be wrapped in single-quotes, "doubling" them so the syntax will be valid. The default for this attribute is False.
Tokens for string values should be wrapped in quotes to conform to your database's SQL syntax. For example, if you'd use quotes in a plain text query with a WHERE clause, like this:
...WHERE user_lastname = 'Smith'
then with tokens it would be:
...WHERE user_lastname = '@Request.UserName~'
The SQL Return Type attribute specifies the return value type of the SQL operation:
- If RowsAffected (the default) is
selected, the operation will return the number of rows changed by
any UPDATE, INSERT, or DELETE commands. You can access this value
later in the task using
the special token:
- If FirstRow is selected, the first row of any result set from the SQL operation is returned. You can access the values of the returned row columns later in the task using tokens in this format:
The example above shows an UPDATE operation but queries using SELECT statements are, of course, also supported. Values returned by a query using Procedure.SQL are limited to those in the first row, as described above. If you want to return multiple rows, use Procedure.Run DataLayer Rows and a datalayer, as described in the next major section below.
The If Error element can be used beneath Procedure.SQL to handle errors that may occur. The actual error message text is available in this token: @Procedure.<yourProcedureSQL_ID>.ErrorMessage
Procedure.SQL elements can also be used beneath Procedure.Run Data Table Rows, Procedure.Run DataLayer Rows, which are discussed in the next major section below.
Using SQL Parameters
The SQL Parameters and SQL Parameter elements can be used to include tokenized parameters, if you prefer not to embed tokens directly into the SQL statement. This approach also allows you to enforce a data type for the parameter value and also offers protection against SQL Injection attacks.
To use parameters, write your SQL statement using "placeholder" notation. The exact syntax for this depends on your database and the Connection element you're using. For example, if you're using Connection.SQLServer, you use this notation:
SELECT * FROM Customers WHERE State=@state AND City=@city
and the ID attribute of each SQL Parameter element must match a placeholder name. So, in the example, the value of an element with an ID of state will replace the @state placeholder at runtime. Note that there is no need to surround the placeholder with quotes, even if it represents string data. The Logi Engine sees the parameter data type in the element attributes and handles it appropriately.
Similarly, if you're using Connection.Oracle, you use this notation:
SELECT * FROM Customers WHERE State=:state AND City=:city
and, as before, the ID attribute of each SQL Parameter element must match a placeholder name.
However, if you're using Connection.OLEDB, you use this notation:
SELECT * FROM Customers WHERE State=? AND City=?
Unlike the previous examples, these are positional parameters so, at runtime, placeholders in the statement will be replaced, starting with the first placeholder, by the values specified in the SQL Parameter elements, based on the elements' top-to-bottom order in the definition. The element IDs are ignored.
The example above illustrates the relationship, in this scenario, between SQL Parameter element order and placeholders in the statement.
SQL Parameters will not work when using Connection.ODBC.
Consult your database documentation for specific placeholder information.
SQL Parameters are especially useful if you're writing string data that includes embedded single quotes to the database. The Logi Engine automatically handles escaping the single quotes in the SQL statement sent to the database server.
Using Stored Procedures
We highly recommend the use of stored procedures, especially when updating the database. It's the most secure method and usually offers the best performance. A stored procedure is code, possibly pre-compiled, that resides on your database server and is called to perform work. It's usually a collection of standard SQL commands.
In the example task above, a Procedure.SP element has been added in order to invoke a stored procedure. Its attributes are set as shown to connect to, and run, the stored procedure. The Command attribute includes a pull-down list of all of the stored procedures available through the database connection specified.
Stored procedures are written using the tools that came with your database server; some servers may accept code written in an external text editor such as Notepad. Logi Studio does not include an editor for writing stored procedures.
Two other types of elements can be used if the stored procedure requires parameters: the SP Parameters element, which is just a container, and one or more SP Parameter elements.
The first SP Parameter element has been configured, as shown above, as an Input parameter. It will pass the First Name value from a Request variable to the stored procedure. Its Direction attribute is set to Input, and its Size attribute value is set to 0, which causes it to be adjusted to the correct size automatically at runtime. Other SP Parameters will be configured similarly, to pass additional values.
The relationship between parameters in the task definition and the parameters in the stored procedure is determined solely by their order, not by their IDs.
SP Return Values
The Procedure.SP return behavior is controlled by its SP Return Type attribute, which has two possible values:
When configured as ReturnValue (the default) only the value of the first column of the first row of data returned by the stored procedure, if any, is available. Additional columns or rows are ignored. The returned value can be accessed with an @Procedure "rdReturnValue" token, for example: @Procedure.myProcedureId.rdReturnValue~
When configured as FirstRow, the entire first row of data returned by the stored procedure is available. Access the values of the first row with @Procedure tokens. For example: @Procedure.myProcedureId.someColumnName~
Using SP Output Parameters
Another mechanism for returning data is to have the stored procedure return output parameters and the task can be configured to receive them:
To accomplish this, the example task has now been given an SP Parameter element that's configured as an output parameter. Note that its Direction attribute is set to Output. The stored procedure will return a value to the task, using this parameter. In this case, the Size attribute must be set to the number of bytes for its data type, or the maximum expected to be returned.
Once again, the relationship of parameter elements in the task and the stored procedure's output parameters is determined solely by their order, not their IDs.
The value returned in the output parameter is available using a special token, shown below:
A Link Parameters element has been added to the task so that we can pass the results back to a report. Its Status attribute has been configured to use the special token that holds the value passed to the output parameter element. The token format is:
@Procedure.<Procedure.SP Element ID>.<SP Parameter Element ID>~
DevNet includes a sample application that demonstrates the use of a Process task to update a table.
Tasks offer you the ability to retrieve just one row of data, or to iterate through all of the rows in either a datalayer or a data table in a Report definition, processing the data in each row individually.
In a manner similar to the Local Data element, the Procedure.Data element can be used to run a datalayer; the column values from the first datalayer row (only) can then be accessed in the task using this token: @Procedure.<Procedure.Data element ID>.<column name>~.
The examples below show you how to iterate through multiple datalayer or data table rows :
In this example task, we'd like to look through a contact database table and send out an email newsletter for every record that has an email address. Here's a description of the purpose of each element used:
- The Procedure.Run Data Layer Rows element is the parent container that causes the iteration through each row in the datalayer once data has been retrieved.
- A DataLayer.SQL element is used to query the database table, returning all of the records into the datalayer. Other elements beneath the Procedure.Run Data Layer Rows element can access data values in the datalayer using standard @Data tokens.
- The Procedure.If element is configured so that its child element, Procedure.Send Mail, will run only if the email address column in the current datalayer row is not Null.
- The Procedure.Send Mail element uses the token @Data.EmailAddress~ in its To Email Address attribute to send out an email for the current datalayer row.
- The Response.Report element, of course, redirects processing somewhere else when the task completes.
Let's look at another example: imagine a report definition that includes a data table and one of its columns has an Input Text element displayed in every row, like this:
At runtime, the user can enter numbers to adjust the table values. But, how would you update the database after multiple changes have been made and the page is submitted? That's right - you can do it with a task.
Here's a description of the elements needed:
- The Procedure.Run Data Table Rows element is the parent container that causes the iteration through each row in the data table named in its Data Table ID attribute. If the attribute is left blank, the first table found in the application that includes user input elements will be used.
- The Procedure.SQL element is used to issue an UPDATE command to the database, using an @Request token to access the value of the Input Text element for each table row.
- The Response.Report element, of course, redirects processing somewhere else when the task completes.
Please note these two important limitations:
- Interactive Paging should not be used with data tables being processed using Procedure.Run Data Table Rows. If possible, use input elements and datalayer filtering elements instead to limit the amount of data in the table.
- Input Checkboxes should not be the sole Input element within a data table row when using Procedure.Run Data Table Rows. This Input element is unusual in that it does not submit a Request variable value at all if the box is not checked and, when this is the only Input element in the table, it will cause Procedure.Run Data Table Rows to only "see" the rows that are selected, creating an incorrect listing of the rows. To avoid this, you can include an Input Hidden element within the table that stores a unique ID for each row. This will ensure that each row is represented by a Request variable and gets processed by Procedure.Run Data Table Rows.
A process task also gives you the ability to send email messages, separately or in bulk.
An example in the previous section demonstrated one method of sending out a mass mailing, but there's a second method you may want to use instead.
- Add a Procedure.Send Mail element to your task, as shown above, and set its attributes as desired to configure the message to be sent. Note that the actual message (the "Email Body") can be formatted as Plain Text or HTML. Use @Data tokens to reference the data values that will be coming from your data source.
- Beneath it, add a Bulk Email Data Layer element, which iterates through its child datalayer rows.
- Beneath it, add an appropriate datalayer element to retrieve the data with the addressing information. If possible, use a query that includes a filter to eliminate records that have Null email addresses.
- Optionally, add one or more Attachment elements beneath the Procedure.Send Mail element. Set its Filename attribute to the fully-qualified file path and file name of the file to be attached. Note that the @Function token for your application folder can be used here, as shown above. Set the Display Name attribute to the text that you wish to appear identifying the attachment in the recipient's mail reader.
Keep in mind that your mail server may impose restrictions on the size of file attachments.
Procedure.Send Mail element supports TLS/SSL encryption, allowing, for example, GMail to be used as an SMTP server. Set the related Connection.SMTP element's SMTP Authentication Method attribute to 3 to invoke this, and its SMTP Port attribute may need to be set to 587.
When sending email from a Java application to an older SMTP server, attachments with long file names (> 60 chars.) result in a split name that cannot be clicked to be viewed by the recipient. To solve this, keep attachment names short, or add this JVM option:
Sending out thousands of emails may have an impact on your network bandwidth and your email server performance, so use caution before "opening the floodgates" and sending out a zillion messages!
DevNet includes a sample application that demonstrates the use of a process task to send email.
The Procedure.REST element can be used to interact with a REST-style web service from within a process task. Typically, this would be to send a request that invokes an HTTP PUT or DELETE method, but GET and POST are also supported.
If you're trying to communicate with a web service that requires the TLS 1.1 or 1.2 protocol, you will need to use Logi Info v12.2-SP4 or later (earlier versions only support TLS 1.0). In addition, Info Java applications must use Oracle JDK 1.8 or OpenJDK 8 to make the protocol work.
The Procedure.REST element has attributes that are similar to those of DataLayer.REST:
(Required) Specifies a unique element ID.
Specifies the type of data expected to be received from a REST request. Options include application/json and application/xml (the default).
Specifies the ID of a Connection.REST element defined in the _Settings definition.
Specifies the verb to be sent with a REST request. Standard options include: DELETE, GET, POST, and PUT, and you can also enter custom verbs, like PATCH, if necessary. The default value is GET.
Specifies a unique element ID. You'll need to provide this if you want to use tokens to get a returned code or description.
Specifies whether the namespace and schema information that some data sources will add to the retrieved data is removed. The default value is False.
Specifies the portion of the URL that will be appended to the end of the URL specified in the Connection.REST element's Url Host attribute and may need to begin with a "/". For example,
Connection.RESTUrl Host = http://local.yahooapis.com
producing this complete URL to request the web service method:
You can reference the web service's response code and description with these Procedure tokens:
Procedure.REST can also use the Http Body child element, which has two attributes:
- Content Type, which sets the content type in the request header and defaults to application/x-www-form-urlencoded.
- Http Body Content, which is the request body data, entered as an XML or JSON document or as a URL-encoded set of name/value pairs.
If you want to encode name/value pairs in the request body data to avoid possible issues with invalid characters, ensure that the Http Body element's Content Type attribute is blank or set to application/x-www-form-urlencoded and use the Http Body Params element to define the pairs. Tokens may be used in Http Body Param values.
Error handling is an important function for any application and tasks include a special element for this purpose.
The If Error element allows you to handle errors that occur when running procedures in a task. The example above shows a typical implementation: if an error occurs when a table update is attempted, an email alert will be sent out and a redirect to a report page will occur (possibly back to the page that called the task). The actual error text can be passed to that report page, using a Link Parameters element, as a Request variable.
The placement of the If Error element is important. Errors will "bubble up" through procedures until an If Error element is found, and if not found, up through tasks and the definition itself. You have the choice of placing your error handling elements in different locations to handle different situations. Without an If Error element, the application will return an error page if an error occurs.
You may use multiple If Error elements in a task, if desired. As mentioned in the previous paragraph, you can access the error message text. This is done using this special token: @Procedure.yourProcedureID.ErrorMessage~
Because the element ID of the procedure is part of the token, it limits the scope of the error message availability. You can also use: @Function.LastErrorMessage~ if you prefer, and its scope is application-wide.
The If Error element has an Error Filter attribute, which allows individual If Error elements to handle different errors. Set the Error Filter attribute value to any text found within the error message. If the text is found, the If Error element will handle the error. If not, the error will be ignored and the error will "bubble up". This allows you to target specific errors, and to react to them differently, if desired. If you use this approach, you'll probably want to include a final If Error element without any Error Filter text, to catch any errors not specifically handled by your other handlers.
The Error Filter also allows you to ignore errors, by specifying their error message text and then placing no child elements beneath the If Error element. When that error occurs, it will be considered "handled" and processing will continue with the next element after the failed procedure element.
Note that the If Error element only recognizes errors that occur in the process task and will not react to those that occur in a report definition run by the task. For example, if a task uses Procedure.Export CSV to export data from a report definition to CSV and an error occurs when the report is run, If Error will not see it. In this case, you can use If Data Error in the report definition to provide alternate data when the report is exported, then Procedure.Run DataLayer Rows to read the exported file, test its data, and take appropriate action.