In Questetra BPM Suite, you can use Spring Expression Language (SpEL) in the [Data Update] step and various configuration expressions to reference and manipulate data item values. This article explains how each data type is represented as an object in SpEL and describes the key methods available.
Accessing Data Items
Access the value of a data item using #fieldName. You can find the field name in the app's "Data Items" settings.
If a data item has not been filled in, its value will be null. Calling a method on null will cause an error, so it is generally recommended to use the ?. (null-safe operator) when calling methods.
When chaining multiple method calls, it is also recommended to add ?. to each call in the chain, as any method after the first ?. may also return null.
// Causes an error if q_Assignee is empty (null) #q_Assignee.getName() // Returns null safely if the value is null (no error) #q_Assignee?.getName() // Use ?. on each method when chaining calls #q_Date?.addMonths(1)?.getFirstDateInMonth()
SpEL Expressions and SpEL Templates
How you write values in the Update Data step depends on the destination data type.
| Destination Data Type | Syntax |
|---|---|
| String / Subject |
SpEL Template: content inside #{...} within the text is evaluated as SpEL |
| Date / Datetime / Select / User / Organization | SpEL Expression: the entire field is evaluated as a SpEL expression |
| Numeric | Not SpEL — uses a dedicated numeric expression syntax (→ R2270) |
// String / Subject: text outside #{...} is output as-is; multiple expressions can be combined
Applicant: #{#q_Assignee?.getName()}, Request No.: #{processInstanceId}
// Date / Datetime: write the expression directly (#{...} is not needed)
#q_ApplyDate?.addDays(7)
// Select: write a string expression that resolves to an option ID
#q_OtherSelect
Property Shorthand (Getter Shorthand)
In SpEL, methods like getXxx() can be written in shorthand as .xxx (both are equivalent).
// These two expressions are equivalent
#{#q_Assignee?.getName()}
#{#q_Assignee?.name}
Collection Operators (Applicable to Lists: Select, File, and Table Types)
| Operator | Description | Example |
|---|---|---|
.?[condition] |
Filters elements matching the condition | #q_Tags?.?[getValue() == 'urgent'] |
.![expression] |
Returns a new list by transforming each element | #q_Tags?.![getValue()] |
.size() |
Returns the number of elements | #q_Tags?.size() |
The Table type (ScriptListArray) is not a List itself, but you can apply collection operators to the List<ScriptListRow> returned by .getRows().
// [Value expression] Get values from a specific column across all rows in a Table type
// (Access ScriptListRow cells using ['fieldName']; see the "Table Type" section for details)
#q_Items?.rows?.![#this['name']]
// [Embedding in a String field] File type: list of filenames for PDF files only
#{#q_Files?.?[getContentType() == 'application/pdf']?.![getName()]}
Data Types and Corresponding Java Classes
| Data Type | Java Class |
|---|---|
| String | java.lang.String |
| Numeric | java.math.BigDecimal |
| Select | java.util.List<com.questetra.bpms.core.event.scripttask.ItemView> |
| Date | com.questetra.bpms.util.AddableDate |
| Datetime | com.questetra.bpms.util.AddableTimestamp |
| User | com.questetra.bpms.core.event.scripttask.QuserView |
| Organization | com.questetra.bpms.core.event.scripttask.QgroupView |
| File | java.util.List<com.questetra.bpms.core.event.scripttask.QfileView> |
| Table | com.questetra.bpms.core.event.scripttask.ScriptListArray |
Method Details by Data Type
String Type (String)
This is the standard java.lang.String.
// Copy the value as-is to another field
#{#q_CustomerName}
// Convert to uppercase
#{#q_Code?.toUpperCase()}
// Extract a substring
#{#q_Serial?.substring(0, 5)}
Numeric Type (BigDecimal)
// When embedding in a String field or notification email:
// digit grouping and decimal point follow the data item's display settings.
// Note: prefix/suffix configured on the data item (e.g., currency symbols) are NOT included in the output. Example: 12,345.67
#{#q_Amount}
// Convert to an integer value (truncates the decimal portion)
#{#q_Score?.intValue()}
Select Type (List<ItemView>)
Each element is an ItemView object.
ItemView methods:
| Method | Description |
|---|---|
.getValue() |
Returns the option ID (key string) |
.getDisplay() |
Returns the option label |
// Get the first option ID (single-select)
#{#q_Status?.get(0)?.getValue()}
// Get the first option label
#{#q_Status?.get(0)?.getDisplay()}
// Count the number of selected options
#{#q_Tags?.size()}
// Generate a list of option IDs (returns List<String>; when embedded in a String field, formatted as [id1, id2])
#{#q_Tags?.![getValue()]}
// Single-select: embedded as a single label; multi-select: embedded as labels joined by ", "
#{#q_Status}
Date Type (AddableDate)
For value updates on Date and Datetime fields, use SpEL expressions directly.
Key methods:
| Method | Description |
|---|---|
.addDays(int days) |
Returns an AddableDate with the specified number of days added (use a negative value for past dates) |
.addMonths(int months) |
Returns an AddableDate with the specified number of months added |
.getFirstDateInMonth() |
Returns the first day of the month |
.getLastDateInMonth() |
Returns the last day of the month |
.getFirstDateInWeek() |
Returns the Monday of the week |
.getFirstTimeInDate() |
Returns 00:00:00 of the date as an AddableTimestamp (converts Date type to Datetime type) |
.toString() |
Returns a string formatted according to the subtype (e.g., yyyy-MM-dd for year/month/day) |
// Set the due date to 7 days after the application date
#q_ApplyDate?.addDays(7)
// Set the first day of the following month (calculated as the day after the last day of the current month)
#q_TargetDate?.getLastDateInMonth()?.addDays(1)
// Set the first day of the following month (alternative approach)
#q_TargetDate?.addMonths(1)?.getFirstDateInMonth()
// Convert Date type to Datetime type (returns AddableTimestamp at 00:00:00 of that date)
#q_StartDate?.getFirstTimeInDate()
// To embed a date in a String field or notification email, use #{...} (different from value update usage)
// Embedded as a date string formatted according to the subtype (e.g., yyyy-MM-dd for year/month/day)
#{#q_StartDate}
Datetime Type (AddableTimestamp)
As with the Date type, use SpEL expressions directly for value updates. Use #{...} to embed values in String fields.
Key methods:
| Method | Description |
|---|---|
.addMinutes(int minutes) |
Returns an AddableTimestamp with the specified number of minutes added |
.addHours(int hours) |
Returns an AddableTimestamp with the specified number of hours added |
.addDays(int days) |
Returns an AddableTimestamp with the specified number of days added |
.addMonths(int months) |
Returns an AddableTimestamp with the specified number of months added |
.getFirstTimeInDate() |
Returns an AddableTimestamp reset to 00:00:00 of the same date (resets the time portion) |
.getFirstTimeInWeek() |
Returns 00:00:00 on the Monday of the week |
.getFirstTimeInMonth() |
Returns 00:00:00 on the first day of the month |
.toString() |
Returns a string in yyyy-MM-dd HH:mm format |
// Set the datetime to 24 hours after the received datetime
#q_ReceivedAt?.addHours(24)
// Set to Monday 00:00 of the same week
#q_Deadline?.getFirstTimeInWeek()
// Set to the 1st day of the month at 00:00
#q_Deadline?.getFirstTimeInMonth()
// To embed a datetime in a String field or notification email, use #{...} (different from value update usage)
// Embedded as a datetime string in yyyy-MM-dd HH:mm format
#{#q_Timestamp}
Date vs. Datetime method availability:
addMinutes()andaddHours()are exclusive to the Datetime type and cannot be used with the Date type (AddableDate). Conversely,getFirstDateInMonth(),getLastDateInMonth(), andgetFirstDateInWeek()are exclusive to the Date type and cannot be used with the Datetime type (AddableTimestamp).
User Type (QuserView)
| Method | Description |
|---|---|
.getId() |
Returns the user ID as an integer (Long) |
.getName() |
Returns the user's name |
.getEmail() |
Returns the user's email address |
.isDeletedInFuture() |
Returns true/false indicating whether the user is scheduled for future deletion (true if currently active but set to be deactivated) |
// Embedded as "Name <email>" format (e.g., SUZUKI Ichiro <suzuki@example.com>)
#{#q_Assignee}
// Set the user's name in a String field
#{#q_Assignee?.getName()}
// Set the user's email address in a String field
#{#q_Assignee?.getEmail()}
Organization Type (QgroupView)
| Method | Description |
|---|---|
.getId() |
Returns the organization ID as an integer (Long) |
.getName() |
Returns the organization name |
.getEmail() |
Returns the organization's email address |
.isDeletedInFuture() |
Returns true/false indicating whether the organization is scheduled for future deletion (true if currently active but set to be deactivated) |
// Embedded as "Organization Name <email>" format (e.g., Sales <sales@example.com>)
#{#q_Department}
// Set the organization name in a String field
#{#q_Department?.getName()}
File Type (List<QfileView>)
Each element is a QfileView object.
| Method | Description |
|---|---|
.getName() |
Returns the file name |
.getContentType() |
Returns the Content-Type of the file (e.g., application/pdf, text/plain; charset=UTF-8) |
.getCharset() |
Returns the file's character encoding (the charset parameter from the Content-Type header returned by getContentType(); e.g., UTF-8) |
.getLength() |
Returns the file size in bytes |
// Get the number of attached files
#{#q_Files?.size()}
// Get the name of the first file
#{#q_Files?.get(0)?.getName()}
// Embedded as file names joined by ", "
#{#q_Files}
// Generate a list combining file names and sizes
#{#q_Files?.![getName() + ' (' + getLength() + ' bytes)']}
Table Type (ScriptListArray)
| Method | Description |
|---|---|
.size() |
Returns the number of rows |
.get(int rowIndex, int colIndex) |
Returns the cell value as a string (zero-based index) |
.get(int rowIndex, String fieldName) |
Returns the cell value as a string, accessed by field name |
.getObject(int rowIndex, int colIndex) |
Returns the cell's underlying object (String for String type, BigDecimal for Numeric, ItemView for Select, AddableDate for Date, etc.) |
.getObject(int rowIndex, String fieldName) |
Returns the cell's underlying object, accessed by field name |
.getSummary() |
Returns the sum of Numeric columns (returned in ScriptListRow format; use .get('columnName') to retrieve the BigDecimal value) |
.getRow(int rowIndex) |
Returns the ScriptListRow for the specified row |
.getRows() |
Returns all rows as a List<ScriptListRow> |
ScriptListRow is an object representing a single row of data.
| Access Method | Description |
|---|---|
#this['fieldName'] |
Returns the field value as a string (equivalent to .get('fieldName')) |
.getCol(int colIndex) |
Returns the value of the specified column (zero-based) as a string |
.getCols() |
Returns all column values as a List<String>
|
.getObject(String fieldName) |
Returns the underlying object for the specified column by field name (String for String type, BigDecimal for Numeric, ItemView for Select, AddableDate for Date, etc.) |
.getObject(int colIndex) |
Returns the underlying object for the specified column by index (same types as above) |
.size() |
Returns the number of columns |
// Get the number of rows in the table
#{#q_Items?.size()}
// Get the sum of a Numeric column (specify the column name)
#{#q_Items?.getSummary()?.get('price')}
// Get a Select-type cell as an ItemView and access its label
#{#q_Items?.getObject(0, 'kind')?.getDisplay()}
// Generate a list of strings combining multiple columns from each row
#{#q_Items?.rows?.![#this['name'] + ' | ' + #this['price']]}
// Embedded as a string representing the row count (e.g., 2 row(s))
#{#q_Items}