summaryrefslogtreecommitdiffstats
path: root/src/site-docs/adoc/fragments/howto-write-logic/task-logic.adoc
diff options
context:
space:
mode:
Diffstat (limited to 'src/site-docs/adoc/fragments/howto-write-logic/task-logic.adoc')
-rw-r--r--src/site-docs/adoc/fragments/howto-write-logic/task-logic.adoc177
1 files changed, 177 insertions, 0 deletions
diff --git a/src/site-docs/adoc/fragments/howto-write-logic/task-logic.adoc b/src/site-docs/adoc/fragments/howto-write-logic/task-logic.adoc
new file mode 100644
index 000000000..23a05024d
--- /dev/null
+++ b/src/site-docs/adoc/fragments/howto-write-logic/task-logic.adoc
@@ -0,0 +1,177 @@
+//
+// ============LICENSE_START=======================================================
+// Copyright (C) 2016-2018 Ericsson. All rights reserved.
+// ================================================================================
+// This file is licensed under the CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL LICENSE
+// Full license text at https://creativecommons.org/licenses/by/4.0/legalcode
+//
+// SPDX-License-Identifier: CC-BY-4.0
+// ============LICENSE_END=========================================================
+//
+// @author Sven van der Meer (sven.van.der.meer@ericsson.com)
+//
+
+== Writing APEX Task Logic
+
+Task logic specifies the behavior of an Apex Task.
+This logic can be specified in a number of ways, exploiting Apex's plug-in architecture to support a range of logic executors.
+In Apex scripted Task Logic can be written in any of these languages:
+
+* https://en.wikipedia.org/wiki/MVEL[`MVEL`],
+* https://en.wikipedia.org/wiki/JavaScript[`JavaScript`],
+* https://en.wikipedia.org/wiki/JRuby[`JRuby`] or
+* https://en.wikipedia.org/wiki/Jython[`Jython`].
+
+These languages were chosen because the scripts can be compiled into Java bytecode at runtime and then efficiently executed natively in the JVM.
+Task Logic an also be written directly in Java but needs to be compiled, with the resulting classes added to the classpath.
+There are also a number of other Task Logic types (e.g. Fuzzy Logic), but these are not supported as yet.
+This guide will focus on the scripted Task Logic approaches, with MVEL and JavaScript being our favorite languages.
+In particular this guide will focus on the Apex aspects of the scripts.
+However, this guide does not attempt to teach you about the scripting languages themselves ... that is up to you!
+
+[TIP]
+.JVM-based scripting languages
+====
+For more more information on Scripting for the Java platform see: https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/index.html
+====
+
+[NOTE]
+.What do Tasks do?
+====
+The function of an Apex Task is to provide the logic that can be executed for an Apex State as one of the steps in an Apex Policy.
+Each task receives some _incoming fields_, executes some logic (e.g: make a decision based on _shared state_ or _context_, _incoming fields_, _external context_, etc.), perhaps set some _shared state_ or _context_ and then emits _outgoing fields_.
+The state that uses the task is responsible for extracting the _incoming fields_ from the state input event.
+The state also has an _output mapper_ associated with the task, and this _output mapper_ is responsible for mapping the _outgoing fields_ from the task into an appropriate output event for the state.
+====
+
+First lets start with a sample task, drawn from the "My First Apex Policy" example:
+The task "MorningBoozeCheck" from the "My First Apex Policy" example is available in both MVEL and JavaScript:
+
+.Javascript code for the `MorningBoozeCheck` task
+[source,javascript,options="nowrap"]
+----
+include::{adsite-examples-myfirstpolicy-dir}/main/resources/examples/models/MyFirstPolicy/1/MorningBoozeCheck.js[]
+----
+
+.MVEL code for the `MorningBoozeCheck` task
+[source,java,options="nowrap"]
+----
+include::{adsite-examples-myfirstpolicy-dir}/main/resources/examples/models/MyFirstPolicy/1/MorningBoozeCheck.mvel[]
+----
+
+The role of the task in this simple example is to copy the values in the incoming fields into the outgoing fields, then examine the values in some incoming fields (`item_id` and `time`), then set the values in some other outgoing fields (`authorised` and `message`).
+
+Both MVEL and JavaScript like most JVM-based scripting languages can use standard Java libraries to perform complex tasks.
+Towards the top of the scripts you will see how to import Java classes and packages to be used directly in the logic.
+Another thing to notice is that Task Logic should return a `java.lang.Boolean` value `true` if the logic executed correctly.
+If the logic fails for some reason then `false` can be returned, but this will cause the policy invoking this task will fail and exit.
+
+[NOTE]
+.How to return a value from task logic
+====
+Some languages explicitly support returning values from the script (e.g. MVEL and JRuby) using an explicit return statement (e.g. `return true`), other languages do not (e.g. JavaScript and Jython).
+For languages that do not support the `return` statement, a special field called `returnValue` must be created to hold the result of the task logic operation (i.e. assign a `java.lang.Boolean` value to the `returnValue` field before completing the task).
+
+Also, in MVEL if there is no explicit return statement then the return value of the last executed statement will return (e.g. the statement a=(1+2) will return the value 3).
+====
+
+Besides these imported classes and normal language features Apex provides some natively available parameters and functions that can be used directly.
+At run-time these parameters are populated by the Apex execution environment and made natively available to logic scripts each time the logic script is invoked.
+(These can be accessed using the `executor` keyword for most languages, or can be accessed directly without the `executor` keyword in MVEL):
+
+.The `executor` Fields / Methods
+[width="100%",cols="10l,10d,30m,40a",options="header"]
+|====================
+|Name | Type | Java type | Description
+
+|inFields | Fields | java.util.Map <String,Object> |
+The incoming task fields. This is implemented as a standard Java (unmodifiable) Map.
+
+2+| 2+<a|
+*Example:*
+[source,javascript,options="nowrap"]
+----
+executor.logger.debug("Incoming fields: "
+ +executor.inFields.entrySet());
+var item_id = executor.incomingFields["item_ID"];
+if (item_id >=1000) { ... }
+----
+
+|outFields | Fields | java.util.Map <String,Object> |
+The outgoing task fields. This is implemented as a standard initially empty Java (modifiable) Map.
+To create a new schema-compliant instance of a field object see the utility method `subject.getOutFieldSchemaHelper()` below
+
+2+| 2+<a|
+*Example:*
+[source,javascript,options="nowrap"]
+----
+executor.outFields["authorised"] = false;
+----
+
+|logger | Logger | org.slf4j.ext.XLogger | A helpful logger
+
+2+| 2+<a|
+*Example:*
+[source,javascript,options="nowrap"]
+----
+executor.logger.info("Executing task: "
+ +executor.subject.id);
+----
+
+|TRUE/FALSE | boolean | java.land.Boolean | 2 helpful constants. These are useful to retrieve correct return values for the task logic
+
+2+| 2+<a|
+*Example:*
+[source,javascript,options="nowrap"]
+----
+var returnValue = executor.TRUE;
+// functionally equivalent to:
+var returnValueType = Java.type("java.lang.Boolean");
+var returnValue = new returnValueType(true);
+----
+
+|subject | Task | TaskFacade |
+
+This provides some useful information about the task that contains this task logic.
+This object has some useful fields and methods :
+
+[options="compact"]
+- *_AxTask task_* to get access to the full task definition of the host task
+- *_String getTaskName()_* to get the name of the host task
+- *_String getId()_* to get the ID of the host task
+- *_SchemaHelper getInFieldSchemaHelper( String fieldName )_* to get a `SchemaHelper` helper object to manipulate incoming task fields in a schema-aware manner
+- *_SchemaHelper getOutFieldSchemaHelper( String fieldName )_* to get a `SchemaHelper` helper object to manipulate outgoing task fields in a schema-aware manner, e.g. to instantiate new schema-compliant field objects to populate the `executor.outFields` outgoing fields map
+
+2+| 2+<a|
+*Example:*
+[source,javascript,options="nowrap"]
+----
+executor.logger.info("Task name: "
+ +executor.subject.getTaskName());
+executor.logger.info("Task id: "
+ +executor.subject.getId());
+executor.logger.info("Task inputs definitions: "
+ +"executor.subject.task.getInputFieldSet());
+executor.logger.info("Task outputs definitions: "
+ +"executor.subject.task.getOutputFieldSet());
+executor.outFields["authorised"] = executor.subject
+ .getOutFieldSchemaHelper("authorised")
+ .createNewInstance("false");
+----
+
+3+l|ContextAlbum getContextAlbum(
+ String ctxtAlbumName ) |
+A utility method to retrieve a `ContextAlbum` for use in the task. This is how you access the context used by the task. The returned `ContextAlbum` implements the `java.util.Map <String,Object>` interface to get and set context as appropriate. The returned `ContextAlbum` also has methods to lock context albums, get information about the schema of the items to be stored in a context album, and get a `SchemaHelper` to manipulate context album items. How to define and use context in a task is described in the Apex Programmer's Guide and in the My First Apex Policy guide.
+
+2+| 2+<a|
+*Example:*
+[source,javascript,options="nowrap"]
+----
+var bkey = executor.inFields.get("branch_ID");
+var cnts = executor.getContextMap("BranchCounts");
+cnts.lockForWriting(bkey);
+cnts.put(bkey, cnts.get(bkey) + 1);
+cnts.unlockForWriting(bkey);
+----
+|====================
+