# Dynamic Actions
The powerful dynamic action subsystem is one of the core functionalities of this system. Through dynamic actions, users can define various operations within the system.
# Definition
Dynamic actions are injected into the system using Dynamic Action objects. These objects
can be created directly through the interface menu Development > Dynamic actions
, where
users can input the execution code for the Action. Alternatively, Action definitions can
be imported via CSV files.
The fields for creating an Action object are detailed as follows:
Name: Name, non-empty and unique
Label: Label displayed in the interface
Description(helpText): Description, also used as help information displayed to users in the frontend
Organization: The organization to which the Action belongs
Icon: Display icon
Enable logic: Dynamic logic for enabling, see the documentation below for injectable variables and return value conventions
Core logic: Specific execution dynamic logic, only effective for groovy-type Actions, see the documentation below for injectable variables and return value conventions
Mode: Action mode, see details in the documentation below
async: Whether it's an asynchronous Action. Asynchronous Actions execute in the background without blocking the frontend interface. Upon completion, a system message is sent to the user
Support result tuning: Whether result tuning is supported
Confirm Type: How to display confirmation or prompt information to users before execution in the frontend
Confirm message: Confirmation and prompt message text displayed to users before execution in the frontend
Enable for roles: Which role users to enable for
2
3
4
5
6
7
8
9
10
11
12
13
# Scope (Action Modes)
Currently supported modes are as follows:
OBJECT_SINGLE
Can run on a single ObjectOBJECT_SINGLE_MULTIPLE
Can run on one or multiple ObjectsOBJECT_MULTIPLE
Can run on multiple ObjectsCLASS_LEVEL
Can act on a certain Domain, rather than specific objects
# Prompt Information Display Modes
Currently supported prompt information display modes are as follows:
NO_CONFIRM
No prompt needed. The Action runs directly after the user clicks the Action link in the frontend.NO_POPUP_NO_CONFIRM
Does not pop up the running Popover control. After clicking, it directly calls the backend API to run the Action, and refreshes the Action list upon completion.DISPLAY_CONFIRM
Displays a confirmation control in the frontend. The user needs to click the confirm button on this confirmation control before the Action is executed.
# Support for Result Tuning
When defining an Action, you can set whether result tuning is supported during the Action execution. This feature is mainly used for result tuning when the Action calls a large language model.
# Association between Action and Domain
Dynamic Action itself is not directly associated with Domain. The association is made through the
DynamicActionDomainClass
object, which contains the following fields:
dynamicAction
: Dynamic Action objectdomainClass
: Domain objectdisplaySequence
: The display order of this Action in the interface. The smaller the displaySequence value, the more forward it is displayedgroup
:DynamicActionGroup
object, representing the grouping of this Action in the interface. Actions in the same group will be displayed in the same dropdown menu.
# Enable Logic
Before returning the Action list to the frontend, the system will run the Enable Logic code defined
in the Action to determine whether the Action is enabled for the current scenario. The Enable Logic
is defined in the system as DynamicLogic with Logic Type DYNAMIC_ACTION_ENABLE_LOGIC
.
# Injected Variables
When the code runs, the system will inject the following context variables
Variable Name | Variable Type | Description |
---|---|---|
userContext | grails.plugin.springsecurity.userdetails.GrailsUser | Current operating user information |
application | grails.core.GrailsApplication | Current grails application context |
action | tech.muyan.dynamic.action.DynamicAction | Running action definition |
objectIds | List<java.lang.Long> | List of target domain object ids |
objects | List<? extends GormEntity> | List of target domain objects |
objectType | tech.muyan.DomainClass | Type information of target domain object |
parameters | Map<String, Object> | Action running parameters input by users from the frontend (only available in core Logic) |
ownerInfo | tech.muyan.importexport.OwnerInfo | The associated main object of the current display list |
log | Closure<?> | Log closure for printing execution logs |
For information about display icons, please refer to the Icon Description section
ownerInfo
parameter explanation: If the current display and execution context is when displaying the
associated objects list of a main object, the ownerInfo
parameter will contain the following information:
ownerId
: The id of the main objectownerClassName
: The type of the main objectcolumnNameInOwnerClass
: The property name of the associated object in the main object
Example: If the current display is the OrderItem
list of an Order
object, then the ownerInfo
parameter
will contain the following information:
ownerId
: The id of theOrder
object associated with the currently selectedOrderItem
objectownerClassName
: The type of theOrder
objectcolumnNameInOwnerClass
: The property name of theOrderItem
object in theOrder
object
Note
The parameters
parameter is only injected during core logic execution. It is not injected during
enable Logic execution because enable Logic is used to determine whether the Action is available and
does not require user input parameters.
Caution
For scenarios where multiple records are selected to display the Action list or execute the Action, the objects injected into the execution code are a list of selected objects.
When displaying the Action list or executing the Action on a single object, the passed objects parameter is also an array, but with only one element.
Caution
In the following scenarios, when running Enable Logic code to get the available Action list, the injected objectIds and objects are empty. When implementing Enable Logic, care should be taken to accommodate this scenario.
- When users enter the list page and the frontend retrieves the available CLASS_LEVEL Action list;
For scenarios where Actions are run on multiple selected records, the system will display the full
set of available Actions in OBJECT_SINGLE
, OBJECT_SINGLE_MULTIPLE
, and OBJECT_MULTIPLE
modes
after Enable Logic judgment.
Note
When importing Action definitions in CSV files, the Description field should use helpText as the column name
# Return Result
The structure of the return result after Enable Logic runs is as follows
// 表示该 action 或 task 或 widget 是否启用
// Indicates whether this action or task or widget is enabled
[result: true | false]
2
# Execution and Result Return
The execution results are saved in the DynamicActionExecRecord
object. The possible states of action
execution are:
NOT_START
Execution has not startedRUNNING
Execution in progressSUCCESS
Execution successfulFAILED
Execution failedSUCCESS_WITH_WARNING
Execution completed but with warnings
# GROOVY_CODE Actions
# Injected Variables
For GROOVY_CODE type Actions, the specific execution logic is defined as a Dynamic Logic with Type
DYNAMIC_ACTION_LOGIC
. During execution, the system will inject the following context variables
Variable Name | Variable Type | Description |
---|---|---|
userContext | grails.plugin.springsecurity.userdetails.GrailsUser | Current operating user information |
application | grails.core.GrailsApplication | Current grails application context |
action | tech.muyan.dynamic.action.DynamicAction | Current action definition to be judged |
object | <? extends GormEntity> | Current domain object to be judged |
objectType | tech.muyan.DomainClass | Type information of the current domain object to be judged |
classLoader | java.lang.ClassLoader | ClassLoader of the caller running customized code |
log | Closure<?> | Log closure for printing execution logs |
# Return Result
For the convention of return results, please refer to the Execution Result Return Convention section.
# OS_COMMAND and LLM_ENGINE Actions
# Command Replacement
For Actions with CORE_LOGIC
execution engine of OS_COMMAND
and LLM_ENGINE
type logic definitions,
the system will by default inject the following rules to replace the execution commands during
execution. You can also define a preLogic in Core Logic
to return the replacement context.
Placeholder | Replacement Target |
---|---|
${username} | User's username |
${roles} | User's role list, comma-separated |
${object} | JSON serialized string of Domain Object |
${parameterName} | User input parameters passed from the frontend |
TIP
For date type parameters, when doing parameter replacement, the "yyyy-MM-dd HH:mm:ss z"
format will
be used to format the user input parameters.
# Result Saving
After the execution of an OS_COMMAND
type Action, the system will automatically capture the command line
output as the result, following these specific rules:
If the Core Logic of the Dynamic Action has defined a Post Logic, the result of the Post Logic execution will be used as the return value. For details on Post Logic execution, refer to the Post-processing section.
If the Core Logic of the Dynamic Action has not defined a Post Logic, the following return logic will be followed:
If the command's exit code is 0, and no exceptions were caught by the execution framework during the process, the execution result will be
SUCCESS
.If the command's exit code is non-zero, and no exceptions were caught by the execution framework during the process, the execution result will be
SUCCESS_WITH_WARNING
.The SystemError stream output redirected to standard output will be captured in the execLog of the execution result as the execution log.
The SystemOut stream output redirected to standard output will be captured in the execResult of the execution result as the execution result.
# Post-processing
For OS_COMMAND
and LLM_ENGINE
type Actions, their CORE_LOGIC can be associated with post-processing logic
to handle the results of external command execution. The system will pass the execution result of Core Logic
along with the following variables to the post-processing logic:
Variable Name | Variable Type | Description |
---|---|---|
userContext | grails.plugin.springsecurity.userdetails.GrailsUser | Current operating user information |
application | grails.core.GrailsApplication | Current grails application context |
action | tech.muyan.dynamic.action.DynamicAction | Current action definition to be judged |
object | <? extends GormEntity> | Current domain object to be judged |
objectType | tech.muyan.DomainClass | Type information of the current domain object to be judged |
stdout | java.lang.String | Standard output stream of the external command execution |
stderr | java.lang.String | Standard error output stream of the external command execution |
classLoader | java.lang.ClassLoader | ClassLoader of the caller running customized code |
log | Closure<?> | Log closure for printing execution logs |
For the convention of return results from post-processing logic, please refer to the Execution Result Return Convention section.
# Execution Result Return Convention
The convention for the return result of Action execution is as follows:
- If the code executes normally and returns without warnings or errors, the execution code should return a result object with the following structure:
// execResult 为字符类型
// execResult is of string type
// redirect 为字符类型
// redirect is of string type
[
execResult: "执行的结果/Execution result",
redirect: "执行后的跳转页面/Page to redirect to after execution",
//类型为tech.muyan.storage.StorageFieldValue
//Type is tech.muyan.storage.StorageFieldValue
download: "执行后返回前端的文件/File returned to the frontend after execution"
]
2
3
4
5
6
7
8
9
10
If during the code execution, you want to set the status of this Action as successful but with warnings, the execution code should throw a
tech.muyan.exception.CustomLogicWarningException
. If you also want to return execution results, you can call the constructor of CustomLogicWarningExceptionCustomLogicWarningException(String message, Object data)
, passing data as the result to the execution framework. The execution framework will save this information in the execution result fieldexecResult
.If any exception other than
tech.muyan.exception.CustomLogicWarningException
is thrown during code execution, the system will mark the execution result of this Action as failed, and record the return value of thegetMessage()
method of the exception, or ifgetMessage()
returns empty, the return value of thetoString()
method in the execution Log.
# Frontend Redirect Implementation
If you want to redirect to a specified page in the frontend after the code execution is complete, you need
to include an element with key redirect
and value of type String in the returned result Map.
# File Download Implementation
If you want to return a file for user download after the code execution is complete, you need to include
an element with key download
and value of type tech.muyan.storage.StorageFieldValue
in the returned
result Map.
# Available extInfo List
The following is a list of available extInfo for DynamicAction, used to control the display and execution behavior of DynamicAction
{
/** 前台是否显示该 Action 的 label, 默认为 true, 如果只希望显示 Action 图标,可设置 displayLabel 为 false */
/** Whether to display the label of this Action in the frontend, default is true. If you only want to display the Action icon, you can set displayLabel to false */
"displayLabel"?: true | false,
/** 是否在执行该 Action 后,刷新当前页面, 默认为 true, 如果 action 执行不更新显示数据,可以无需刷新页面 */
/** Whether to refresh the current page after executing this Action, default is true. If the action execution does not update display data, you can choose not to refresh the page */
"refreshPage"?: true | false
}
2
3
4
5
6
7