You can create a plugin to implement a custom Action to use in your Rules.
First Steps
- Read the dynamic plugins (OSGI) documentation and documentation on how to set up an OSGi plugin environment.
- Review the example Rules Engine OSGi Actionlet Plugin under /docs/examples/osgi/com.dotcms.ruleengine.actionlet in the dotCMS release.
- Read the following sections for more detailed information.
Note: Rule Action types ('Actionlets') and Rule Condition types ('Conditionlets') are very similar in their implementation. The main difference between the two is that the evaluate()
method of an Action type is expected to have side effects, while there should be no side effects to the evaluate()
method of a Condition type.
Create the Plugin
The class that extends a rules engine Actionlet is named: com.dotmarketing.portlets.rules.actionlet.RuleActionlet.
Any custom Rule Action type must:
- Provide a name (i18nKey) and zero or more ParameterDefinitions to the superclass constructor,
protected RuleActionlet(String i18nKey, ParameterDefinition... parameterDefinitions)
- The Rule Action type should generally be fully configured at creation time.
- That is to say, when the constructor exits, the Action type should be 'fully defined'.
- While it is possible to override the
public Map<String, ParameterDefinition> getParameterDefinitions()
method in order to dynamically update the parameter definitions based on current system state, it is discouraged.- Instead, consider using or creating new
InputElements
that define where and how to gather dynamic data. - For an example, see the internal class
com.dotmarketing.portlets.rules.actionlet.PersonaActionlet
and its use of the ReST-populated dropdown inputcom.dotmarketing.portlets.rules.parameter.display.RestDropdownInput
.
- Instead, consider using or creating new
- Note: Please see the conditionlet plugin documentation for more information on
ParameterDefinition
classes and thei18nkey
.
- The Rule Action type should generally be fully configured at creation time.
- Implement the method
public Instance instanceFrom(Map<String, ParameterModel> parameters)
- An 'Instance' is a container for validated parameters.
- This method is called when an instance of your Action is saved (e.g. when modified from the User Interface) as well as when writing data to the database.
- Expensive operations should be performed in this method if possible (rather than evaluate()), as this method is called much less frequently than the
evaluate(...)
method.
- Implement the abstract method
public boolean evaluate(HttpServletRequest request, HttpServletResponse response, Instance instance)
- The evaluate() method performs the check that forms the basis for the Action. This can happen as frequently as multiple times per request to your active site, depending on number of rules and their configurations.
- The evaluate() method is provided the Instance that was generated by
instanceFrom
, as well as the Request and Response objects. - The return value should indicate success (true) or acceptable failure due to a known and permissible 'error' state (false).
- Throwing exceptions for states that are predictable and handleable is discouraged, as future implementations are likely to disable Rules that fail to evaluate after some configurable number of consecutive exceptions.
- Legitimately invalid states SHOULD throw exceptions, as a Rule that is executing frequently and not performing an expected action SHOULD be disabled so it will not cause unwanted side effects and/or performance degregation.
Build the Plugin
Build the plugin using gradle:
./gradlew jar
Upload the Plugin
Upload the JAR file created by the plugin build](#Build) to dotCMS, using the Dynamic Plugins admin portlet.
JSON Output
The JSON output from a sample action type will be similar to the following: :
{
"SetResponseHeaderActionlet":{
"id":"SetResponseHeaderActionlet",
"i18nKey":"api.system.ruleengine.actionlet.SetResponseHeader",
"parameterDefinitions":{
"headerKey":{
"key":"headerKey",
"i18nBaseKey":null,
"defaultValue":"",
"inputType":{
"id":"text",
"dataType":{
"id":"text",
"errorMessageKey":"api.system.type.text",
"minLength":1,
"maxLength":255,
"defaultValue":""
},
"placeholder":""
},
"priority":1
},
"headerValue":{
"key":"headerValue",
"i18nBaseKey":null,
"defaultValue":"",
"inputType":{
"id":"text",
"dataType":{
"id":"text",
"errorMessageKey":"api.system.type.text",
"minLength":0,
"maxLength":255,
"defaultValue":""
},
"placeholder":""
},
"priority":2
}
}
}
}
Note that there are two parameters, one for the 'headerKey' and one for the 'headerValue.