blob: fe3cd0d0d0474da2f48aa76d60577c6f5ce34b4f [file] [log] [blame]
ramvermaaf74a622018-07-31 18:25:39 +01001//
2// ============LICENSE_START=======================================================
3// Copyright (C) 2016-2018 Ericsson. All rights reserved.
4// ================================================================================
5// This file is licensed under the CREATIVE COMMONS ATTRIBUTION 4.0 INTERNATIONAL LICENSE
6// Full license text at https://creativecommons.org/licenses/by/4.0/legalcode
7//
8// SPDX-License-Identifier: CC-BY-4.0
9// ============LICENSE_END=========================================================
10//
11// @author Sven van der Meer (sven.van.der.meer@ericsson.com)
12//
13
14== Logic Cheatsheet
15
16Examples given here use Javascript (if not stated otherwise), other execution environments will be similar.
17
18
19=== Add Nashorn
20
21First line in the logic use this import.
22
23.JS Nashorn
24[source,javascript,options="nowrap"]
25----
26load("nashorn:mozilla_compat.js");
27----
28
29
30=== Finish Logic with Success or Error
31
32To finish logic, i.e. return to APEX, with success use the following lines close to the end of the logic.
33
34.JS Success
35[source,javascript,options="nowrap"]
36----
37var returnValueType = Java.type("java.lang.Boolean");
38var returnValue = new returnValueType(true);
39----
40
41To notify a problem, finish with an error.
42
43.JS Fail
44[source,javascript,options="nowrap"]
45----
46var returnValueType = Java.type("java.lang.Boolean");
47var returnValue = new returnValueType(false);
48----
49
50
51=== Logic Logging
52
53Logging can be made easy using a local variable for the logger.
54Line 1 below does that.
55Then we start with a trace log with the task (or task logic) identifier followed by the infields.
56
57.JS Logging
58[source,javascript,options="nowrap"]
59----
60var logger = executor.logger;
61logger.trace("start: " + executor.subject.id);
62logger.trace("-- infields: " + executor.inFields);
63----
64
65For larger logging blocks you can use the standard logging API to detect log levels, for instance:
66
67.JS Logging Blocks
68[source,javascript,options="nowrap"]
69----
70if(logger.isTraceEnabled()){
71 // trace logging block here
72}
73----
74
75Note: the shown logger here logs to `org.onap.policy.apex.executionlogging`.
76The behavior of the actual logging can be specified in the `$APEX_HOME/etc/logback.xml`.
77
78If you want to log into the APEX root logger (which is sometimes necessary to report serious logic errors to the top),
79then import the required class and use this logger.
80
81.JS Root Logger
82[source,javascript,options="nowrap"]
83----
84importClass(org.slf4j.LoggerFactory);
85var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
86
87rootLogger.error("Serious error in logic detected: " + executor.subject.id);
88----
89
90=== Local Variable for Infields
91
92It is a good idea to use local variables for `infields`.
93This avoids long code lines and policy evolution.
94The following example assumes infields named `nodeName` and `nodeAlias`.
95
96.JS Infields Local Var
97[source,javascript,options="nowrap"]
98----
99var ifNodeName = executor.inFields["nodeName"];
100var ifNodeAlias = executor.inFields["nodeAlias"];
101----
102
103
104=== Local Variable for Context Albums
105
106Similar to the `infields` it is good practice to use local variables for context albums as well.
107The following example assumes that a task can access a context album `albumTopoNodes`.
108The second line gets a particular node from this context album.
109
110.JS Infields Local Var
111[source,javascript,options="nowrap"]
112----
113var albumTopoNodes = executor.getContextAlbum("albumTopoNodes");
114var ctxtNode = albumTopoNodes.get(ifNodeName);
115----
116
117
118=== Set Outfields in Logic
119
120The task logic needs to set outfields with content generated.
121The exception are outfields that are a direct copy from an infield of the same name, APEX does that autmatically.
122
123.JS Set Outfields
124[source,javascript,options="nowrap"]
125----
126executor.outFields["report"] = "node ctxt :: added node " + ifNodeName;
127----
128
129
130=== Create a instance of an Outfield using Schemas
131
132If an outfield is not an atomic type (string, integer, etc.) but uses a complex schema (with a Java or Avro backend), APEX can help to create new instances.
133The `executor` provides a field called `subject`, which provides a schem helper with an API for this.
134The complete API of the schema helper is documented here: link:https://ericsson.github.io/apex-docs/javadocs/index.html[API Doc: SchemaHelper].
135
136If the backend is Avro, then an import of the Avro schema library is required:
137
138.JS Import Avro
139[source,javascript,options="nowrap"]
140----
141importClass(org.apache.avro.generic.GenericData.Array);
142importClass(org.apache.avro.generic.GenericRecord);
143importClass(org.apache.avro.Schema);
144----
145
146If the backend is Java, then the Java class implementing the schema needs to be imported.
147
148The following example assumes an outfield `situation`.
149The `subject` method `getOutFieldSchemaHelper()` is used to create a new instance.
150
151.JS Outfield Instance with Schema
152[source,javascript,options="nowrap"]
153----
154var situation = executor.subject.getOutFieldSchemaHelper("situation").createNewInstance();
155----
156
157If the schema backend is Java, the new instance will be as implemented in the Java class.
158If the schema backend is Avro, the new instance will have all fields from the Avro schema specification, but set to `null`.
159So any entry here needs to be done separately.
160For instance, the `situation` schema has a field `problemID` which we set.
161
162.JS Outfield Instance with Schema, set
163[source,javascript,options="nowrap"]
164----
165situation.put("problemID", "my-problem");
166----
167
168
169=== Create a instance of an Context Album entry using Schemas
170
171Context album instances can be created using very similar to the outfields.
172Here, the schema helper comes from the context album directly.
173The API of the schema helper is the same as for outfields, see link:https://ericsson.github.io/apex-docs/javadocs/index.html[API Doc: SchemaHelper].
174
175If the backend is Avro, then an import of the Avro schema library is required:
176
177.JS Import Avro
178[source,javascript,options="nowrap"]
179----
180importClass(org.apache.avro.generic.GenericData.Array);
181importClass(org.apache.avro.generic.GenericRecord);
182importClass(org.apache.avro.Schema);
183----
184
185If the backend is Java, then the Java class implementing the schema needs to be imported.
186
187The following example creates a new instance of a context album instance named `albumProblemMap`.
188
189.JS Outfield Instance with Schema
190[source,javascript,options="nowrap"]
191----
192var albumProblemMap = executor.getContextAlbum("albumProblemMap");
193var linkProblem = albumProblemMap.getSchemaHelper().createNewInstance();
194----
195
196This can of course be also done in a single call without the local variable for the context album.
197
198.JS Outfield Instance with Schema, one line
199[source,javascript,options="nowrap"]
200----
201var linkProblem = executor.getContextAlbum("albumProblemMap").getSchemaHelper().createNewInstance();
202----
203
204If the schema backend is Java, the new instance will be as implemented in the Java class.
205If the schema backend is Avro, the new instance will have all fields from the Avro schema specification, but set to `null`.
206So any entry here needs to be done separately (see above in outfields for an example).
207
208
209=== Enumerates
210
211When dealing with enumerates (Avro or Java defined), it is sometimes and in some execution environments necessary to convert them to a string.
212For example, assume an Avro enumerate schema as:
213
214.Avro Enumerate Schema
215[source,json,options="nowrap"]
216----
217{
218 "type": "enum",
219 "name": "Status",
220 "symbols" : [
221 "UP",
222 "DOWN"
223 ]
224}
225
226----
227
228Using a switch over a field initialized with this enumerate in Javascript will fail.
229Instead, use the `toString` method, for example:
230
231.JS Outfield Instance with Schema, one line
232[source,javascript,options="nowrap"]
233----
234var switchTest = executor.inFields["status"];
235switch(switchTest.toString()){
236 case "UP": ...; break;
237 case "DOWN": ...; break;
238 default: ...;
239}
240----
241
242
243=== MVEL Initialize Outfields First!
244
245In MVEL, we observed a problem when accessing (setting) outfields without a prior access to them.
246So in any MVEL task logic, before setting any outfield, simply do a get (with any string), to load the outfields into the MVEL cache.
247
248.MVEL Outfield Initialization
249[source,java,options="nowrap"]
250----
251outFields.get("initialize outfields");
252----
253
254
255=== Using Java in Scripting Logic
256
257Since APEX executes the logic inside a JVM, most scripting languages provide access to all standard Java classes.
258Simply add an import for the required class and then use it as in actual Java.
259
260The following example imports `java.util.arraylist` into a Javascript logic, and then creates a new list.
261
262.JS Import ArrayList
263[source,javascript,options="nowrap"]
264----
265importClass(java.util.ArrayList);
266var myList = new ArrayList();
267----
268
269