# 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
1
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 Object
  • OBJECT_SINGLE_MULTIPLE Can run on one or multiple Objects
  • OBJECT_MULTIPLE Can run on multiple Objects
  • CLASS_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 object
  • domainClass: Domain object
  • displaySequence: The display order of this Action in the interface. The smaller the displaySequence value, the more forward it is displayed
  • group: 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 object
  • ownerClassName: The type of the main object
  • columnNameInOwnerClass: 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 the Order object associated with the currently selected OrderItem object
  • ownerClassName: The type of the Order object
  • columnNameInOwnerClass: The property name of the OrderItem object in the Order 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]
1
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 started
  • RUNNING Execution in progress
  • SUCCESS Execution successful
  • FAILED Execution failed
  • SUCCESS_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:

  1. 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.

  2. If the Core Logic of the Dynamic Action has not defined a Post Logic, the following return logic will be followed:

  3. 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.

  4. 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.

  5. The SystemError stream output redirected to standard output will be captured in the execLog of the execution result as the execution log.

  6. 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:

  1. 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"
]
1
2
3
4
5
6
7
8
9
10
  1. 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 CustomLogicWarningException CustomLogicWarningException(String message, Object data), passing data as the result to the execution framework. The execution framework will save this information in the execution result field execResult.

  2. 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 the getMessage() method of the exception, or if getMessage() returns empty, the return value of the toString() 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
}
1
2
3
4
5
6
7
Last Updated: 12/4/2024, 1:00:56 PM