diff options
Diffstat (limited to 'docs/APEX-User-Manual.rst')
-rw-r--r-- | docs/APEX-User-Manual.rst | 8071 |
1 files changed, 0 insertions, 8071 deletions
diff --git a/docs/APEX-User-Manual.rst b/docs/APEX-User-Manual.rst deleted file mode 100644 index 01f74fabe..000000000 --- a/docs/APEX-User-Manual.rst +++ /dev/null @@ -1,8071 +0,0 @@ -.. This work is licensed under a Creative Commons Attribution 4.0 International License. -.. http://creativecommons.org/licenses/by/4.0 - - -APEX User Manual -**************** - -.. contents:: - :depth: 3 - -Installation -^^^^^^^^^^^^ - -Requirements ------------- - - .. container:: paragraph - - APEX is 100% written in Java and runs on any platform - that supports a JVM, e.g. Windows, Unix, Cygwin. Some - APEX applications (such as the monitoring application) - come as web archives, they do require a war-capable web - server installed. - -Installation Requirements -######################### - - .. container:: ulist - - - Downloaded distribution: JAVA runtime environment - (JRE, Java 8 or later, APEX is tested with the - Oracle Java) - - - Building from source: JAVA development kit (JDK, - Java 8 or later, APEX is tested with the Oracle - Java) - - - A web archive capable webserver, for instance for - the monitoring application - - .. container:: ulist - - - for instance `Apache - Tomcat <https://tomcat.apache.org/>`__ - - - Sufficient rights to install APEX on the system - - - Installation tools depending on the installation - method used: - - .. container:: ulist - - - ZIP to extract from a ZIP distribution - - .. container:: ulist - - - Windows for instance - `7Zip <http://www.7-zip.org/>`__ - - - TAR and GZ to extract from that TAR.GZ - distribution - - .. container:: ulist - - - Windows for instance - `7Zip <http://www.7-zip.org/>`__ - - - RPM to install from the RPM distribution - - .. container:: ulist - - - Install: ``sudo apt-get install rpm`` - - - DPKG to install from the DEB distribution - - .. container:: ulist - - - Install: ``sudo apt-get install dpkg`` - -Feature Requirements -#################### - - .. container:: paragraph - - APEX supports a number of features that require extra - software being installed. - - .. container:: ulist - - - `Apache Kafka <https://kafka.apache.org/>`__ to - connect APEX to a Kafka message bus - - - `Hazelcast <https://hazelcast.com/>`__ to use - distributed hash maps for context - - - `Infinispan <http://infinispan.org/>`__ for - distributed context and persistence - - - `Docker <https://www.docker.com/>`__ to run APEX - inside a Docker container - -Build (Install from Source) Requirements -######################################## - - .. container:: paragraph - - Installation from source requires a few development - tools - - .. container:: ulist - - - GIT to retrieve the source code - - - Java SDK, Java version 8 or later - - - Apache Maven 3 (the APEX build environment) - -Get the APEX Source Code ------------------------- - - .. container:: paragraph - - The first APEX source code was hosted on Github in - January 2018. By the end of 2018, APEX was added as a - project in the ONAP Policy Framework, released later in - the ONAP Casablanca release. - - .. container:: paragraph - - The APEX source code is hosted in ONAP as project APEX. - The current stable version is in the master branch. - Simply clone the master branch from ONAP using HTTPS. - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - git clone https://gerrit.onap.org/r/policy/apex-pdp - -Build APEX ----------- - - .. container:: paragraph - - The examples in this document assume that the APEX source - repositories are cloned to: - - .. container:: ulist - - - Unix, Cygwin: ``/usr/local/src/apex-pdp`` - - - Windows: ``C:\dev\apex-pdp`` - - - Cygwin: ``/cygdrive/c/dev/apex-pdp`` - - .. important:: - A Build requires ONAP Nexus - APEX has a dependency to ONAP parent projects. You might need to adjust your Maven M2 settings. The most current - settings can be found in the ONAP oparent repo: `Settings <https://git.onap.org/oparent/plain/settings.xml>`__. - - .. important:: - A Build needs Space - Building APEX requires approximately 2-3 GB of hard disc space, 1 GB for the actual build with full - distribution and 1-2 GB for the downloaded dependencies - - .. important:: - A Build requires Internet (for first build) - During the build, several (a lot) of Maven dependencies will be downloaded and stored in the configured local Maven - repository. The first standard build (and any first specific build) requires Internet access to download those - dependencies. - - .. important:: - Building RPM distributions - RPM images are only build if the ``rpm`` package is installed (Unix). To install ``rpm`` run ``sudo apt-get install rpm``, - then build APEX. - - .. container:: paragraph - - Use Maven to for a standard build without any tests. - - +-------------------------------------------------------+--------------------------------------------------------+ - | Unix, Cygwin | Windows | - +=======================================================+========================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | :number-lines: | :number-lines: | - | | | - | # cd /usr/local/src/apex-pdp | >c: | - | # mvn clean install -DskipTest | >cd \dev\apex | - | | >mvn clean install -DskipTests | - +-------------------------------------------------------+--------------------------------------------------------+ - -.. container:: paragraph - - The build takes 2-3 minutes on a standard development laptop. It - should run through without errors, but with a lot of messages from - the build process. - -.. container:: paragraph - - When Maven is finished with the build, the final screen should look - similar to this (omitting some ``success`` lines): - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - [INFO] tools .............................................. SUCCESS [ 0.248 s] - [INFO] tools-common ....................................... SUCCESS [ 0.784 s] - [INFO] simple-wsclient .................................... SUCCESS [ 3.303 s] - [INFO] model-generator .................................... SUCCESS [ 0.644 s] - [INFO] packages ........................................... SUCCESS [ 0.336 s] - [INFO] apex-pdp-package-full .............................. SUCCESS [01:10 min] - [INFO] Policy APEX PDP - Docker build 2.0.0-SNAPSHOT ...... SUCCESS [ 10.307 s] - [INFO] ------------------------------------------------------------------------ - [INFO] BUILD SUCCESS - [INFO] ------------------------------------------------------------------------ - [INFO] Total time: 03:43 min - [INFO] Finished at: 2018-09-03T11:56:01+01:00 - [INFO] ------------------------------------------------------------------------ - -.. container:: paragraph - - The build will have created all artifacts required for an APEX - installation. The following example show how to change to the target - directory and how it should look like. - -+----------------------------------------------------------------------------------------------------------------------------+ -| Unix, Cygwin | -+============================================================================================================================+ -| .. container:: | -| | -| .. container:: listingblock | -| | -| .. container:: content | -| | -| .. code:: | -| :number-lines: | -| | -| -rwxrwx---+ 1 esvevan Domain Users 772 Sep 3 11:55 apex-pdp-package-full_2.0.0~SNAPSHOT_all.changes* | -| -rwxrwx---+ 1 esvevan Domain Users 146328082 Sep 3 11:55 apex-pdp-package-full-2.0.0-SNAPSHOT.deb* | -| -rwxrwx---+ 1 esvevan Domain Users 15633 Sep 3 11:54 apex-pdp-package-full-2.0.0-SNAPSHOT.jar* | -| -rwxrwx---+ 1 esvevan Domain Users 146296819 Sep 3 11:55 apex-pdp-package-full-2.0.0-SNAPSHOT-tarball.tar.gz* | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 archive-tmp/ | -| -rwxrwx---+ 1 esvevan Domain Users 89 Sep 3 11:54 checkstyle-cachefile* | -| -rwxrwx---+ 1 esvevan Domain Users 10621 Sep 3 11:54 checkstyle-checker.xml* | -| -rwxrwx---+ 1 esvevan Domain Users 584 Sep 3 11:54 checkstyle-header.txt* | -| -rwxrwx---+ 1 esvevan Domain Users 86 Sep 3 11:54 checkstyle-result.xml* | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 classes/ | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 dependency-maven-plugin-markers/ | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 etc/ | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 examples/ | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:55 install_hierarchy/ | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 maven-archiver/ | -+----------------------------------------------------------------------------------------------------------------------------+ - -+--------------------------------------------------------------------------------------------------------+ -| Windows | -+========================================================================================================+ -| .. container:: | -| | -| .. container:: listingblock | -| | -| .. container:: content | -| | -| .. code:: | -| :number-lines: | -| | -| 03/09/2018 11:55 <DIR> . | -| 03/09/2018 11:55 <DIR> .. | -| 03/09/2018 11:55 146,296,819 apex-pdp-package-full-2.0.0-SNAPSHOT-tarball.tar.gz | -| 03/09/2018 11:55 146,328,082 apex-pdp-package-full-2.0.0-SNAPSHOT.deb | -| 03/09/2018 11:54 15,633 apex-pdp-package-full-2.0.0-SNAPSHOT.jar | -| 03/09/2018 11:55 772 apex-pdp-package-full_2.0.0~SNAPSHOT_all.changes | -| 03/09/2018 11:54 <DIR> archive-tmp | -| 03/09/2018 11:54 89 checkstyle-cachefile | -| 03/09/2018 11:54 10,621 checkstyle-checker.xml | -| 03/09/2018 11:54 584 checkstyle-header.txt | -| 03/09/2018 11:54 86 checkstyle-result.xml | -| 03/09/2018 11:54 <DIR> classes | -| 03/09/2018 11:54 <DIR> dependency-maven-plugin-markers | -| 03/09/2018 11:54 <DIR> etc | -| 03/09/2018 11:54 <DIR> examples | -| 03/09/2018 11:55 <DIR> install_hierarchy | -| 03/09/2018 11:54 <DIR> maven-archiver | -| 8 File(s) 292,652,686 bytes | -| 9 Dir(s) 14,138,720,256 bytes free | -+--------------------------------------------------------------------------------------------------------+ - -Install APEX ------------- - - .. container:: paragraph - - APEX can be installed in different ways: - - .. container:: ulist - - - Unix: automatically using ``rpm`` or ``dpkg`` from ``.rpm`` or - ``.deb`` archive - - - Windows, Unix, Cygwin: manually from a ``.tar.gz`` archive - - - Windows, Unix, Cygwin: build from source using Maven, then - install manually - -Install with RPM and DPKG -######################### - - .. container:: paragraph - - The install distributions of APEX automatically install the - system. The installation directory is - ``/opt/app/policy/apex-pdp``. Log files are located in - ``/var/log/onap/policy/apex-pdp``. The latest APEX version will - be available as ``/opt/app/policy/apex-pdp/apex-pdp``. - - .. container:: paragraph - - For the installation, a new user ``apexuser`` and a new group - ``apexuser`` will be created. This user owns the installation - directories and the log file location. The user is also used by - the standard APEX start scripts to run APEX with this user’s - permissions. - - +-----------------------------------------------------------------------+ - | RPM Installation | - +=======================================================================+ - | .. container:: | - | | - | .. container:: listingblock | - | | - | .. container:: content | - | | - | .. code:: | - | :number-lines: | - | | - | # sudo rpm -i apex-pdp-package-full-2.0.0-SNAPSHOT.rpm | - | ********************preinst******************* | - | arguments 1 | - | ********************************************** | - | creating group apexuser . . . | - | creating user apexuser . . . | - | ********************postinst**************** | - | arguments 1 | - | *********************************************** | - +-----------------------------------------------------------------------+ - -+--------------------------------------------------------------------------------------+ -| DPKG Installation | -+======================================================================================+ -| .. container:: | -| | -| .. container:: listingblock | -| | -| .. container:: content | -| | -| .. code:: | -| :number-lines: | -| | -| # sudo dpkg -i apex-pdp-package-full-2.0.0-SNAPSHOT.deb | -| Selecting previously unselected package apex-uservice. | -| (Reading database ... 288458 files and directories currently installed.) | -| Preparing to unpack apex-pdp-package-full-2.0.0-SNAPSHOT.deb ... | -| ********************preinst******************* | -| arguments install | -| ********************************************** | -| creating group apexuser . . . | -| creating user apexuser . . . | -| Unpacking apex-uservice (2.0.0-SNAPSHOT) ... | -| Setting up apex-uservice (2.0.0-SNAPSHOT) ... | -| ********************postinst**************** | -| arguments configure | -| *********************************************** | -+--------------------------------------------------------------------------------------+ - -.. container:: paragraph - - Once the installation is finished, APEX is fully installed and ready - to run. - -Install Manually from Archive (Unix, Cygwin) -############################################ - - .. container:: paragraph - - Download a ``tar.gz`` archive. Create a directory where APEX - should be installed. Extract the ``tar`` archive. The following - example shows how to install APEX in ``/opt/apex`` and create a - link to ``/opt/apex/apex`` for the most recent installation. - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - # cd /opt - # mkdir apex - # cd apex - # mkdir apex-full-2.0.0-SNAPSHOT - # tar xvfz ~/Downloads/apex-pdp-package-full-2.0.0-SNAPSHOT.tar.gz -C apex-full-2.0.0-SNAPSHOT - # ln -s apex apex-pdp-package-full-2.0.0-SNAPSHOT - -Install Manually from Archive (Windows, 7Zip, GUI) -################################################## - - .. container:: paragraph - - Download a ``tar.gz`` archive and copy the file into the install - folder (in this example ``C:\apex``). Assuming you are using 7Zip, - right click on the file and extract the ``tar`` archive. Note: the - screenshots might show an older version than you have. - - .. container:: imageblock - - .. container:: content - - |Extract the TAR archive| - - .. container:: paragraph - - The right-click on the new created TAR file and extract the actual - APEX distribution. - - .. container:: imageblock - - .. container:: content - - |Extract the APEX distribution| - - .. container:: paragraph - - Inside the new APEX folder you see the main directories: ``bin``, - ``etc``, ``examples``, ``lib``, and ``war`` - - .. container:: paragraph - - Once extracted, please rename the created folder to - ``apex-full-2.0.0-SNAPSHOT``. This will keep the directory name in - line with the rest of this documentation. - -Install Manually from Archive (Windows, 7Zip, CMD) -################################################## - - .. container:: paragraph - - Download a ``tar.gz`` archive and copy the file into the install - folder (in this example ``C:\apex``). Start ``cmd``, for instance - typing ``Windows+R`` and then ``cmd`` in the dialog. Assuming - ``7Zip`` is installed in the standard folder, simply run the - following commands (for APEX version 2.0.0-SNAPSHOT full - distribution) - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - >c: - >cd \apex - >"\Program Files\7-Zip\7z.exe" x apex-pdp-package-full-2.0.0-SNAPSHOT.tar.gz -so | "\Program Files\7-Zip\7z.exe" x -aoa -si -ttar -o"apex-full-2.0.0-SNAPSHOT" - -.. container:: paragraph - - APEX is now installed in the folder - ``C:\apex\apex-full-2.0.0-SNAPSHOT``. - -Build from Source ------------------ - -Build and Install Manually (Unix, Windows, Cygwin) -################################################## - - .. container:: paragraph - - Clone the APEX GIT repositories into a directory. Go to that - directory. Use Maven to build APEX (all details on building - APEX from source can be found in *APEX HowTo: Build*). Install - from the created artifacts (``rpm``, ``deb``, ``tar.gz``, or - copying manually). - - .. important:: - Building RPM distributions - RPM images are only build if the ``rpm`` package is installed (Unix). To install ``rpm`` run - ``sudo apt-get install rpm``, then build APEX. - - .. container:: paragraph - - The following example shows how to build the APEX system, - without tests (``-DskipTests``) to safe some time. It assumes - that the APX GIT repositories are cloned to: - - .. container:: ulist - - - Unix, Cygwin: ``/usr/local/src/apex`` - - - Windows: ``C:\dev\apex`` - - +-------------------------------------------------------+--------------------------------------------------------+ - | Unix, Cygwin | Windows | - +=======================================================+========================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | :number-lines: | :number-lines: | - | | | - | # cd /usr/local/src/apex | >c: | - | # mvn clean install -DskipTests | >cd \dev\apex | - | | >mvn clean install -DskipTests | - +-------------------------------------------------------+--------------------------------------------------------+ - -.. container:: paragraph - - The build takes about 2 minutes without test and about 4-5 minutes - with tests on a standard development laptop. It should run through - without errors, but with a lot of messages from the build process. If - build with tests (i.e. without ``-DskipTests``), there will be error - messages and stack trace prints from some tests. This is normal, as - long as the build finishes successful. - -.. container:: paragraph - - When Maven is finished with the build, the final screen should look - similar to this (omitting some ``success`` lines): - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - [INFO] tools .............................................. SUCCESS [ 0.248 s] - [INFO] tools-common ....................................... SUCCESS [ 0.784 s] - [INFO] simple-wsclient .................................... SUCCESS [ 3.303 s] - [INFO] model-generator .................................... SUCCESS [ 0.644 s] - [INFO] packages ........................................... SUCCESS [ 0.336 s] - [INFO] apex-pdp-package-full .............................. SUCCESS [01:10 min] - [INFO] Policy APEX PDP - Docker build 2.0.0-SNAPSHOT ...... SUCCESS [ 10.307 s] - [INFO] ------------------------------------------------------------------------ - [INFO] BUILD SUCCESS - [INFO] ------------------------------------------------------------------------ - [INFO] Total time: 03:43 min - [INFO] Finished at: 2018-09-03T11:56:01+01:00 - [INFO] ------------------------------------------------------------------------ - -.. container:: paragraph - - The build will have created all artifacts required for an APEX - installation. The following example show how to change to the target - directory and how it should look like. - -+-----------------------------------------------------------------------------------------------------------------------------+ -| Unix, Cygwin | -+=============================================================================================================================+ -| .. container:: | -| | -| .. container:: listingblock | -| | -| .. code:: | -| :number-lines: | -| | -| # cd packages/apex-pdp-package-full/target | -| # ls -l | -| -rwxrwx---+ 1 esvevan Domain Users 772 Sep 3 11:55 apex-pdp-package-full_2.0.0~SNAPSHOT_all.changes* | -| -rwxrwx---+ 1 esvevan Domain Users 146328082 Sep 3 11:55 apex-pdp-package-full-2.0.0-SNAPSHOT.deb* | -| -rwxrwx---+ 1 esvevan Domain Users 15633 Sep 3 11:54 apex-pdp-package-full-2.0.0-SNAPSHOT.jar* | -| -rwxrwx---+ 1 esvevan Domain Users 146296819 Sep 3 11:55 apex-pdp-package-full-2.0.0-SNAPSHOT-tarball.tar.gz* | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 archive-tmp/ | -| -rwxrwx---+ 1 esvevan Domain Users 89 Sep 3 11:54 checkstyle-cachefile* | -| -rwxrwx---+ 1 esvevan Domain Users 10621 Sep 3 11:54 checkstyle-checker.xml* | -| -rwxrwx---+ 1 esvevan Domain Users 584 Sep 3 11:54 checkstyle-header.txt* | -| -rwxrwx---+ 1 esvevan Domain Users 86 Sep 3 11:54 checkstyle-result.xml* | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 classes/ | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 dependency-maven-plugin-markers/ | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 etc/ | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 examples/ | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:55 install_hierarchy/ | -| drwxrwx---+ 1 esvevan Domain Users 0 Sep 3 11:54 maven-archiver/ | -+-----------------------------------------------------------------------------------------------------------------------------+ - -+-----------------------------------------------------------------------------------------------------------------------------+ -| Windows | -+=============================================================================================================================+ -| .. container:: | -| | -| .. container:: listingblock | -| | -| .. code:: | -| :number-lines: | -| | -| >cd packages\apex-pdp-package-full\target | -| >dir | -| 03/09/2018 11:55 <DIR> . | -| 03/09/2018 11:55 <DIR> .. | -| 03/09/2018 11:55 146,296,819 apex-pdp-package-full-2.0.0-SNAPSHOT-tarball.tar.gz | -| 03/09/2018 11:55 146,328,082 apex-pdp-package-full-2.0.0-SNAPSHOT.deb | -| 03/09/2018 11:54 15,633 apex-pdp-package-full-2.0.0-SNAPSHOT.jar | -| 03/09/2018 11:55 772 apex-pdp-package-full_2.0.0~SNAPSHOT_all.changes | -| 03/09/2018 11:54 <DIR> archive-tmp | -| 03/09/2018 11:54 89 checkstyle-cachefile | -| 03/09/2018 11:54 10,621 checkstyle-checker.xml | -| 03/09/2018 11:54 584 checkstyle-header.txt | -| 03/09/2018 11:54 86 checkstyle-result.xml | -| 03/09/2018 11:54 <DIR> classes | -| 03/09/2018 11:54 <DIR> dependency-maven-plugin-markers | -| 03/09/2018 11:54 <DIR> etc | -| 03/09/2018 11:54 <DIR> examples | -| 03/09/2018 11:55 <DIR> install_hierarchy | -| 03/09/2018 11:54 <DIR> maven-archiver | -| 8 File(s) 292,652,686 bytes | -| 9 Dir(s) 14,138,720,256 bytes free | -+-----------------------------------------------------------------------------------------------------------------------------+ - -.. container:: paragraph - - Now, take the ``.deb`` or the ``.tar.gz`` file and install APEX. - Alternatively, copy the content of the folder ``install_hierarchy`` - to your APEX directory. - -Installation Layout -------------------- - - .. container:: paragraph - - A full installation of APEX comes with the following layout. - - .. container:: listingblock - - .. container:: content - - :: - - $APEX_HOME - ├───bin (1) - ├───etc (2) - │ ├───editor - │ ├───hazelcast - │ ├───infinispan - │ └───META-INF - ├───examples (3) - │ ├───config (4) - │ ├───docker (5) - │ ├───events (6) - │ ├───html (7) - │ ├───models (8) - │ └───scripts (9) - ├───lib (10) - │ └───applications (11) - └───war (12) - - .. container:: colist arabic - - +-----------------------------------+-----------------------------------+ - | **1** | binaries, mainly scripts (bash | - | | and bat) to start the APEX engine | - | | and applications | - +-----------------------------------+-----------------------------------+ - | **2** | configuration files, such as | - | | logback (logging) and third party | - | | library configurations | - +-----------------------------------+-----------------------------------+ - | **3** | example policy models to get | - | | started | - +-----------------------------------+-----------------------------------+ - | **4** | configurations for the examples | - | | (with sub directories for | - | | individual examples) | - +-----------------------------------+-----------------------------------+ - | **5** | Docker files and additional | - | | Docker instructions for the | - | | exampples | - +-----------------------------------+-----------------------------------+ - | **6** | example events for the examples | - | | (with sub directories for | - | | individual examples) | - +-----------------------------------+-----------------------------------+ - | **7** | HTML files for some examples, | - | | e.g. the Decisionmaker example | - +-----------------------------------+-----------------------------------+ - | **8** | the policy models, generated for | - | | each example (with sub | - | | directories for individual | - | | examples) | - +-----------------------------------+-----------------------------------+ - | **9** | additional scripts for the | - | | examples (with sub directories | - | | for individual examples) | - +-----------------------------------+-----------------------------------+ - | **10** | the library folder with all Java | - | | JAR files | - +-----------------------------------+-----------------------------------+ - | **11** | applications, also known as jar | - | | with dependencies (or fat jars), | - | | individually deployable | - +-----------------------------------+-----------------------------------+ - | **12** | WAR files for web applications | - +-----------------------------------+-----------------------------------+ - -System Configuration --------------------- - - .. container:: paragraph - - Once APEX is installed, a few configurations need to be done: - - .. container:: ulist - - - Create an APEX user and an APEX group (optional, if not - installed using RPM and DPKG) - - - Create environment settings for ``APEX_HOME`` and - ``APEX_USER``, required by the start scripts - - - Change settings of the logging framework (optional) - - - Create directories for logging, required (execution might fail - if directories do not exist or cannot be created) - -APEX User and Group -################### - - .. container:: paragraph - - On smaller installations and test systems, APEX can run as any - user or group. - - .. container:: paragraph - - However, if APEX is installed in production, we strongly - recommend you set up a dedicated user for running APEX. This - will isolate the execution of APEX to that user. We recommend - you use the userid ``apexuser`` but you may use any user you - choose. - - .. container:: paragraph - - The following example, for UNIX, creates a group called - ``apexuser``, an APEX user called ``apexuser``, adds the group - to the user, and changes ownership of the APEX installation to - the user. Substitute ``<apex-dir>`` with the directory where - APEX is installed. - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - # sudo groupadd apexuser - # sudo useradd -g apexuser apexuser - # sudo chown -R apexuser:apexuser <apex-dir> - -.. container:: paragraph - - For other operating systems please consult your manual or system - administrator. - -Environment Settings: APEX_HOME and APEX_USER -############################################# - - .. container:: paragraph - - The provided start scripts for APEX require two environment - variables being set: - - .. container:: ulist - - - ``APEX_USER`` with the user under whos name and permission APEX - should be started (Unix only) - - - ``APEX_HOME`` with the directory where APEX is installed (Unix, - Windows, Cygwin) - - .. container:: paragraph - - The first row in the following table shows how to set these - environment variables temporary (assuming the user is - ``apexuser``). The second row shows how to verify the settings. - The last row explains how to set those variables permanently. - - +------------------------------------------------+---------------------------------------------------------+ - | Unix, Cygwin (bash/tcsh) | Windows | - +================================================+=========================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | :number-lines: | :number-lines: | - | | | - | # export APEX_USER=apexuser | >set APEX_HOME=C:\apex\apex-full-2.0.0-SNAPSHOT | - | # cd /opt/app/policy/apex-pdp | | - | # export APEX_HOME=`pwd` | | - | | | - +------------------------------------------------+ | - | .. container:: | | - | | | - | .. container:: content | | - | | | - | .. code:: tcsh | | - | :number-lines: | | - | | | - | # setenv APEX_USER apexuser | | - | # cd /opt/app/policy/apex-pdp | | - | # setenv APEX_HOME `pwd` | | - | | | - +------------------------------------------------+---------------------------------------------------------+ - | .. container:: | .. container:: | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | :number-lines: | :number-lines: | - | | | - | # env | grep APEX | >set APEX_HOME | - | # APEX_USER=apexuser | APEX_HOME=\apex\apex-full-2.0.0-SNAPSHOT | - | # APEX_HOME=/opt/app/policy/apex-pdp | | - | | | - +------------------------------------------------+---------------------------------------------------------+ - -Making Environment Settings Permanent (Unix, Cygwin) -==================================================== - - .. container:: paragraph - - For a per-user setting, edit the a user’s ``bash`` or ``tcsh`` - settings in ``~/.bashrc`` or ``~/.tcshrc``. For system-wide - settings, edit ``/etc/profiles`` (requires permissions). - -Making Environment Settings Permanent (Windows) -=============================================== - - .. container:: paragraph - - On Windows 7 do - - .. container:: ulist - - - Click on the **Start** Menu - - - Right click on **Computer** - - - Select **Properties** - - .. container:: paragraph - - On Windows 8/10 do - - .. container:: ulist - - - Click on the **Start** Menu - - - Select **System** - - .. container:: paragraph - - Then do the following - - .. container:: ulist - - - Select **Advanced System Settings** - - - On the **Advanced** tab, click the **Environment Variables** - button - - - Edit an existing variable, or create a new System variable: - 'Variable name'="APEX_HOME", 'Variable - value'="C:\apex\apex-full-2.0.0-SNAPSHOT" - - .. container:: paragraph - - For the settings to take effect, an application needs to be - restarted (e.g. any open ``cmd`` window). - -Edit the APEX Logging Settings -############################## - - .. container:: paragraph - - Configure the APEX logging settings to your requirements, for - instance: - - .. container:: ulist - - - change the directory where logs are written to, or - - - change the log levels - - .. container:: paragraph - - Edit the file ``$APEX_HOME/etc/logback.xml`` for any required - changes. To change the log directory change the line - - .. container:: paragraph - - ``<property name="VAR_LOG" value="/var/log/onap/policy/apex-pdp/" />`` - - .. container:: paragraph - - to - - .. container:: paragraph - - ``<property name="VAR_LOG" value="/PATH/TO/LOG/DIRECTORY/" />`` - - .. container:: paragraph - - On Windows, it is recommended to change the log directory to: - - .. container:: paragraph - - ``<property name="VAR_LOG" value="C:/apex/apex-full-2.0.0-SNAPSHOT/logs" />`` - - .. container:: paragraph - - Note: Be careful about when to use ``\`` vs. ``/`` as the path - separator! - -Create Directories for Logging -############################## - - .. container:: paragraph - - Make sure that the log directory exists. This is important when - APEX was installed manually or when the log directory was changed - in the settings (see above). - - +------------------------------------------------------------------+-------------------------------------------------------+ - | Unix, Cygwin | Windows | - +==================================================================+=======================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | :number-lines: | :number-lines: | - | | | - | mkdir -p /var/log/onap/policy/apex-pdp | >mkdir C:\apex\apex-full-2.0.0-SNAPSHOT\logs | - | chown -R apexuser:apexuser /var/log/onap/policy/apex-pdp | | - +------------------------------------------------------------------+-------------------------------------------------------+ - -Verify the APEX Installation ----------------------------- - - .. container:: paragraph - - When APEX is installed and all settings are realized, the - installation can be verified. - -Verify Installation - run Engine -################################ - - .. container:: paragraph - - A simple verification of an APEX installation can be done by - simply starting the APEX engine without any configuration. On - Unix (or Cygwin) start the engine using - ``$APEX_HOME/bin/apexEngine.sh``. On Windows start the engine - using ``%APEX_HOME%\bin\apexEngine.bat``. The engine will fail - to fully start. However, if the output looks similar to the - following line, the APEX installation is realized. - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - Starting Apex service with parameters [] . . . - start of Apex service failed: Apex configuration file was not specified as an argument - 2018-09-03 13:11:33,914 Apex [main] ERROR o.o.p.a.service.engine.main.ApexMain - start of Apex service failed - org.onap.policy.apex.model.basicmodel.concepts.ApexException: Apex configuration file was not specified as an argument - at org.onap.policy.apex.service.engine.main.ApexCommandLineArguments.validateReadableFile(ApexCommandLineArguments.java:267) - at org.onap.policy.apex.service.engine.main.ApexCommandLineArguments.validate(ApexCommandLineArguments.java:161) - at org.onap.policy.apex.service.engine.main.ApexMain.<init>(ApexMain.java:68) - at org.onap.policy.apex.service.engine.main.ApexMain.main(ApexMain.java:165) - usage: org.onap.policy.apex.service.engine.main.ApexMain [options...] - options - -c,--config-file <CONFIG_FILE>the full path to the configuration file to use, the configuration file must be a Json file - containing the Apex configuration parameters - -h,--help outputs the usage of this command - -m,--model-file <MODEL_FILE> the full path to the model file to use, if set it overrides the model file set in the - configuration file - -v,--version outputs the version of Apex - -Verify Installation - run an Example -#################################### - - .. container:: paragraph - - A full APEX installation comes with several examples. Here, we can - fully verify the installation by running one of the examples. - - .. container:: paragraph - - We use the example called *SampleDomain* and configure the engine - to use standard in and standard out for events. Run the engine - with the provided configuration. Note: Cygwin executes scripts as - Unix scripts but runs Java as a Windows application, thus the - configuration file must be given as a Windows path. - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - # $APEX_HOME/bin/apexEngine.sh -c $APEX_HOME/examples/config/SampleDomain/Stdin2StdoutJsonEventJava.json (1) - # $APEX_HOME/bin/apexEngine.sh -c C:/apex/apex-full-2.0.0-SNAPSHOT/examples/config/SampleDomain/Stdin2StdoutJsonEventJava.json (2) - >%APEX_HOME%\bin\apexEngine.bat -c %APEX_HOME%\examples\config\SampleDomain\Stdin2StdoutJsonEventJava.json :: (3) - -.. container:: colist arabic - - +-------+---------+ - | **1** | UNIX | - +-------+---------+ - | **2** | Cygwin | - +-------+---------+ - | **3** | Windows | - +-------+---------+ - -.. container:: paragraph - - The engine should start successfully. Assuming the logging levels are - not change (default level is ``info``), the output should look - similar to this (last few lines) - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - Starting Apex service with parameters [-c, v:/dev/ericsson/apex/onap/apex-pdp/packages/apex-pdp-package-full/target/install_hierarchy/examples/config/SampleDomain/Stdin2StdoutJsonEventJava.json] . . . - 2018-09-05 15:16:42,800 Apex [main] INFO o.o.p.a.s.e.r.impl.EngineServiceImpl - Created apex engine MyApexEngine-0:0.0.1 . - 2018-09-05 15:16:42,804 Apex [main] INFO o.o.p.a.s.e.r.impl.EngineServiceImpl - Created apex engine MyApexEngine-1:0.0.1 . - 2018-09-05 15:16:42,804 Apex [main] INFO o.o.p.a.s.e.r.impl.EngineServiceImpl - Created apex engine MyApexEngine-2:0.0.1 . - 2018-09-05 15:16:42,805 Apex [main] INFO o.o.p.a.s.e.r.impl.EngineServiceImpl - Created apex engine MyApexEngine-3:0.0.1 . - 2018-09-05 15:16:42,805 Apex [main] INFO o.o.p.a.s.e.r.impl.EngineServiceImpl - APEX service created. - 2018-09-05 15:16:43,962 Apex [main] INFO o.o.p.a.s.e.e.EngDepMessagingService - engine<-->deployment messaging starting . . . - 2018-09-05 15:16:43,963 Apex [main] INFO o.o.p.a.s.e.e.EngDepMessagingService - engine<-->deployment messaging started - 2018-09-05 15:16:44,987 Apex [main] INFO o.o.p.a.s.e.r.impl.EngineServiceImpl - Registering apex model on engine MyApexEngine-0:0.0.1 - 2018-09-05 15:16:45,112 Apex [main] INFO o.o.p.a.s.e.r.impl.EngineServiceImpl - Registering apex model on engine MyApexEngine-1:0.0.1 - 2018-09-05 15:16:45,113 Apex [main] INFO o.o.p.a.s.e.r.impl.EngineServiceImpl - Registering apex model on engine MyApexEngine-2:0.0.1 - 2018-09-05 15:16:45,113 Apex [main] INFO o.o.p.a.s.e.r.impl.EngineServiceImpl - Registering apex model on engine MyApexEngine-3:0.0.1 - 2018-09-05 15:16:45,120 Apex [main] INFO o.o.p.a.s.e.r.impl.EngineServiceImpl - Added the action listener to the engine - Started Apex service - -.. container:: paragraph - - Important are the last two line, stating that APEX has added the - final action listener to the engine and that the engine is started. - -.. container:: paragraph - - The engine is configured to read events from standard input and write - produced events to standard output. The policy model is a very simple - policy. - -.. container:: paragraph - - The following table shows an input event in the left column and an - output event in the right column. Past the input event into the - console where APEX is running, and the output event should appear in - the console. Pasting the input event multiple times will produce - output events with different values. - -+-------------------------------------------------------------+-------------------------------------------------------------+ -| Input Event | Example Output Event | -+=============================================================+=============================================================+ -| .. container:: | .. container:: | -| | | -| .. container:: content | .. container:: content | -| | | -| .. code:: | .. code:: | -| :number-lines: | :number-lines: | -| | | -| { | { | -| "nameSpace": "org.onap.policy.apex.sample.events", | "name": "Event0004", | -| "name": "Event0000", | "version": "0.0.1", | -| "version": "0.0.1", | "nameSpace": "org.onap.policy.apex.sample.events", | -| "source": "test", | "source": "Act", | -| "target": "apex", | "target": "Outside", | -| "TestSlogan": "Test slogan for External Event0", | "TestActCaseSelected": 2, | -| "TestMatchCase": 0, | "TestActStateTime": 1536157104627, | -| "TestTimestamp": 1469781869269, | "TestDecideCaseSelected": 0, | -| "TestTemperature": 9080.866 | "TestDecideStateTime": 1536157104625, | -| } | "TestEstablishCaseSelected": 0, | -| | "TestEstablishStateTime": 1536157104623, | -| | "TestMatchCase": 0, | -| | "TestMatchCaseSelected": 1, | -| | "TestMatchStateTime": 1536157104620, | -| | "TestSlogan": "Test slogan for External Event0", | -| | "TestTemperature": 9080.866, | -| | "TestTimestamp": 1469781869269 | -| | } | -+-------------------------------------------------------------+-------------------------------------------------------------+ - -.. container:: paragraph - - Terminate APEX by simply using ``CTRL+C`` in the console. - -Verify a Full Installation - REST Editor -######################################## - - .. container:: paragraph - - APEX has a REST application for viewing policy models. The - application can also be used to create new policy models close to - the engine native policy language. Start the REST editor as - follows. - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - # $APEX_HOME/bin/apexApps.sh rest-editor - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - >%APEX_HOME%\bin\apexApps.bat rest-editor - -.. container:: paragraph - - The script will start a simple web server - (`Grizzly <https://javaee.github.io/grizzly/>`__) and deploy a - ``war`` web archive in it. Once the editor is started, it will be - available on ``localhost:18989``. The last few line of the messages - should be: - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - Apex Editor REST endpoint (ApexEditorMain: Config=[ApexEditorParameters: URI=http://localhost:18989/apexservices/, TTL=-1sec], State=READY) starting at http://localhost:18989/apexservices/ . . . - Sep 05, 2018 10:35:57 PM org.glassfish.grizzly.http.server.NetworkListener start - INFO: Started listener bound to [localhost:18989] - Sep 05, 2018 10:35:57 PM org.glassfish.grizzly.http.server.HttpServer start - INFO: [HttpServer] Started. - Apex Editor REST endpoint (ApexEditorMain: Config=[ApexEditorParameters: URI=http://localhost:18989/apexservices/, TTL=-1sec], State=RUNNING) started at http://localhost:18989/apexservices/ - -.. container:: paragraph - - Now open a browser (Firefox, Chrome, Opera, Internet Explorer) and - use the URL ``http://localhost:18989/``. This will connect the - browser to the started REST editor. The start screen should be as - follows. - -.. container:: imageblock - - .. container:: content - - |REST Editor Start Screen| - - .. container:: title - - Figure 1. REST Editor Start Screen - -.. container:: paragraph - - Now load a policy model by clicking the menu ``File`` and then - ``Open``. In the opened dialog, go to the directory where APEX is - installed, then ``examples``, ``models``, ``SampleDomain``, and there - select the file ``SamplePolicyModelJAVA.json``. This will load the - policy model used to verify the policy engine (see above). Once - loaded, the screen should look as follows. - -.. container:: imageblock - - .. container:: content - - |REST Editor with loaded SampleDomain Policy Model| - - .. container:: title - - Figure 2. REST Editor with loaded SampleDomain Policy Model - -.. container:: paragraph - - Now you can use the REST editor. To finish this verification, simply - terminate your browser (or the tab), and then use ``CTRL+C`` in the - console where you started the REST editor. - -Installing WAR Applications ---------------------------- - - .. container:: paragraph - - APEX comes with a set of WAR files. These are complete - applications that can be installed and run in an application - server. All of these applications are realized as servlets. You - can find the WAR applications in ``$APEX_HOME/war`` (UNIX, Cygwin) - or ``%APEX_HOME%\war`` (Windows). - - .. container:: paragraph - - Installing and using the WAR applications requires a web server - that can execute ``war`` web archives. We recommend to use `Apache - Tomcat <https://tomcat.apache.org/>`__, however other web servers - can be used as well. - - .. container:: paragraph - - Install Apache Tomcat including the ``Manager App``, see `V9.0 - Docs <https://tomcat.apache.org/tomcat-9.0-doc/manager-howto.html#Configuring_Manager_Application_Access>`__ - for details. Start the Tomcat service, or make sure that Tomcat is - running. - - .. container:: paragraph - - There are multiple ways to install the APEX WAR applications: - - .. container:: ulist - - - copy the ``.war`` file into the Tomcat ``webapps`` folder - - - use the Tomcat ``Manager App`` to deploy via the web interface - - - deploy using a REST call to Tomcat - - .. container:: paragraph - - For details on how to install ``war`` files please consult the - `Tomcat - Documentation <https://tomcat.apache.org/tomcat-9.0-doc/index.html>`__ - or the `Manager App - HOW-TO <https://tomcat.apache.org/tomcat-9.0-doc/manager-howto.html>`__. - Once you installed an APEX WAR application (and wait for - sufficient time for Tomcat to finalize the installation), open the - ``Manager App`` in Tomcat. You should see the APEX WAR application - being installed and running. - - .. container:: paragraph - - In case of errors, examine the log files in the Tomcat log - directory. In a conventional install, those log files are in the - logs directory where Tomcat is installed. - - .. container:: paragraph - - The current APEX version provides the following WAR applications: - - .. container:: ulist - - - client-deployment-2.0.0-SNAPSHOT.war - a client to deploy new - policy models to a running engine - - - client-editor-2.0.0-SNAPSHOT.war - the standard policy REST - editor GUI - - - client-monitoring-2.0.0-SNAPSHOT.war - a client for monitoring - a running APEX engine - - - client-full-2.0.0-SNAPSHOT.war - a full client with a - one-stop-access to deployment, monitoring, and REST editor - - - examples-servlet-2.0.0-SNAPSHOT.war - an example APEX servlet - -Running APEX in Docker ----------------------- - - .. container:: paragraph - - Since APEX is in ONAP, we provide a full virtualization - environment for the engine. - -Run in ONAP -########### - - .. container:: paragraph - - Running APEX from the ONAP docker repository only requires 2 - commands: - - .. container:: olist arabic - - #. Log into the ONAP docker repo - - .. container:: listingblock - - .. container:: content - - :: - - docker login -u docker -p docker nexus3.onap.org:10003 - - .. container:: olist arabic - - #. Run the APEX docker image - - .. container:: listingblock - - .. container:: content - - :: - - docker run -it --rm nexus3.onap.org:10003/onap/policy-apex-pdp:latest - -Build a Docker Image -#################### - - .. container:: paragraph - - Alternatively, one can use the Dockerfile defined in the Docker - package to build an image. - - .. container:: listingblock - - .. container:: title - - APEX Dockerfile - - .. container:: content - - .. code:: - :number-lines: - - # - # Docker file to build an image that runs APEX on Java 8 in Ubuntu - # - FROM ubuntu:16.04 - - RUN apt-get update && \ - apt-get upgrade -y && \ - apt-get install -y software-properties-common && \ - add-apt-repository ppa:openjdk-r/ppa -y && \ - apt-get update && \ - apt-get install -y openjdk-8-jdk - - # Create apex user and group - RUN groupadd apexuser - RUN useradd --create-home -g apexuser apexuser - - # Add Apex-specific directories and set ownership as the Apex admin user - RUN mkdir -p /opt/app/policy/apex-pdp - RUN mkdir -p /var/log/onap/policy/apex-pdp - RUN chown -R apexuser:apexuser /var/log/onap/policy/apex-pdp - - # Unpack the tarball - RUN mkdir /packages - COPY apex-pdp-package-full.tar.gz /packages - RUN tar xvfz /packages/apex-pdp-package-full.tar.gz --directory /opt/app/policy/apex-pdp - RUN rm /packages/apex-pdp-package-full.tar.gz - - # Ensure everything has the correct permissions - RUN find /opt/app -type d -perm 755 - RUN find /opt/app -type f -perm 644 - RUN chmod a+x /opt/app/policy/apex-pdp/bin/* - - # Copy examples to Apex user area - RUN cp -pr /opt/app/policy/apex-pdp/examples /home/apexuser - - RUN apt-get clean - - RUN chown -R apexuser:apexuser /home/apexuser/* - - USER apexuser - ENV PATH /opt/app/policy/apex-pdp/bin:$PATH - WORKDIR /home/apexuser - -APEX Configurations Explained -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Introduction to APEX Configuration ----------------------------------- - - .. container:: paragraph - - An APEX engine can be configured to use various combinations - of event input handlers, event output handlers, event - protocols, context handlers, and logic executors. The system - is build using a plugin architecture. Each configuration - option is realized by a plugin, which can be loaded and - configured when the engine is started. New plugins can be - added to the system at any time, though to benefit from a - new plugin an engine will need to be restarted. - - .. container:: imageblock - - .. container:: content - - |APEX Configuration Matrix| - - .. container:: title - - Figure 3. APEX Configuration Matrix - - .. container:: paragraph - - The APEX distribution already comes with a number of - plugins. The figure above shows the provided plugins. Any - combination of input, output, event protocol, context - handlers, and executors is possible. - -General Configuration Format ----------------------------- - - .. container:: paragraph - - The APEX configuration file is a JSON file containing a few - main blocks for different parts of the configuration. Each - block then holds the configuration details. The following - code shows the main blocks: - - .. container:: listingblock - - .. container:: content - - .. code:: - - { - "engineServiceParameters":{ - ... (1) - "engineParameters":{ (2) - "engineParameters":{...}, (3) - "contextParameters":{...} (4) - } - }, - "eventInputParameters":{ (5) - "input1":{ (6) - "carrierTechnologyParameters":{...}, - "eventProtocolParameters":{...} - }, - "input2":{...}, (7) - "carrierTechnologyParameters":{...}, - "eventProtocolParameters":{...} - }, - ... (8) - }, - "eventOutputParameters":{ (9) - "output1":{ (10) - "carrierTechnologyParameters":{...}, - "eventProtocolParameters":{...} - }, - "output2":{ (11) - "carrierTechnologyParameters":{...}, - "eventProtocolParameters":{...} - }, - ... (12) - } - } - - .. container:: colist arabic - - +-----------------------------------+-----------------------------------+ - | **1** | main engine configuration | - +-----------------------------------+-----------------------------------+ - | **2** | engine parameters for plugin | - | | configurations (execution | - | | environments and context | - | | handling) | - +-----------------------------------+-----------------------------------+ - | **3** | engine specific parameters, | - | | mainly for executor plugins | - +-----------------------------------+-----------------------------------+ - | **4** | context specific parameters, e.g. | - | | for context schemas, persistence, | - | | etc. | - +-----------------------------------+-----------------------------------+ - | **5** | configuration of the input | - | | interface | - +-----------------------------------+-----------------------------------+ - | **6** | an example input called | - | | ``input1`` with carrier | - | | technology and event protocol | - +-----------------------------------+-----------------------------------+ - | **7** | an example input called | - | | ``input2`` with carrier | - | | technology and event protocol | - +-----------------------------------+-----------------------------------+ - | **8** | any further input configuration | - +-----------------------------------+-----------------------------------+ - | **9** | configuration of the output | - | | interface | - +-----------------------------------+-----------------------------------+ - | **10** | an example output called | - | | ``output1`` with carrier | - | | technology and event protocol | - +-----------------------------------+-----------------------------------+ - | **11** | an example output called | - | | ``output2`` with carrier | - | | technology and event protocol | - +-----------------------------------+-----------------------------------+ - | **12** | any further output configuration | - +-----------------------------------+-----------------------------------+ - -Engine Service Parameters -------------------------- - - .. container:: paragraph - - The configuration provides a number of parameters to - configure the engine. An example configuration with - explanations of all options is shown below. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "engineServiceParameters" : { - "name" : "AADMApexEngine", (1) - "version" : "0.0.1", (2) - "id" : 45, (3) - "instanceCount" : 4, (4) - "deploymentPort" : 12345, (5) - "policyModelFileName" : "examples/models/VPN/VPNPolicyModelJava.json", (6) - "periodicEventPeriod": 1000, (7) - "engineParameters":{ (8) - "engineParameters":{...}, (9) - "contextParameters":{...} (10) - } - } - - .. container:: colist arabic - - +-----------------------------------+-----------------------------------+ - | **1** | a name for the engine. The engine | - | | name is used to create a key in a | - | | runtime engine. An name matching | - | | the following regular expression | - | | can be used here: | - | | ``[A-Za-z0-9\\-_\\.]+`` | - +-----------------------------------+-----------------------------------+ - | **2** | a version of the engine, use | - | | semantic versioning as explained | - | | here: `Semantic | - | | Versioning <http://semver.org/>`_ | - | | _. | - | | This version is used in a runtime | - | | engine to create a version of the | - | | engine. For that reason, the | - | | version must match the following | - | | regular expression ``[A-Z0-9.]+`` | - +-----------------------------------+-----------------------------------+ - | **3** | a numeric identifier for the | - | | engine | - +-----------------------------------+-----------------------------------+ - | **4** | the number of threads (policy | - | | instances executed in parallel) | - | | the engine should use, use ``1`` | - | | for single threaded engines | - +-----------------------------------+-----------------------------------+ - | **5** | the port for the deployment | - | | Websocket connection to the | - | | engine | - +-----------------------------------+-----------------------------------+ - | **6** | the model file to load into the | - | | engine on startup (optional) | - +-----------------------------------+-----------------------------------+ - | **7** | an optional timer for periodic | - | | policies, in milliseconds (a | - | | defined periodic policy will be | - | | executed every ``X`` | - | | milliseconds), not used of not | - | | set or ``0`` | - +-----------------------------------+-----------------------------------+ - | **8** | engine parameters for plugin | - | | configurations (execution | - | | environments and context | - | | handling) | - +-----------------------------------+-----------------------------------+ - | **9** | engine specific parameters, | - | | mainly for executor plugins | - +-----------------------------------+-----------------------------------+ - | **10** | context specific parameters, e.g. | - | | for context schemas, persistence, | - | | etc. | - +-----------------------------------+-----------------------------------+ - - .. container:: paragraph - - The model file is optional, it can also be specified via - command line. In any case, make sure all execution and other - required plug-ins for the loaded model are loaded as - required. - -Input and Output Interfaces ---------------------------- - - .. container:: paragraph - - An APEX engine has two main interfaces: - - .. container:: ulist - - - An *input* interface to receive events: also known as - ingress interface or consumer, receiving (consuming) - events commonly named triggers, and - - - An *output* interface to publish produced events: also - known as egress interface or producer, sending - (publishing) events commonly named actions or action - events. - - .. container:: paragraph - - The input and output interface is configured in terms of - inputs and outputs, respectively. Each input and output is a - combination of a carrier technology and an event protocol. - Carrier technologies and event protocols are provided by - plugins, each with its own specific configuration. Most - carrier technologies can be configured for input as well as - output. Most event protocols can be used for all carrier - technologies. One exception is the JMS object event - protocol, which can only be used for the JMS carrier - technology. Some further restrictions apply (for instance - for carrier technologies using bi- or uni-directional - modes). - - .. container:: paragraph - - Input and output interface can be configured separately, in - isolation, with any number of carrier technologies. The - resulting general configuration options are: - - .. container:: ulist - - - Input interface with one or more inputs - - .. container:: ulist - - - each input with a carrier technology and an event - protocol - - - some inputs with optional synchronous mode - - - some event protocols with additional parameters - - - Output interface with one or more outputs - - .. container:: ulist - - - each output with a carrier technology and an event - encoding - - - some outputs with optional synchronous mode - - - some event protocols with additional parameters - - .. container:: paragraph - - The configuration for input and output is contained in - ``eventInputParameters`` and ``eventOutputParameters``, - respectively. Inside here, one can configure any number of - inputs and outputs. Each of them needs to have a unique - identifier (name), the content of the name is free form. The - example below shows a configuration for two inputs and two - outputs. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventInputParameters": { (1) - "FirstConsumer": { (2) - "carrierTechnologyParameters" : {...}, (3) - "eventProtocolParameters":{...}, (4) - ... (5) - }, - "SecondConsumer": { (6) - "carrierTechnologyParameters" : {...}, (7) - "eventProtocolParameters":{...}, (8) - ... (9) - }, - }, - "eventOutputParameters": { (10) - "FirstProducer": { (11) - "carrierTechnologyParameters":{...}, (12) - "eventProtocolParameters":{...}, (13) - ... (14) - }, - "SecondProducer": { (15) - "carrierTechnologyParameters":{...}, (16) - "eventProtocolParameters":{...}, (17) - ... (18) - } - } - - .. container:: colist arabic - - +--------+--------------------------------------------------------------------+ - | **1** | input interface configuration, APEX input plugins | - +--------+--------------------------------------------------------------------+ - | **2** | first input called ``FirstConsumer`` | - +--------+--------------------------------------------------------------------+ - | **3** | carrier technology for plugin | - +--------+--------------------------------------------------------------------+ - | **4** | event protocol for plugin | - +--------+--------------------------------------------------------------------+ - | **5** | any other input configuration (e.g. event name filter, see below) | - +--------+--------------------------------------------------------------------+ - | **6** | second input called ``SecondConsumer`` | - +--------+--------------------------------------------------------------------+ - | **7** | carrier technology for plugin | - +--------+--------------------------------------------------------------------+ - | **8** | event protocol for plugin | - +--------+--------------------------------------------------------------------+ - | **9** | any other plugin configuration | - +--------+--------------------------------------------------------------------+ - | **10** | output interface configuration, APEX output plugins | - +--------+--------------------------------------------------------------------+ - | **11** | first output called ``FirstProducer`` | - +--------+--------------------------------------------------------------------+ - | **12** | carrier technology for plugin | - +--------+--------------------------------------------------------------------+ - | **13** | event protocol for plugin | - +--------+--------------------------------------------------------------------+ - | **14** | any other plugin configuration | - +--------+--------------------------------------------------------------------+ - | **15** | second output called ``SecondProducer`` | - +--------+--------------------------------------------------------------------+ - | **16** | carrier technology for plugin | - +--------+--------------------------------------------------------------------+ - | **17** | event protocol for plugin | - +--------+--------------------------------------------------------------------+ - | **18** | any other output configuration (e.g. event name filter, see below) | - +--------+--------------------------------------------------------------------+ - -Event Filters -############# - - .. container:: paragraph - - APEX will always send an event after a policy execution - is finished. For a successful execution, the event sent - is the output event created by the policy. In case the - policy does not create an output event, APEX will create - a new event with all input event fields plus an - additional field ``exceptionMessage`` with an exception - message. - - .. container:: paragraph - - There are situations in which this auto-generated error - event might not be required or wanted: - - .. container:: ulist - - - when a policy failing should not result in an event - send out via an output interface - - - when the auto-generated event goes back in an APEX - engine (or the same APEX engine), this can create - endless loops - - - the auto-generated event should go to a special output - interface or channel - - .. container:: paragraph - - All of these situations are supported by a filter option - using a wildecard (regular expression) configuration on - APEX I/O interfaces. The parameter is called - ``eventNameFilter`` and the value are `Java regular - expressions <https://docs.oracle.com/javase/8/docs/api/java/util/regex/Pattern.html>`__ - (a - `tutorial <http://www.vogella.com/tutorials/JavaRegularExpressions/article.html>`__). - The following code shows some examples: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventInputParameters": { - "Input1": { - "carrierTechnologyParameters" : {...}, - "eventProtocolParameters":{...}, - "eventNameFilter" : "^E[Vv][Ee][Nn][Tt][0-9]004$" (1) - } - }, - "eventOutputParameters": { - "Output1": { - "carrierTechnologyParameters":{...}, - "eventProtocolParameters":{...}, - "eventNameFilter" : "^E[Vv][Ee][Nn][Tt][0-9]104$" (2) - } - } - -Executors ---------- - - .. container:: paragraph - - Executors are plugins that realize the execution of logic - contained in a policy model. Logic can be in a task - selector, a task, and a state finalizer. Using plugins for - execution environments makes APEX very flexible to support - virtually any executable logic expressions. - - .. container:: paragraph - - APEX 2.0.0-SNAPSHOT supports the following executors: - - .. container:: ulist - - - Java, for Java implemented logic - - .. container:: ulist - - - This executor requires logic implemented using the - APEX Java interfaces. - - - Generated JAR files must be in the classpath of the - APEX engine at start time. - - - Javascript - - - JRuby, - - - Jython, - - - MVEL - - .. container:: ulist - - - This executor uses the latest version of the MVEL - engine, which can be very hard to debug and can - produce unwanted side effects during execution - -Configure the Javascript Executor -################################# - - .. container:: paragraph - - The Javascript executor is added to the configuration as - follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "engineServiceParameters":{ - "engineParameters":{ - "executorParameters":{ - "JAVASCRIPT":{ - "parameterClassName" : - "org.onap.policy.apex.plugins.executor.javascript.JavascriptExecutorParameters" - } - } - } - } - -Configure the Jython Executor -############################# - - .. container:: paragraph - - The Jython executor is added to the configuration as - follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "engineServiceParameters":{ - "engineParameters":{ - "executorParameters":{ - "JYTHON":{ - "parameterClassName" : - "org.onap.policy.apex.plugins.executor.jython.JythonExecutorParameters" - } - } - } - } - -Configure the JRuby Executor -############################ - - .. container:: paragraph - - The JRuby executor is added to the configuration as - follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "engineServiceParameters":{ - "engineParameters":{ - "executorParameters":{ - "JRUBY":{ - "parameterClassName" : - "org.onap.policy.apex.plugins.executor.jruby.JrubyExecutorParameters" - } - } - } - } - -Configure the Java Executor -########################### - - .. container:: paragraph - - The Java executor is added to the configuration as - follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "engineServiceParameters":{ - "engineParameters":{ - "executorParameters":{ - "JAVA":{ - "parameterClassName" : - "org.onap.policy.apex.plugins.executor.java.JavaExecutorParameters" - } - } - } - } - -Configure the MVEL Executor -########################### - - .. container:: paragraph - - The MVEL executor is added to the configuration as - follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "engineServiceParameters":{ - "engineParameters":{ - "executorParameters":{ - "MVEL":{ - "parameterClassName" : - "org.onap.policy.apex.plugins.executor.mvel.MVELExecutorParameters" - } - } - } - } - -Context Handlers ----------------- - - .. container:: paragraph - - Context handlers are responsible for all context processing. - There are the following main areas: - - .. container:: ulist - - - Context schema: use schema handlers other than Java class - (supported by default without configuration) - - - Context distribution: distribute context across multiple - APEX engines - - - Context locking: mechanisms to lock context elements for - read/write - - - Context persistence: mechanisms to persist context - - .. container:: paragraph - - APEX provides plugins for each of the main areas. - -Configure AVRO Schema Handler -############################# - - .. container:: paragraph - - The AVRO schema handler is added to the configuration as - follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "engineServiceParameters":{ - "engineParameters":{ - "contextParameters":{ - "parameterClassName" : "org.onap.policy.apex.context.parameters.ContextParameters", - "schemaParameters":{ - "Avro":{ - "parameterClassName" : - "org.onap.policy.apex.plugins.context.schema.avro.AvroSchemaHelperParameters" - } - } - } - } - } - - .. container:: paragraph - - Using the AVRO schema handler has one limitation: AVRO - only supports field names that represent valid Java class - names. This means only letters and the character ``_`` - are supported. Characters commonly used in field names, - such as ``.`` and ``-``, are not supported by AVRO. for - more information see `Avro Spec: - Names <https://avro.apache.org/docs/1.8.1/spec.html#names>`__. - - .. container:: paragraph - - To work with this limitation, the APEX Avro plugin will - parse a given AVRO definition and replace *all* - occurrences of ``.`` and ``-`` with a ``_``. This means - that - - .. container:: ulist - - - In a policy model, if the AVRO schema defined a field - as ``my-name`` the policy logic should access it as - ``my_name`` - - - In a policy model, if the AVRO schema defined a field - as ``my.name`` the policy logic should access it as - ``my_name`` - - - There should be no field names that convert to the - same internal name - - .. container:: ulist - - - For instance the simultaneous use of - ``my_name``, ``my.name``, and ``my-name`` should - be avoided - - - If not avoided, the event processing might - create unwanted side effects - - - If field names use any other not-supported character, - the AVRO plugin will reject it - - .. container:: ulist - - - Since AVRO uses lazy initialization, this - rejection might only become visible at runtime - -Carrier Technologies --------------------- - - .. container:: paragraph - - Carrier technologies define how APEX receives (input) and - sends (output) events. They can be used in any combination, - using asynchronous or synchronous mode. There can also be - any number of carrier technologies for the input (consume) - and the output (produce) interface. - - .. container:: paragraph - - Supported *input* technologies are: - - .. container:: ulist - - - Standard input, read events from the standard input - (console), not suitable for APEX background servers - - - File input, read events from a file - - - Kafka, read events from a Kafka system - - - Websockets, read events from a Websocket - - - JMS, - - - REST (synchronous and asynchronous), additionally as - client or server - - - Event Requestor, allows reading of events that have been - looped back into APEX - - .. container:: paragraph - - Supported *output* technologies are: - - .. container:: ulist - - - Standard output, write events to the standard output - (console), not suitable for APEX background servers - - - File output, write events to a file - - - Kafka, write events to a Kafka system - - - Websockets, write events to a Websocket - - - JMS - - - REST (synchronous and asynchronous), additionally as - client or server - - - Event Requestor, allows events to be looped back into - APEX - - .. container:: paragraph - - New carrier technologies can be added as plugins to APEX or - developed outside APEX and added to an APEX deployment. - -Standard IO -########### - - .. container:: paragraph - - Standard IO does not require a specific plugin, it is - supported be default. - -Standard Input -============== - .. container:: paragraph - - APEX will take events from its standard input. This - carrier is good for testing, but certainly not for a - use case where APEX runs as a server. The - configuration is as follows: - - .. container:: listingblock - - .. container:: content - - :: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "FILE", (1) - "parameters" : { - "standardIO" : true (2) - } - } - - .. container:: colist arabic - - +-------+---------------------------------------+ - | **1** | standard input is considered a file | - +-------+---------------------------------------+ - | **2** | file descriptor set to standard input | - +-------+---------------------------------------+ - -Standard Output -=============== - - .. container:: paragraph - - APEX will send events to its standard output. This - carrier is good for testing, but certainly not for a - use case where APEX runs as a server. The - configuration is as follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "FILE", (1) - "parameters" : { - "standardIO" : true (2) - } - } - - .. container:: colist arabic - - +-------+----------------------------------------+ - | **1** | standard output is considered a file | - +-------+----------------------------------------+ - | **2** | file descriptor set to standard output | - +-------+----------------------------------------+ - -2.7.2. File IO -############## - - .. container:: paragraph - - File IO does not require a specific plugin, it is - supported be default. - -File Input -========== - - .. container:: paragraph - - APEX will take events from a file. The same file - should not be used as an output. The configuration is - as follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "FILE", (1) - "parameters" : { - "fileName" : "examples/events/SampleDomain/EventsIn.xmlfile" (2) - } - } - - .. container:: colist arabic - - +-------+------------------------------------------+ - | **1** | set file input | - +-------+------------------------------------------+ - | **2** | the name of the file to read events from | - +-------+------------------------------------------+ - -File Output -=========== - .. container:: paragraph - - APEX will write events to a file. The same file should - not be used as an input. The configuration is as - follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "FILE", (1) - "parameters" : { - "fileName" : "examples/events/SampleDomain/EventsOut.xmlfile" (2) - } - } - - .. container:: colist arabic - - +-------+-----------------------------------------+ - | **1** | set file output | - +-------+-----------------------------------------+ - | **2** | the name of the file to write events to | - +-------+-----------------------------------------+ - -Event Requestor IO -################## - - .. container:: paragraph - - Event Requestor IO does not require a specific plugin, it - is supported be default. It should only be used with the - APEX event protocol. - -Event Requestor Input -===================== - - .. container:: paragraph - - APEX will take events from APEX. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology": "EVENT_REQUESTOR" (1) - } - - .. container:: colist arabic - - +-------+---------------------------+ - | **1** | set event requestor input | - +-------+---------------------------+ - -Event Requestor Output -====================== - - .. container:: paragraph - - APEX will write events to APEX. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology": "EVENT_REQUESTOR" (1) - } - -Peering Event Requestors -======================== - - .. container:: paragraph - - When using event requestors, they need to be peered. - This means an event requestor output needs to be - peered (associated) with an event requestor input. The - following example shows the use of an event requestor - with the APEX event protocol and the peering of output - and input. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventInputParameters": { - "EventRequestorConsumer": { - "carrierTechnologyParameters": { - "carrierTechnology": "EVENT_REQUESTOR" (1) - }, - "eventProtocolParameters": { - "eventProtocol": "APEX" (2) - }, - "eventNameFilter": "InputEvent", (3) - "requestorMode": true, (4) - "requestorPeer": "EventRequestorProducer", (5) - "requestorTimeout": 500 (6) - } - }, - "eventOutputParameters": { - "EventRequestorProducer": { - "carrierTechnologyParameters": { - "carrierTechnology": "EVENT_REQUESTOR" (7) - }, - "eventProtocolParameters": { - "eventProtocol": "APEX" (8) - }, - "eventNameFilter": "EventListEvent", (9) - "requestorMode": true, (10) - "requestorPeer": "EventRequestorConsumer", (11) - "requestorTimeout": 500 (12) - } - } - - .. container:: colist arabic - - +-----------------------------------+-----------------------------------+ - | **1** | event requestor on a consumer | - +-----------------------------------+-----------------------------------+ - | **2** | with APEX event protocol | - +-----------------------------------+-----------------------------------+ - | **3** | optional filter (best to use a | - | | filter to prevent unwanted events | - | | on the consumer side) | - +-----------------------------------+-----------------------------------+ - | **4** | activate requestor mode | - +-----------------------------------+-----------------------------------+ - | **5** | the peer to the output (must | - | | match the output carrier) | - +-----------------------------------+-----------------------------------+ - | **6** | an optional timeout in | - | | milliseconds | - +-----------------------------------+-----------------------------------+ - | **7** | event requestor on a producer | - +-----------------------------------+-----------------------------------+ - | **8** | with APEX event protocol | - +-----------------------------------+-----------------------------------+ - | **9** | optional filter (best to use a | - | | filter to prevent unwanted events | - | | on the consumer side) | - +-----------------------------------+-----------------------------------+ - | **10** | activate requestor mode | - +-----------------------------------+-----------------------------------+ - | **11** | the peer to the output (must | - | | match the input carrier) | - +-----------------------------------+-----------------------------------+ - | **12** | an optional timeout in | - | | milliseconds | - +-----------------------------------+-----------------------------------+ - -Kafka IO -######## - - .. container:: paragraph - - Kafka IO is supported by the APEX Kafka plugin. The - configurations below are examples. APEX will take any - configuration inside the parameter object and forward it - to Kafka. More information on Kafka specific - configuration parameters can be found in the Kafka - documentation: - - .. container:: ulist - - - `Kafka Consumer - Class <https://kafka.apache.org/090/javadoc/org/apache/kafka/clients/consumer/KafkaConsumer.html>`__ - - - `Kafka Producer - Class <https://kafka.apache.org/090/javadoc/org/apache/kafka/clients/producer/KafkaProducer.html>`__ - -Kafka Input -=========== - .. container:: paragraph - - APEX will receive events from the Apache Kafka - messaging system. The input is uni-directional, an - engine will only receive events from the input but not - send any event to the input. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "KAFKA", (1) - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.kafka.KAFKACarrierTechnologyParameters", - "parameters" : { - "bootstrapServers" : "localhost:49092", (2) - "groupId" : "apex-group-id", (3) - "enableAutoCommit" : true, (4) - "autoCommitTime" : 1000, (5) - "sessionTimeout" : 30000, (6) - "consumerPollTime" : 100, (7) - "consumerTopicList" : ["apex-in-0", "apex-in-1"], (8) - "keyDeserializer" : - "org.apache.kafka.common.serialization.StringDeserializer", (9) - "valueDeserializer" : - "org.apache.kafka.common.serialization.StringDeserializer" (10) - } - } - - .. container:: colist arabic - - +--------+-------------------------------------+ - | **1** | set Kafka as carrier technology | - +--------+-------------------------------------+ - | **2** | bootstrap server and port | - +--------+-------------------------------------+ - | **3** | a group identifier | - +--------+-------------------------------------+ - | **4** | flag for auto-commit | - +--------+-------------------------------------+ - | **5** | auto-commit timeout in milliseconds | - +--------+-------------------------------------+ - | **6** | session timeout in milliseconds | - +--------+-------------------------------------+ - | **7** | consumer poll time in milliseconds | - +--------+-------------------------------------+ - | **8** | consumer topic list | - +--------+-------------------------------------+ - | **9** | key for the Kafka de-serializer | - +--------+-------------------------------------+ - | **10** | value for the Kafka de-serializer | - +--------+-------------------------------------+ - -Kafka Output -============ - .. container:: paragraph - - APEX will send events to the Apache Kafka messaging - system. The output is uni-directional, an engine will - send events to the output but not receive any event - from the output. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "KAFKA", (1) - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.kafka.KAFKACarrierTechnologyParameters", - "parameters" : { - "bootstrapServers" : "localhost:49092", (2) - "acks" : "all", (3) - "retries" : 0, (4) - "batchSize" : 16384, (5) - "lingerTime" : 1, (6) - "bufferMemory" : 33554432, (7) - "producerTopic" : "apex-out", (8) - "keySerializer" : - "org.apache.kafka.common.serialization.StringSerializer", (9) - "valueSerializer" : - "org.apache.kafka.common.serialization.StringSerializer" (10) - } - } - - .. container:: colist arabic - - +--------+---------------------------------+ - | **1** | set Kafka as carrier technology | - +--------+---------------------------------+ - | **2** | bootstrap server and port | - +--------+---------------------------------+ - | **3** | acknowledgement strategy | - +--------+---------------------------------+ - | **4** | number of retries | - +--------+---------------------------------+ - | **5** | batch size | - +--------+---------------------------------+ - | **6** | time to linger in milliseconds | - +--------+---------------------------------+ - | **7** | buffer memory in byte | - +--------+---------------------------------+ - | **8** | producer topic | - +--------+---------------------------------+ - | **9** | key for the Kafka serializer | - +--------+---------------------------------+ - | **10** | value for the Kafka serializer | - +--------+---------------------------------+ - -JMS IO -####### - - .. container:: paragraph - - APEX supports the Java Messaging Service (JMS) as input - as well as output. JMS IO is supported by the APEX JMS - plugin. Input and output support an event encoding as - text (JSON string) or object (serialized object). The - input configuration is the same for both encodings, the - output configuration differs. - -JMS Input -========= - .. container:: paragraph - - APEX will receive events from a JMS messaging system. - The input is uni-directional, an engine will only - receive events from the input but not send any event - to the input. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "JMS", (1) - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.jms.JMSCarrierTechnologyParameters", - "parameters" : { (2) - "initialContextFactory" : - "org.jboss.naming.remote.client.InitialContextFactory", (3) - "connectionFactory" : "ConnectionFactory", (4) - "providerURL" : "remote://localhost:5445", (5) - "securityPrincipal" : "guest", (6) - "securityCredentials" : "IAmAGuest", (7) - "consumerTopic" : "jms/topic/apexIn" (8) - } - } - - .. container:: colist arabic - - +-----------------------------------+-----------------------------------+ - | **1** | set JMS as carrier technology | - +-----------------------------------+-----------------------------------+ - | **2** | set all JMS specific parameters | - +-----------------------------------+-----------------------------------+ - | **3** | the context factory, in this case | - | | from JBOSS (it requires the | - | | dependency | - | | org.jboss:jboss-remote-naming:2.0 | - | | .4.Final | - | | or a different version to be in | - | | the directory ``$APEX_HOME/lib`` | - | | or ``%APEX_HOME%\lib`` | - +-----------------------------------+-----------------------------------+ - | **4** | a connection factory for the JMS | - | | connection | - +-----------------------------------+-----------------------------------+ - | **5** | URL with host and port of the JMS | - | | provider | - +-----------------------------------+-----------------------------------+ - | **6** | access credentials, user name | - +-----------------------------------+-----------------------------------+ - | **7** | access credentials, user password | - +-----------------------------------+-----------------------------------+ - | **8** | the JMS topic to listen to | - +-----------------------------------+-----------------------------------+ - -JMS Output with Text -==================== - - .. container:: paragraph - - APEX engine send events to a JMS messaging system. The - output is uni-directional, an engine will send events - to the output but not receive any event from output. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "JMS", (1) - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.jms.JMSCarrierTechnologyParameters", - "parameters" : { (2) - "initialContextFactory" : - "org.jboss.naming.remote.client.InitialContextFactory", (3) - "connectionFactory" : "ConnectionFactory", (4) - "providerURL" : "remote://localhost:5445", (5) - "securityPrincipal" : "guest", (6) - "securityCredentials" : "IAmAGuest", (7) - "producerTopic" : "jms/topic/apexOut", (8) - "objectMessageSending": "false" (9) - } - } - - .. container:: colist arabic - - +-----------------------------------+-----------------------------------+ - | **1** | set JMS as carrier technology | - +-----------------------------------+-----------------------------------+ - | **2** | set all JMS specific parameters | - +-----------------------------------+-----------------------------------+ - | **3** | the context factory, in this case | - | | from JBOSS (it requires the | - | | dependency | - | | org.jboss:jboss-remote-naming:2.0 | - | | .4.Final | - | | or a different version to be in | - | | the directory ``$APEX_HOME/lib`` | - | | or ``%APEX_HOME%\lib`` | - +-----------------------------------+-----------------------------------+ - | **4** | a connection factory for the JMS | - | | connection | - +-----------------------------------+-----------------------------------+ - | **5** | URL with host and port of the JMS | - | | provider | - +-----------------------------------+-----------------------------------+ - | **6** | access credentials, user name | - +-----------------------------------+-----------------------------------+ - | **7** | access credentials, user password | - +-----------------------------------+-----------------------------------+ - | **8** | the JMS topic to write to | - +-----------------------------------+-----------------------------------+ - | **9** | set object messaging to ``false`` | - | | means it sends JSON text | - +-----------------------------------+-----------------------------------+ - -JMS Output with Object -====================== - - .. container:: paragraph - - To configure APEX for JMS objects on the output - interface use the same configuration as above (for - output). Simply change the ``objectMessageSending`` - parameter to ``true``. - -Websocket (WS) IO -######################## - - .. container:: paragraph - - APEX supports the Websockets as input as well as output. - WS IO is supported by the APEX Websocket plugin. This - carrier technology does only support uni-directional - communication. APEX will not send events to a Websocket - input and any event sent to a Websocket output will - result in an error log. - - .. container:: paragraph - - The input can be configured as client (APEX connects to - an existing Websocket server) or server (APEX starts a - Websocket server). The same applies to the output. Input - and output can both use a client or a server - configuration, or separate configurations (input as - client and output as server, input as server and output - as client). Each configuration should use its own - dedicated port to avoid any communication loops. The - configuration of a Websocket client is the same for input - and output. The configuration of a Websocket server is - the same for input and output. - -Websocket Client -================ - - .. container:: paragraph - - APEX will connect to a given Websocket server. As - input, it will receive events from the server but not - send any events. As output, it will send events to the - server and any event received from the server will - result in an error log. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "WEBSOCKET", (1) - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.websocket.WEBSOCKETCarrierTechnologyParameters", - "parameters" : { - "host" : "localhost", (2) - "port" : 42451 (3) - } - } - - .. container:: colist arabic - - +-------+------------------------------------------------------+ - | **1** | set Websocket as carrier technology | - +-------+------------------------------------------------------+ - | **2** | the host name on which a Websocket server is running | - +-------+------------------------------------------------------+ - | **3** | the port of that Websocket server | - +-------+------------------------------------------------------+ - -Websocket Server -================ - - .. container:: paragraph - - APEX will start a Websocket server, which will accept - any Websocket clients to connect. As input, it will - receive events from the server but not send any - events. As output, it will send events to the server - and any event received from the server will result in - an error log. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "WEBSOCKET", (1) - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.websocket.WEBSOCKETCarrierTechnologyParameters", - "parameters" : { - "wsClient" : false, (2) - "port" : 42450 (3) - } - } - - .. container:: colist arabic - - +-------+------------------------------------------------------------+ - | **1** | set Websocket as carrier technology | - +-------+------------------------------------------------------------+ - | **2** | disable client, so that APEX will start a Websocket server | - +-------+------------------------------------------------------------+ - | **3** | the port for the Websocket server APEX will start | - +-------+------------------------------------------------------------+ - -REST Client IO -############## - - .. container:: paragraph - - APEX can act as REST client on the input as well as on - the output interface. The media type is - ``application/json``, so this plugin does only work with - the JSON Event protocol. - -REST Client Input -================= - - .. container:: paragraph - - APEX will connect to a given URL to receive events, - but not send any events. The server is polled, i.e. - APEX will do an HTTP GET, take the result, and then do - the next GET. Any required timing needs to be handled - by the server configured via the URL. For instance, - the server could support a wait timeout via the URL as - ``?timeout=100ms``. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "RESTCLIENT", (1) - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.restclient.RESTClientCarrierTechnologyParameters", - "parameters" : { - "url" : "http://example.org:8080/triggers/events", (2) - } - } - - .. container:: colist arabic - - +-------+---------------------------------------+ - | **1** | set REST client as carrier technology | - +-------+---------------------------------------+ - | **2** | the URL of the HTTP server for events | - +-------+---------------------------------------+ - -REST Client Output -================== - - .. container:: paragraph - - APEX will connect to a given URL to send events, but - not receive any events. The default HTTP operation is - POST (no configuration required). To change it to PUT - simply add the configuration parameter (as shown in - the example below). - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters" : { - "carrierTechnology" : "RESTCLIENT", (1) - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.restclient.RESTClientCarrierTechnologyParameters", - "parameters" : { - "url" : "http://example.com:8888/actions/events", (2) - "httpMethod" : "PUT" (3) - } - } - - .. container:: colist arabic - - +-------+--------------------------------------------------+ - | **1** | set REST client as carrier technology | - +-------+--------------------------------------------------+ - | **2** | the URL of the HTTP server for events | - +-------+--------------------------------------------------+ - | **3** | use HTTP PUT (remove this line to use HTTP POST) | - +-------+--------------------------------------------------+ - -REST Server IO -############## - - .. container:: paragraph - - APEX supports a REST server for input and output. - - .. container:: paragraph - - The REST server plugin always uses a synchronous mode. A - client does a HTTP GET on the APEX REST server with the - input event and receives the generated output event in - the server reply. This means that for the REST server - there has to always to be an input with an associated - output. Input or output only are not permitted. - - .. container:: paragraph - - The plugin will start a Grizzly server as REST server for - a normal APEX engine. If the APEX engine is executed as a - servlet, for instance inside Tomcat, then Tomcat will be - used as REST server (this case requires configuration on - Tomcat as well). - - .. container:: paragraph - - Some configuration restrictions apply for all scenarios: - - .. container:: ulist - - - Minimum port: 1024 - - - Maximum port: 65535 - - - The media type is ``application/json``, so this plugin - does only work with the JSON Event protocol. - - .. container:: paragraph - - The URL the client calls is created using - - .. container:: ulist - - - the configured host and port, e.g. - ``http://localhost:12345`` - - - the standard path, e.g. ``/apex/`` - - - the name of the input/output, e.g. ``FirstConsumer/`` - - - the input or output name, e.g. ``EventIn``. - - .. container:: paragraph - - The examples above lead to the URL - ``http://localhost:12345/apex/FirstConsumer/EventIn``. - - .. container:: paragraph - - A client can also get status information of the REST - server using ``/Status``, e.g. - ``http://localhost:12345/apex/FirstConsumer/Status``. - -REST Server Stand-alone -======================= - - .. container:: paragraph - - We need to configure a REST server input and a REST - server output. Input and output are associated with - each other via there name. - - .. container:: paragraph - - Timeouts for REST calls need to be set carefully. If - they are too short, the call might timeout before a - policy finished creating an event. - - .. container:: paragraph - - The following example configures the input named as - ``MyConsumer`` and associates an output named - ``MyProducer`` with it. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventInputParameters": { - "MyConsumer": { - "carrierTechnologyParameters" : { - "carrierTechnology" : "RESTSERVER", (1) - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.restserver.RESTServerCarrierTechnologyParameters", - "parameters" : { - "standalone" : true, (2) - "host" : "localhost", (3) - "port" : 12345 (4) - } - }, - "eventProtocolParameters":{ - "eventProtocol" : "JSON" (5) - }, - "synchronousMode" : true, (6) - "synchronousPeer" : "MyProducer", (7) - "synchronousTimeout" : 500 (8) - } - } - - .. container:: colist arabic - - +-------+---------------------------------------+ - | **1** | set REST server as carrier technology | - +-------+---------------------------------------+ - | **2** | set the server as stand-alone | - +-------+---------------------------------------+ - | **3** | set the server host | - +-------+---------------------------------------+ - | **4** | set the server listen port | - +-------+---------------------------------------+ - | **5** | use JSON event protocol | - +-------+---------------------------------------+ - | **6** | activate synchronous mode | - +-------+---------------------------------------+ - | **7** | associate an output ``MyProducer`` | - +-------+---------------------------------------+ - | **8** | set a timeout of 500 milliseconds | - +-------+---------------------------------------+ - - .. container:: paragraph - - The following example configures the output named as - ``MyProducer`` and associates the input ``MyConsumer`` - with it. Note that for the output there are no more - paramters (such as host or port), since they are - already configured in the associated input - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventOutputParameters": { - "MyProducer": { - "carrierTechnologyParameters":{ - "carrierTechnology" : "RESTSERVER", - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.restserver.RESTServerCarrierTechnologyParameters" - }, - "eventProtocolParameters":{ - "eventProtocol" : "JSON" - }, - "synchronousMode" : true, - "synchronousPeer" : "MyConsumer", - "synchronousTimeout" : 500 - } - } - -REST Server Stand-alone, multi input -==================================== - - .. container:: paragraph - - Any number of input/output pairs for REST servers can - be configured. For instance, we can configure an input - ``FirstConsumer`` with output ``FirstProducer`` and an - input ``SecondConsumer`` with output - ``SecondProducer``. Important is that there is always - one pair of input/output. - -REST Server Stand-alone in Servlet -================================== - - .. container:: paragraph - - If APEX is executed as a servlet, e.g. inside Tomcat, - the configuration becomes easier since the plugin can - now use Tomcat as the REST server. In this scenario, - there are not parameters (port, host, etc.) and the - key ``standalone`` must not be used (or set to false). - - .. container:: paragraph - - For the Tomcat configuration, we need to add the REST - server plugin, e.g. - - .. container:: listingblock - - .. container:: content - - .. code:: - - <servlet> - ... - <init-param> - ... - <param-value>org.onap.policy.apex.plugins.event.carrier.restserver</param-value> - </init-param> - ... - </servlet> - -REST Requestor IO -################## - - .. container:: paragraph - - APEX can act as REST requestor on the input as well as on - the output interface. The media type is - ``application/json``, so this plugin does only work with - the JSON Event protocol. - -REST Requestor Input -==================== - - .. container:: paragraph - - APEX will connect to a given URL to request an input. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters": { - "carrierTechnology": "RESTREQUESTOR", (1) - "parameterClassName": "org.onap.policy.apex.plugins.event.carrier.restrequestor.RESTRequestorCarrierTechnologyParameters", - "parameters": { - "url": "http://localhost:54321/some/path/to/rest/resource", (2) - "httpMethod": "POST", (3) - "restRequestTimeout": 2000 (4) - } - }, - - .. container:: colist arabic - - +-------+--------------------------------------------------+ - | **1** | set REST requestor as carrier technology | - +-------+--------------------------------------------------+ - | **2** | the URL of the HTTP server for events | - +-------+--------------------------------------------------+ - | **3** | use HTTP PUT (remove this line to use HTTP POST) | - +-------+--------------------------------------------------+ - | **4** | request timeout in milliseconds | - +-------+--------------------------------------------------+ - - .. container:: paragraph - - Further settings are required on the consumer to - define the event that is requested, for example: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventName": "GuardResponseEvent", (1) - "eventNameFilter": "GuardResponseEvent", (2) - "requestorMode": true, (3) - "requestorPeer": "GuardRequestorProducer", (4) - "requestorTimeout": 500 (5) - - .. container:: colist arabic - - +-------+---------------------------+ - | **1** | the event name | - +-------+---------------------------+ - | **2** | a filter on the event | - +-------+---------------------------+ - | **3** | the mode of the requestor | - +-------+---------------------------+ - | **4** | a peer for the requestor | - +-------+---------------------------+ - | **5** | a general request timeout | - +-------+---------------------------+ - -REST Requestor Output -===================== - - .. container:: paragraph - - APEX will connect to a given URL to send events, but - not receive any events. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "carrierTechnologyParameters": { - "carrierTechnology": "RESTREQUESTOR", (1) - "parameterClassName": "org.onap.policy.apex.plugins.event.carrier.restrequestor.RESTRequestorCarrierTechnologyParameters" - }, - - .. container:: colist arabic - - +-------+------------------------------------------+ - | **1** | set REST requestor as carrier technology | - +-------+------------------------------------------+ - - .. container:: paragraph - - Further settings are required on the consumer to - define the event that is requested, for example: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventNameFilter": "GuardRequestEvent", (1) - "requestorMode": true, (2) - "requestorPeer": "GuardRequestorConsumer", (3) - "requestorTimeout": 500 (4) - - .. container:: colist arabic - - +-------+---------------------------+ - | **1** | a filter on the event | - +-------+---------------------------+ - | **2** | the mode of the requestor | - +-------+---------------------------+ - | **3** | a peer for the requestor | - +-------+---------------------------+ - | **4** | a general request timeout | - +-------+---------------------------+ - -Event Protocols, Format and Encoding ------------------------------------- - - .. container:: paragraph - - Event protocols define what event formats APEX can receive - (input) and should send (output). They can be used in any - combination for input and output, unless further restricted - by a carrier technology plugin (for instance for JMS - output). There can only be 1 event protocol per event - plugin. - - .. container:: paragraph - - Supported *input* event protocols are: - - .. container:: ulist - - - JSON, the event as a JSON string - - - APEX, an APEX event - - - JMS object, the event as a JMS object, - - - JMS text, the event as a JMS text, - - - XML, the event as an XML string, - - - YAML, the event as YAML text - - .. container:: paragraph - - Supported *output* event protocols are: - - .. container:: ulist - - - JSON, the event as a JSON string - - - APEX, an APEX event - - - JMS object, the event as a JMS object, - - - JMS text, the event as a JMS text, - - - XML, the event as an XML string, - - - YAML, the event as YAML text - - .. container:: paragraph - - New event protocols can be added as plugins to APEX or - developed outside APEX and added to an APEX deployment. - -JSON Event -########## - - .. container:: paragraph - - The event protocol for JSON encoding does not require a - specific plugin, it is supported by default. Furthermore, - there is no difference in the configuration for the input - and output interface. - - .. container:: paragraph - - For an input, APEX requires a well-formed JSON string. - Well-formed here means according to the definitions of a - policy. Any JSON string that is not defined as a trigger - event (consume) will not be consumed (errors will be - thrown). For output JSON events, APEX will always produce - valid JSON strings according to the definition in the - policy model. - - .. container:: paragraph - - The following JSON shows the configuration. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventProtocolParameters":{ - "eventProtocol" : "JSON" - } - - .. container:: paragraph - - For JSON events, there are a few more optional - parameters, which allow to define a mapping for standard - event fields. An APEX event must have the fields - ``name``, ``version``, ``source``, and ``target`` - defined. Sometimes it is not possible to configure a - trigger or actioning system to use those fields. However, - they might be in an event generated outside APEX (or used - outside APEX) just with different names. To configure - APEX to map between the different event names, simply add - the following parameters to a JSON event: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventProtocolParameters":{ - "eventProtocol" : "JSON", - "nameAlias" : "policyName", (1) - "versionAlias" : "policyVersion", (2) - "sourceAlias" : "from", (3) - "targetAlias" : "to", (4) - "nameSpaceAlias": "my.name.space" (5) - } - - .. container:: colist arabic - - +-----------------------------------+-----------------------------------+ - | **1** | mapping for the ``name`` field, | - | | here from a field called | - | | ``policyName`` | - +-----------------------------------+-----------------------------------+ - | **2** | mapping for the ``version`` | - | | field, here from a field called | - | | ``policyVersion`` | - +-----------------------------------+-----------------------------------+ - | **3** | mapping for the ``source`` field, | - | | here from a field called ``from`` | - | | (only for an input event) | - +-----------------------------------+-----------------------------------+ - | **4** | mapping for the ``target`` field, | - | | here from a field called ``to`` | - | | (only for an output event) | - +-----------------------------------+-----------------------------------+ - | **5** | mapping for the ``nameSpace`` | - | | field, here from a field called | - | | ``my.name.space`` | - +-----------------------------------+-----------------------------------+ - -APEX Event -########## - .. container:: paragraph - - The event protocol for APEX events does not require a - specific plugin, it is supported by default. Furthermore, - there is no difference in the configuration for the input - and output interface. - - .. container:: paragraph - - For input and output APEX uses APEX events. - - .. container:: paragraph - - The following JSON shows the configuration. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventProtocolParameters":{ - "eventProtocol" : "APEX" - } - -JMS Event -######### - - .. container:: paragraph - - The event protocol for JMS is provided by the APEX JMS - plugin. The plugin supports encoding as JSON text or as - object. There is no difference in the configuration for - the input and output interface. - -JMS Text -======== - .. container:: paragraph - - If used as input, APEX will take a JMS message and - extract a JSON string, then proceed as if a JSON event - was received. If used as output, APEX will take the - event produced by a policy, create a JSON string, and - then wrap it into a JMS message. - - .. container:: paragraph - - The configuration for JMS text is as follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventProtocolParameters":{ - "eventProtocol" : "JMSTEXT", - "parameterClassName" : - "org.onap.policy.apex.plugins.event.protocol.jms.JMSTextEventProtocolParameters" - } - -JMS Object -========== - .. container:: paragraph - - If used as input, APEX will will take a JMS message, - extract a Java Bean from the ``ObjectMessage`` - message, construct an APEX event and put the bean on - the APEX event as a parameter. If used as output, APEX - will take the event produced by a policy, create a - Java Bean and send it as a JMS message. - - .. container:: paragraph - - The configuration for JMS object is as follows: - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventProtocolParameters":{ - "eventProtocol" : "JMSOBJECT", - "parameterClassName" : - "org.onap.policy.apex.plugins.event.protocol.jms.JMSObjectEventProtocolParameters" - } - -YAML Event -########## - - .. container:: paragraph - - The event protocol for YAML is provided by the APEX YAML - plugin. There is no difference in the configuration for - the input and output interface. - - .. container:: paragraph - - If used as input, APEX will consume events as YAML and - map them to policy trigger events. Not well-formed YAML - and not understood trigger events will be rejected. If - used as output, APEX produce YAML encoded events from the - event a policy produces. Those events will always be - well-formed according to the definition in the policy - model. - - .. container:: paragraph - - The following code shows the configuration. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventProtocolParameters":{ - "eventProtocol" : "XML", - "parameterClassName" : - "org.onap.policy.apex.plugins.event.protocol.yaml.YamlEventProtocolParameters" - } - -XML Event -######### - .. container:: paragraph - - The event protocol for XML is provided by the APEX XML - plugin. There is no difference in the configuration for - the input and output interface. - - .. container:: paragraph - - If used as input, APEX will consume events as XML and map - them to policy trigger events. Not well-formed XML and - not understood trigger events will be rejected. If used - as output, APEX produce XML encoded events from the event - a policy produces. Those events will always be - well-formed according to the definition in the policy - model. - - .. container:: paragraph - - The following code shows the configuration. - - .. container:: listingblock - - .. container:: content - - .. code:: - - "eventProtocolParameters":{ - "eventProtocol" : "XML", - "parameterClassName" : - "org.onap.policy.apex.plugins.event.protocol.xml.XMLEventProtocolParameters" - } - -A configuration example ------------------------ - - .. container:: paragraph - - The following example loads all available plug-ins. - - .. container:: paragraph - - Events are consumed from a Websocket, APEX as client. - Consumed event format is JSON. - - .. container:: paragraph - - Events are produced to Kafka. Produced event format is XML. - - .. container:: listingblock - - .. container:: content - - .. code:: - - { - "engineServiceParameters" : { - "name" : "MyApexEngine", - "version" : "0.0.1", - "id" : 45, - "instanceCount" : 4, - "deploymentPort" : 12345, - "policyModelFileName" : "examples/models/some-model.json", - "engineParameters" : { - "executorParameters" : { - "JAVASCRIPT" : { - "parameterClassName" : - "org.onap.policy.apex.plugins.executor.javascript.JavascriptExecutorParameters" - }, - "JYTHON" : { - "parameterClassName" : - "org.onap.policy.apex.plugins.executor.jython.JythonExecutorParameters" - }, - "JRUBY" : { - "parameterClassName" : - "org.onap.policy.apex.plugins.executor.jruby.JrubyExecutorParameters" - }, - "JAVA" : { - "parameterClassName" : - "org.onap.policy.apex.plugins.executor.java.JavaExecutorParameters" - }, - "MVEL" : { - "parameterClassName" : - "org.onap.policy.apex.plugins.executor.mvel.MVELExecutorParameters" - } - }, - "contextParameters" : { - "parameterClassName" : - "org.onap.policy.apex.context.parameters.ContextParameters", - "schemaParameters" : { - "Avro":{ - "parameterClassName" : - "org.onap.policy.apex.plugins.context.schema.avro.AvroSchemaHelperParameters" - } - } - } - } - }, - "producerCarrierTechnologyParameters" : { - "carrierTechnology" : "KAFKA", - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.kafka.KAFKACarrierTechnologyParameters", - "parameters" : { - "bootstrapServers" : "localhost:49092", - "acks" : "all", - "retries" : 0, - "batchSize" : 16384, - "lingerTime" : 1, - "bufferMemory" : 33554432, - "producerTopic" : "apex-out", - "keySerializer" : "org.apache.kafka.common.serialization.StringSerializer", - "valueSerializer" : "org.apache.kafka.common.serialization.StringSerializer" - } - }, - "producerEventProtocolParameters" : { - "eventProtocol" : "XML", - "parameterClassName" : - "org.onap.policy.apex.plugins.event.protocol.xml.XMLEventProtocolParameters" - }, - "consumerCarrierTechnologyParameters" : { - "carrierTechnology" : "WEBSOCKET", - "parameterClassName" : - "org.onap.policy.apex.plugins.event.carrier.websocket.WEBSOCKETCarrierTechnologyParameters", - "parameters" : { - "host" : "localhost", - "port" : 88888 - } - }, - "consumerEventProtocolParameters" : { - "eventProtocol" : "JSON" - } - } - -Engine and Applications of the APEX System -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Introduction to APEX Engine and Applications --------------------------------------------- - - .. container:: paragraph - - The core of APEX is the APEX Engine, also known as the APEX - Policy Engine or the APEX PDP (since it is in fact a Policy - Decision Point). Beside this engine, an APEX system comes - with a few applications intended to help with policy - authoring, deployment, and execution. - - .. container:: paragraph - - The engine itself and most applications are started from the - command line with command line arguments. This is called a - Command Line Interface (CLI). Some applications require an - installation on a webserver, as for instance the REST - Editor. Those applications can be accessed via a web - browser. - - .. container:: paragraph - - You can also use the available APEX APIs and applications to - develop other applications as required. This includes policy - languages (and associated parsers and compilers / - interpreters), GUIs to access APEX or to define policies, - clients to connect to APEX, etc. - - .. container:: paragraph - - For this documentation, we assume an installation of APEX as - a full system based on a current ONAP release. - -CLI on Unix, Windows, and Cygwin --------------------------------- - - .. container:: paragraph - - A note on APEX CLI applications: all applications and the - engine itself have been deployed and tested on different - operating systems: Red Hat, Ubuntu, Debian, Mac OSX, - Windows, Cygwin. Each operating system comes with its own - way of configuring and executing Java. The main items here - are: - - .. container:: ulist - - - For UNIX systems (RHL, Ubuntu, Debian, Mac OSX), the - provided bash scripts work as expected with absolute - paths (e.g. - ``/opt/app/policy/apex-pdp/apex-pdp-2.0.0-SNAPSHOT/examples``), - indirect and linked paths (e.g. ``../apex/apex``), and - path substitutions using environment settings (e.g. - ``$APEX_HOME/bin/``) - - - For Windows systems, the provided batch files (``.bat``) - work as expected with with absolute paths (e.g. - ``C:\apex\apex-2.0.0-SNAPSHOT\examples``), and path - substitutions using environment settings (e.g. - ``%APEX_HOME%\bin\``) - - - For Cygwin system we assume a standard Cygwin - installation with standard tools (mainly bash) using a - Windows Java installation. This means that the bash - scripts can be used as in UNIX, however any argument - pointing to files and directories need to use either a - DOS path (e.g. - ``C:\apex\apex-2.0.0-SNAPSHOT\examples\config...``) or - the command ``cygpath`` with a mixed option. The reason - for that is: Cygwin executes Java using UNIX paths but - then runs Java as a DOS/WINDOWS process, which requires - DOS paths for file access. - -The APEX Engine ---------------- - - .. container:: paragraph - - The APEX engine can be started in different ways, depending - your requirements. All scripts are located in the APEX *bin* - directory - - .. container:: paragraph - - On UNIX and Cygwin systems use: - - .. container:: ulist - - - ``apexEngine.sh`` - this script will - - .. container:: ulist - - - Test if ``$APEX_USER`` is set and if the user - exists, terminate with an error otherwise - - - Test if ``$APEX_HOME`` is set. If not set, it will - use the default setting as - ``/opt/app/policy/apex-pdp/apex-pdp``. Then the set - directory is tested to exist, the script will - terminate if not. - - - When all tests are passed successfully, the script - will call ``apexApps.sh`` with arguments to start - the APEX engine. - - - ``apexApps.sh engine`` - this is the general APEX - application launcher, which will - - .. container:: ulist - - - Start the engine with the argument ``engine`` - - - Test if ``$APEX_HOME`` is set and points to an - existing directory. If not set or directory does - not exist, script terminates. - - - Not test for any settings of ``$APEX_USER``. - - .. container:: paragraph - - On Windows systems use ``apexEngine.bat`` and - ``apexApps.bat engine`` respectively. Note: none of the - windows batch files will test for ``%APEX_USER%``. - - .. container:: paragraph - - Summary of alternatives to start the APEX Engine: - - +--------------------------------------------------------+----------------------------------------------------------+ - | Unix, Cygwin | Windows | - +========================================================+==========================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: listingblock | .. container:: listingblock | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | | | - | # $APEX_HOME/bin/apexEngine.sh [args] | > %APEX_HOME%\bin\apexEngine.bat [args] | - | # $APEX_HOME/bin/apexApps.sh engine [args] | > %APEX_HOME%\bin\apexApps.bat engine [args] | - +--------------------------------------------------------+----------------------------------------------------------+ - - .. container:: paragraph - - The APEX engine comes with a few CLI arguments for setting - configuration and policy model. The configuration file is - always required. The policy model file is only required if - no model file is specified in the configuration, or if the - specified model file should be over written. The option - ``-h`` prints a help screen. - - .. container:: listingblock - - .. container:: content - - .. code:: - - usage: org.onap.policy.apex.service.engine.main.ApexMain [options...] - options - -c,--config-file <CONFIG_FILE> the full path to the configuration file to use, the configuration file must be a Json file - containing the Apex configuration parameters - -h,--help outputs the usage of this command - -m,--model-file <MODEL_FILE> the full path to the model file to use, if set it overrides the model file set in the - configuration file - -v,--version outputs the version of Apex - -The APEX CLI Editor -------------------- - - .. container:: paragraph - - The CLI Editor allows to define policies from the command - line. The application uses a simple language and supports - all elements of an APEX policy. It can be used in to - different ways: - - .. container:: ulist - - - non-interactive, specifying a file with the commands to - create a policy - - - interactive, using the editors CLI to create a policy - - .. container:: paragraph - - When a policy is fully specified, the editor will generate - the APEX core policy specification in JSON. This core - specification is called the policy model in the APEX engine - and can be used directly with the APEX engine. - - .. container:: paragraph - - On UNIX and Cygwin systems use: - - .. container:: ulist - - - ``apexCLIEditor.sh`` - simply starts the CLI editor, - arguments to the script determine the mode of the editor - - - ``apexApps.sh cli-editor`` - simply starts the CLI - editor, arguments to the script determine the mode of the - editor - - .. container:: paragraph - - On Windows systems use: - - .. container:: ulist - - - ``apexCLIEditor.bat`` - simply starts the CLI editor, - arguments to the script determine the mode of the editor - - - ``apexApps.bat cli-editor`` - simply starts the CLI - editor, arguments to the script determine the mode of the - editor - - .. container:: paragraph - - Summary of alternatives to start the APEX CLI Editor: - - +------------------------------------------------------------+--------------------------------------------------------------+ - | Unix, Cygwin | Windows | - +============================================================+==============================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: listingblock | .. container:: listingblock | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | | | - | # $APEX_HOME/bin/apexCLIEditor.sh.sh [args] | > %APEX_HOME%\bin\apexCLIEditor.bat [args] | - | # $APEX_HOME/bin/apexApps.sh cli-editor [args] | > %APEX_HOME%\bin\apexApps.bat cli-editor [args] | - +------------------------------------------------------------+--------------------------------------------------------------+ - - .. container:: paragraph - - The option ``-h`` provides a help screen with all command - line arguments. - - .. container:: listingblock - - .. container:: content - - .. code:: - - usage: org.onap.policy.apex.auth.clieditor.ApexCLIEditorMain [options...] - options - -a,--model-props-file <MODEL_PROPS_FILE> name of the apex model properties file to use - -c,--command-file <COMMAND_FILE> name of a file containing editor commands to run into the editor - -h,--help outputs the usage of this command - -i,--input-model-file <INPUT_MODEL_FILE> name of a file that contains an input model for the editor - -if,--ignore-failures <IGNORE_FAILURES_FLAG> true or false, ignore failures of commands in command files and continue - executing the command file - -l,--log-file <LOG_FILE> name of a file that will contain command logs from the editor, will log - to standard output if not specified or suppressed with "-nl" flag - -m,--metadata-file <CMD_METADATA_FILE> name of the command metadata file to use - -nl,--no-log if specified, no logging or output of commands to standard output or log - file is carried out - -nm,--no-model-output if specified, no output of a model to standard output or model output - file is carried out, the user can use the "save" command in a script to - save a model - -o,--output-model-file <OUTPUT_MODEL_FILE> name of a file that will contain the output model for the editor, will - output model to standard output if not specified or suppressed with - "-nm" flag - -wd,--working-directory <WORKING_DIRECTORY> the working directory that is the root for the CLI editor and is the - root from which to look for included macro files - -The APEX REST Editor --------------------- - - .. container:: paragraph - - The standard way to use the APEX REST Editor is via an - installation of the *war* file on a webserver. However, the - REST editor can also be started via command line. This will - start a Grizzly webserver with the *war* deployed. Access to - the REST Editor is then via the provided URL - - .. container:: paragraph - - On UNIX and Cygwin systems use: - - .. container:: ulist - - - ``apexRESTEditor.sh`` - simply starts the webserver with - the REST editor - - - ``apexApps.sh rest-editor`` - simply starts the webserver - with the REST editor - - .. container:: paragraph - - On Windows systems use: - - .. container:: ulist - - - ``apexRESTEditor.bat`` - simply starts the webserver with - the REST editor - - - ``apexApps.bat rest-editor`` - simply starts the - webserver with the REST editor - - .. container:: paragraph - - Summary of alternatives to start the APEX REST Editor: - - +-------------------------------------------------------------+---------------------------------------------------------------+ - | Unix, Cygwin | Windows | - +=============================================================+===============================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: listingblock | .. container:: listingblock | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | | | - | # $APEX_HOME/bin/apexRESTEditor.sh.sh [args] | > %APEX_HOME%\bin\apexRESTEditor.bat [args] | - | # $APEX_HOME/bin/apexApps.sh rest-editor [args] | > %APEX_HOME%\bin\apexApps.bat rest-editor [args] | - +-------------------------------------------------------------+---------------------------------------------------------------+ - - .. container:: paragraph - - The option ``-h`` provides a help screen with all command - line arguments. - - .. container:: listingblock - - .. container:: content - - .. code:: - - usage: org.onap.policy.apex.client.editor.rest.ApexEditorMain [options...] - -h,--help outputs the usage of this command - -l,--listen <ADDRESS> the IP address to listen on. Default value is localhost to restrict access to the - local machine only. - -p,--port <PORT> port to use for the Apex RESTful editor REST calls. - -t,--time-to-live <TIME_TO_LIVE> the amount of time in seconds that the server will run for before terminating. Default - value is -1 to run indefinitely. - - .. container:: paragraph - - If the REST Editor is started without any arguments the - final messages will look similar to this: - - .. container:: listingblock - - .. container:: content - - .. code:: - - Apex Editor REST endpoint (ApexEditorMain: Config=[ApexEditorParameters: URI=http://localhost:18989/apexservices/, TTL=-1sec], State=READY) starting at http://localhost:18989/apexservices/ . . . - Sep 05, 2018 11:24:30 PM org.glassfish.grizzly.http.server.NetworkListener start - INFO: Started listener bound to [localhost:18989] - Sep 05, 2018 11:24:30 PM org.glassfish.grizzly.http.server.HttpServer start - INFO: [HttpServer] Started. - Apex Editor REST endpoint (ApexEditorMain: Config=[ApexEditorParameters: URI=http://localhost:18989/apexservices/, TTL=-1sec], State=RUNNING) started at http://localhost:18989/apexservices/ - - .. container:: paragraph - - The last line states the URL on which the REST Editor can be - accessed. The example above stated - ``http://0.0.0.0:18989/apex/``. In a web browser use the URL - ``http://localhost:18989`` and the REST Editor will start. - -The APEX Monitoring Client --------------------------- - - .. container:: paragraph - - The standard way to use the APEX Monitoring Client is via an - installation of the *war* file on a webserver. However, the - Monitoring Client can also be started via command line. This - will start a Grizzly webserver with the *war* deployed. - Access to the Monitoring Client is then via the provided URL - - .. container:: paragraph - - On UNIX and Cygwin systems use: - - .. container:: ulist - - - ``apexApps.sh eng-monitoring`` - simply starts the - webserver with the Monitoring Client - - .. container:: paragraph - - On Windows systems use: - - .. container:: ulist - - - ``apexApps.bat eng-monitoring`` - simply starts the - webserver with the Monitoring Client - - .. container:: paragraph - - The option ``-h`` provides a help screen with all command - line arguments. - - .. container:: listingblock - - .. container:: content - - .. code:: - - usage: org.onap.policy.apex.client.monitoring.rest.ApexMonitoringRestMain [options...] - -h,--help outputs the usage of this command - -p,--port <PORT> port to use for the Apex Services REST calls - -t,--time-to-live <TIME_TO_LIVE> the amount of time in seconds that the server will run for before terminating - - .. container:: paragraph - - If the Monitoring Client is started without any arguments - the final messages will look similar to this: - - .. container:: listingblock - - .. container:: content - - .. code:: - - Apex Services REST endpoint (ApexMonitoringRestMain: Config=[ApexMonitoringRestParameters: URI=http://localhost:18989/apexservices/, TTL=-1sec], State=READY) starting at http://localhost:18989/apexservices/ . . . - Sep 05, 2018 11:26:20 PM org.glassfish.grizzly.http.server.NetworkListener start - INFO: Started listener bound to [localhost:18989] - Sep 05, 2018 11:26:20 PM org.glassfish.grizzly.http.server.HttpServer start - INFO: [HttpServer] Started. - Apex Services REST endpoint (ApexMonitoringRestMain: Config=[ApexMonitoringRestParameters: URI=http://localhost:18989/apexservices/, TTL=-1sec], State=RUNNING) started at http://localhost:18989/apexservices/ - - .. container:: paragraph - - The last line states the URL on which the Monitoring Client - can be accessed. The example above stated - ``http://localhost:18989/apexservices``. In a web browser - use the URL ``http://localhost:18989``. - -The APEX Deployment Client --------------------------- - - .. container:: paragraph - - The standard way to use the APEX Deployment Client is via an - installation of the *war* file on a webserver. However, the - Deployment Client can also be started via command line. This - will start a Grizzly webserver with the *war* deployed. - Access to the Deployment Client is then via the provided URL - - .. container:: paragraph - - On UNIX and Cygwin systems use: - - .. container:: ulist - - - ``apexApps.sh eng-deployment`` - simply starts the - webserver with the Deployment Client - - .. container:: paragraph - - On Windows systems use: - - .. container:: ulist - - - ``apexApps.bat eng-deployment`` - simply starts the - webserver with the Deployment Client - - .. container:: paragraph - - The option ``-h`` provides a help screen with all command - line arguments. - - .. container:: listingblock - - .. container:: content - - .. code:: - - usage: org.onap.policy.apex.client.deployment.rest.ApexDeploymentRestMain [options...] - -h,--help outputs the usage of this command - -p,--port <PORT> port to use for the Apex Services REST calls - -t,--time-to-live <TIME_TO_LIVE> the amount of time in seconds that the server will run for before terminating - - .. container:: paragraph - - If the Deployment Client is started without any arguments - the final messages will look similar to this: - - .. container:: listingblock - - .. container:: content - - .. code:: - - Apex Services REST endpoint (ApexDeploymentRestMain: Config=[ApexDeploymentRestParameters: URI=http://localhost:18989/apexservices/, TTL=-1sec], State=READY) starting at http://localhost:18989/apexservices/ . . . - Sep 05, 2018 11:27:09 PM org.glassfish.grizzly.http.server.NetworkListener start - INFO: Started listener bound to [localhost:18989] - Sep 05, 2018 11:27:09 PM org.glassfish.grizzly.http.server.HttpServer start - INFO: [HttpServer] Started. - Apex Services REST endpoint (ApexDeploymentRestMain: Config=[ApexDeploymentRestParameters: URI=http://localhost:18989/apexservices/, TTL=-1sec], State=RUNNING) started at http://localhost:18989/apexservices/ - - .. container:: paragraph - - The last line states the URL on which the Deployment Client - can be accessed. The example above stated - ``http://localhost:18989/apexservices``. In a web browser - use the URL ``http://localhost:18989``. - -The APEX Full Client --------------------- - - .. container:: paragraph - - The APEX Full Client combines the REST Editor, the - Monitoring Client, and the Deployment Client into a single - application. The standard way to use the APEX Full Client is - via an installation of the *war* file on a webserver. - However, the Full Client can also be started via command - line. This will start a Grizzly webserver with the *war* - deployed. Access to the Full Client is then via the provided - URL - - .. container:: paragraph - - On UNIX and Cygwin systems use: - - .. container:: ulist - - - ``apexApps.sh full-client`` - simply starts the webserver - with the Full Client - - .. container:: paragraph - - On Windows systems use: - - .. container:: ulist - - - ``apexApps.bat full-client`` - simply starts the - webserver with the Full Client - - .. container:: paragraph - - The option ``-h`` provides a help screen with all command - line arguments. - - .. container:: listingblock - - .. container:: content - - .. code:: - - usage: org.onap.policy.apex.client.full.rest.ApexServicesRestMain [options...] - -h,--help outputs the usage of this command - -p,--port <PORT> port to use for the Apex Services REST calls - -t,--time-to-live <TIME_TO_LIVE> the amount of time in seconds that the server will run for before terminating - - .. container:: paragraph - - If the Full Client is started without any arguments the - final messages will look similar to this: - - .. container:: listingblock - - .. container:: content - - .. code:: - - Apex Editor REST endpoint (ApexServicesRestMain: Config=[ApexServicesRestParameters: URI=http://localhost:18989/apexservices/, TTL=-1sec], State=READY) starting at http://localhost:18989/apexservices/ . . . - Sep 05, 2018 11:28:28 PM org.glassfish.grizzly.http.server.NetworkListener start - INFO: Started listener bound to [localhost:18989] - Sep 05, 2018 11:28:28 PM org.glassfish.grizzly.http.server.HttpServer start - INFO: [HttpServer] Started. - Apex Editor REST endpoint (ApexServicesRestMain: Config=[ApexServicesRestParameters: URI=http://localhost:18989/apexservices/, TTL=-1sec], State=RUNNING) started at http://localhost:18989/apexservices/ - - .. container:: paragraph - - The last line states the URL on which the Monitoring Client - can be accessed. The example above stated - ``http://localhost:18989/apexservices``. In a web browser - use the URL ``http://localhost:18989``. - - The APEX Application Launcher ------------------------------- - - .. container:: paragraph - - The standard applications (Engine, CLI Editor, REST Editor) - come with dedicated start scripts. For all other APEX - applications, we provide an application launcher. - - .. container:: paragraph - - On UNIX and Cygwin systems use: - - .. container:: ulist - - - apexApps.sh\` - simply starts the application launcher - - .. container:: paragraph - - On Windows systems use: - - .. container:: ulist - - - ``apexApps.bat`` - simply starts the application launcher - - .. container:: paragraph - - Summary of alternatives to start the APEX application - launcher: - - +-------------------------------------------------+---------------------------------------------------+ - | Unix, Cygwin | Windows | - +=================================================+===================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: listingblock | .. container:: listingblock | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | | | - | # $APEX_HOME/bin/apexApps.sh [args] | > %APEX_HOME%\bin\apexApps.bat [args] | - +-------------------------------------------------+---------------------------------------------------+ - - .. container:: paragraph - - The option ``-h`` provides a help screen with all launcher - command line arguments. - - .. container:: listingblock - - .. container:: content - - .. code:: - - apexApps.sh - runs APEX applications - - Usage: apexApps.sh [options] | [<application> [<application options>]] - - Options - -d <app> - describes an application - -l - lists all applications supported by this script - -h - this help screen - - .. container:: paragraph - - Using ``-l`` lists all known application the launcher can - start. - - .. container:: listingblock - - .. container:: content - - .. code:: - - apexApps.sh: supported applications: - --> ws-echo engine eng-monitoring full-client eng-deployment tpl-event-json model-2-cli rest-editor cli-editor ws-console - - .. container:: paragraph - - Using the ``-d <name>`` option describes the named - application, for instance for the ``ws-console``: - - .. container:: listingblock - - .. container:: content - - .. code:: - - apexApps.sh: application 'ws-console' - --> a simple console sending events to APEX, connect to APEX consumer port - - .. container:: paragraph - - Launching an application is done by calling the script with - only the application name and any CLI arguments for the - application. For instance, starting the ``ws-echo`` - application with port ``8888``: - - .. container:: listingblock - - .. container:: content - - .. code:: - - apexApps.sh ws-echo -p 8888 - -Application: Create Event Templates ------------------------------------ - - .. container:: paragraph - - **Status: Experimental** - - .. container:: paragraph - - This application takes a policy model (JSON or XML encoded) - and generates templates for events in JSON format. This can - help when a policy defines rather complex trigger or action - events or complex events between states. The application can - produce events for the types: stimuli (policy trigger - events), internal (events between policy states), and - response (action events). - - +----------------------------------------------------------------+------------------------------------------------------------------+ - | Unix, Cygwin | Windows | - +================================================================+==================================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: listingblock | .. container:: listingblock | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | | | - | # $APEX_HOME/bin/apexApps.sh tpl-event-json [args] | > %APEX_HOME%\bin\apexApps.bat tpl-event-json [args] | - +----------------------------------------------------------------+------------------------------------------------------------------+ - - .. container:: paragraph - - The option ``-h`` provides a help screen. - - .. container:: listingblock - - .. container:: content - - .. code:: - - gen-model2event v{release-version} - generates JSON templates for events generated from a policy model - usage: gen-model2event - -h,--help prints this help and usage screen - -m,--model <MODEL-FILE> set the input policy model file - -t,--type <TYPE> set the event type for generation, one of: - stimuli (trigger events), response (action - events), internal (events between states) - -v,--version prints the application version - - .. container:: paragraph - - The created templates are not valid events, instead they use - some markup for values one will need to change to actual - values. For instance, running the tool with the *Sample - Domain* policy model as: - - .. container:: listingblock - - .. container:: content - - .. code:: - - apexApps.sh tpl-event-json -m $APEX_HOME/examples/models/SampleDomain/SamplePolicyModelJAVA.json -t stimuli - - .. container:: paragraph - - will produce the following status messages: - - .. container:: listingblock - - .. container:: content - - .. code:: - - gen-model2event: starting Event generator - --> model file: examples/models/SampleDomain/SamplePolicyModelJAVA.json - --> type: stimuli - - .. container:: paragraph - - and then run the generator application producing two event - templates. The first template is called ``Event0000``. - - .. container:: listingblock - - .. container:: content - - .. code:: - - { - "name" : "Event0000", - "nameSpace" : "org.onap.policy.apex.sample.events", - "version" : "0.0.1", - "source" : "Outside", - "target" : "Match", - "TestTemperature" : ###double: 0.0###, - "TestTimestamp" : ###long: 0###, - "TestMatchCase" : ###integer: 0###, - "TestSlogan" : "###string###" - } - - .. container:: paragraph - - The values for the keys are marked with ``#`` and the - expected type of the value. To create an actual stimuli - event, all these markers need to be change to actual values, - for instance: - - .. container:: listingblock - - .. container:: content - - .. code:: - - { - "name" : "Event0000", - "nameSpace" : "org.onap.policy.apex.sample.events", - "version" : "0.0.1", - "source" : "Outside", - "target" : "Match", - "TestTemperature" : 25, - "TestTimestamp" : 123456789123456789, - "TestMatchCase" : 1, - "TestSlogan" : "Testing the Match Case with Temperature 25" - } - -Application: Convert a Policy Model to CLI Editor Commands ----------------------------------------------------------- - - .. container:: paragraph - - **Status: Experimental** - - .. container:: paragraph - - This application takes a policy model (JSON or XML encoded) - and generates commands for the APEX CLI Editor. This - effectively reverses a policy specification realized with - the CLI Editor. - - +-------------------------------------------------------------+---------------------------------------------------------------+ - | Unix, Cygwin | Windows | - +=============================================================+===============================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: listingblock | .. container:: listingblock | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | | | - | # $APEX_HOME/bin/apexApps.sh model-2-cli [args] | > %APEX_HOME%\bin\apexApps.bat model-2-cli [args] | - +-------------------------------------------------------------+---------------------------------------------------------------+ - - .. container:: paragraph - - The option ``-h`` provides a help screen. - - .. container:: listingblock - - .. container:: content - - .. code:: - - usage: gen-model2cli - -h,--help prints this help and usage screen - -m,--model <MODEL-FILE> set the input policy model file - -sv,--skip-validation switch of validation of the input file - -v,--version prints the application version - - .. container:: paragraph - - For instance, running the tool with the *Sample Domain* - policy model as: - - .. container:: listingblock - - .. container:: content - - .. code:: - - apexApps.sh model-2-cli -m $APEX_HOME/examples/models/SampleDomain/SamplePolicyModelJAVA.json - - .. container:: paragraph - - will produce the following status messages: - - .. container:: listingblock - - .. container:: content - - .. code:: - - gen-model2cli: starting CLI generator - --> model file: examples/models/SampleDomain/SamplePolicyModelJAVA.json - - .. container:: paragraph - - and then run the generator application producing all CLI - Editor commands and printing them to standard out. - -Application: Websocket Clients (Echo and Console) -------------------------------------------------- - - .. container:: paragraph - - **Status: Production** - - .. container:: paragraph - - The application launcher also provides a Websocket echo - client and a Websocket console client. The echo client - connects to APEX and prints all events it receives from - APEX. The console client connects to APEX, reads input from - the command line, and sends this input as events to APEX. - - +------------------------------------------------------------+--------------------------------------------------------------+ - | Unix, Cygwin | Windows | - +============================================================+==============================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: listingblock | .. container:: listingblock | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | | | - | # $APEX_HOME/bin/apexApps.sh ws-echo [args] | > %APEX_HOME%\bin\apexApps.bat ws-echo [args] | - | # $APEX_HOME/bin/apexApps.sh ws-console [args] | > %APEX_HOME%\bin\apexApps.bat ws-console [args] | - +------------------------------------------------------------+--------------------------------------------------------------+ - - .. container:: paragraph - - The arguments are the same for both applications: - - .. container:: ulist - - - ``-p`` defines the Websocket port to connect to (defaults - to ``8887``) - - - ``-s`` defines the host on which a Websocket server is - running (defaults to ``localhost``) - - .. container:: paragraph - - A discussion on how to use these two applications to build - an APEX system is detailed HowTo-Websockets. - -My First Policy -^^^^^^^^^^^^^^^ - -Introduction ------------- - .. container:: paragraph - - Consider a scenario where a supermarket chain called - *HyperM* controls how it sells items in a policy-based - manner. Each time an item is processed by *HyperM*'s - point-of-sale (PoS) system an event is generated and - published about that item of stock being sold. This event - can then be used to update stock levels, etc.. - - .. container:: paragraph - - *HyperM* want to extend this approach to allow some checks - to be performed before the sale can be completed. This can - be achieved by requesting a policy-controlled decision as - each item is processed by for sale by each PoS system. The - decision process is integrated with *HyperM*'s other IT - systems that manage stock control, sourcing and purchasing, - personnel systems, etc. - - .. container:: paragraph - - In this document we will show how APEX and APEX Policies can - be used to achieve this, starting with a simple policy, - building up to more complicated policy that demonstrates the - features of APEX. - -Data Models ------------ - -Sales Input Event -################# - - .. container:: paragraph - - Each time a PoS system processes a sales item an event - with the following format is emitted: - - .. table:: Table 1. Sale Input Event - - +----------------------+----------------------+-----------------------+ - | Event | Fields | Description | - +======================+======================+=======================+ - | SALE_INPUT | time, sale_ID, | Event indicating a | - | | amount, item_ID, | sale of an item is | - | | quantity, | occurring | - | | assistant_ID, | | - | | branch_ID, notes, … | | - +----------------------+----------------------+-----------------------+ - - .. container:: paragraph - - In each ``SALE_INPUT`` event the ``sale_ID`` field is a - unique ID generated by the PoS system. A timestamp for - the event is stored in the ``time`` field. The ``amount`` - field refers to the value of the item(s) to be sold (in - cents). The ``item_ID`` field is a unique identifier for - each item type, and can be used to retrieve more - information about the item from *HyperM*'s stock control - system. The ``quantity`` field refers to the quantity of - the item to be sold. The ``assistant_ID`` field is a - unique identifier for the PoS operator, and can be used - to retrieve more information about the operator from the - *HyperM*'s personnel system. Since *HyperM* has many - branches the ``branch_ID`` identifies the shop. The - ``notes`` field contains arbitrary notes about the sale. - -Sales Decision Event -#################### - - .. container:: paragraph - - After a ``SALE_INPUT`` event is emitted by the PoS system - *HyperM*'s policy-based controlled sales checking system - emits a Sale Authorization Event indicating whether the - sale is authorized or denied. The PoS system can then - listen for this event before continuing with the sale. - - .. table:: Table 2. Sale Authorisation Event - - +----------------------+----------------------+-----------------------+ - | Event | Fields | Description | - +======================+======================+=======================+ - | SALE_AUTH | sale_ID, time, | Event indicating a | - | | authorized, amount, | sale of an item is | - | | item_ID, quantity, | authorized or denied | - | | assistant_ID, | | - | | branch_ID, notes, | | - | | message… | | - +----------------------+----------------------+-----------------------+ - - .. container:: paragraph - - In each ``SALE_AUTH`` event the ``sale_ID`` field is - copied from the ``SALE_INPUT`` event that trigger the - decision request. The ``SALE_AUTH`` event is also - timestamped using the ``time`` field, and a field called - ``authorised`` is set to ``true`` or ``false`` depending - on whether the sale is authorized or denied. The - ``message`` field carries an optional message about why a - sale was not authorized. The other fields from the - ``SALE_INPUT`` event are also included for completeness. - -Stock Control: Items -#################### - - .. container:: paragraph - - *HyperM* maintains information about each item for sale - in a database table called ``ITEMS``. - - .. table:: Table 3. Items Database - - +----------------------+----------------------+-----------------------+ - | Table | Fields | Description | - +======================+======================+=======================+ - | ITEMS | item_ID, | Database table | - | | description, | describing each item | - | | cost_price, barcode, | for sale | - | | supplier_ID, | | - | | category, … | | - +----------------------+----------------------+-----------------------+ - - .. container:: paragraph - - The database table ``ITEMS`` has a row for each items - that *HyperM* sells. Each item is identified by an - ``item_ID`` value. The ``description`` field stores a - description of the item. The cost price of the item is - given in ``cost_price``. The barcode of the item is - encoded in ``barcode``, while the item supplier is - identified by ``supplier_ID``. Items may also be - classified into categories using the ``category`` field. - Useful categories might include: ``soft drinks``, - ``alcoholic drinks``, ``cigarettes``, ``knives``, - ``confectionery``, ``bakery``, ``fruit&vegetables``, - ``meat``, etc.. - -Personnel System: Assistants -############################ - - .. table:: Table 4. Assistants Database - - +----------------------+----------------------+-----------------------+ - | Table | Fields | Description | - +======================+======================+=======================+ - | ASSISTANTS | assistant_ID, | Database table | - | | surname, firstname, | describing each | - | | middlename, age, | *HyperM* sales | - | | grade, phone_number, | assistant | - | | … | | - +----------------------+----------------------+-----------------------+ - - .. container:: paragraph - - The database table ``ASSISTANTS`` has a row for each - sales assistant employed by *HyperM*. Each assistant is - identified by an ``assistant_ID`` value, with their name - given in the ``firstname``, ``middlename`` and - ``surname`` fields. The assistant’s age in years is given - in ``age``, while their phone number is contained in the - ``phone_number`` field. The assistant’s grade is encoded - in ``grade``. Useful values for ``grade`` might include: - ``trainee``, ``operator``, ``supervisor``, etc.. - -Locations: Branches -#################### - - .. table:: Table 5. Branches Database - - +----------------------+----------------------+-----------------------+ - | Table | Fields | Description | - +======================+======================+=======================+ - | BRANCHES | branch_ID, | Database table | - | | branch_Name, | describing each | - | | category, street, | *HyperM* branch | - | | city, country, | | - | | postcode, … | | - +----------------------+----------------------+-----------------------+ - - .. container:: paragraph - - *HyperM* operates a number of branches. Each branch is - described in the ``BRANCHES`` database table. Each branch - is identified by a ``branch_ID``, with a branch name - given in ``branch_Name``. The address for the branch is - encoded in ``street``, ``city``, ``country`` and - ``postcode``. The branch category is given in the - ``category`` field. Useful values for ``category`` might - include: ``Small``, ``Large``, ``Super``, ``Hyper``, - etc.. - -Policy Step 1 -------------- - -Scenario -######### - .. container:: paragraph - - For the first version of our policy, let’s start with - something simple. Let us assume that there exists some - restriction that alcohol products cannot be sold before - 11:30am. In this section we will go through the necessary - steps to define a policy that can enforce this for - *HyperM*. - - .. container:: ulist - - - Alcohol cannot be sold before 11:30am. - -Create the an new empty Policy Model ``MyFirstPolicyModel`` -########################################################### - - .. container:: paragraph - - Since an organisation like *HyperM* may have many - policies covering many different domains, policies should - be grouped into policy sets. In order to edit or deploy a - policy, or policy set, the definition of the policy(ies) - and all required events, tasks, states, etc., are grouped - together into a 'Policy Model'. An organization might - define many Policy Models, each containing a different - set of policies. - - .. container:: paragraph - - So the first step is to create a new empty Policy Model - called ``MyFirstPolicyModel``. Using the APEX Policy - Editor, click on the 'File' menus and select 'New'. Then - define our new policy model called - ``MyFirstPolicyModel``. Use the 'Generate UUID' button to - create a new unique ID for the policy model, and fill in - a description for the policy model. Press the ``Submit`` - button to save your changes. - - .. container:: imageblock - - .. container:: content - - |File > New to create a new Policy Model| - - .. container:: title - - Figure 4. Create a new Policy Model 1/2 - - .. container:: imageblock - - .. container:: content - - |Create a new Policy Model| - - .. container:: title - - Figure 5. Create a new Policy Model 2/2 - -Create the input event ``SALE_INPUT`` and the output event ``SALE_AUTH`` -######################################################################## - - .. container:: paragraph - - Using the APEX Policy Editor, click on the 'Events' tab. - In the 'Events' pane, right click and select 'New': - - .. container:: imageblock - - .. container:: content - - |Right click to create a new event| - - .. container:: title - - Figure 6. Create a new Event type - - .. container:: paragraph - - Create a new event type called ``SALE_INPUT``. Use the - 'Generate UUID' button to create a new unique ID for the - event type, and fill in a description for the event. Add - a namespace, e.g. ``com.hyperm``. We can add hard-coded - strings for the ``Source`` and ``Target``, e.g. ``POS`` - and ``APEX``. At this stage we will not add any parameter - fields, we will leave this until later. Use the - ``Submit`` button to create the event. - - .. container:: imageblock - - .. container:: content - - |Fill in the necessary information for the - 'SALE_INPUT' event and click 'Submit'| - - .. container:: title - - Figure 7. Populate the ``SALE_INPUT`` event - - .. container:: paragraph - - Repeat the same steps for a new event type called - ``SALE_AUTH``. Just use ``APEX`` as source and ``POS`` as - target, since this is the output event coming from APEX - going to the sales point. - - .. container:: paragraph - - Before we can add parameter fields to an event we must - first define APEX Context Item Schemas that can be used - by those fields. - - .. container:: paragraph - - To create new item schemas, click on the 'Context Item - Schemas' tab. In that 'Context Item Schemas' pane, right - click and select 'Create new ContextSchema'. - - .. container:: imageblock - - .. container:: content - - |Right click to create a new Item Schema| - - .. container:: title - - Figure 8. Create new Data Types - - .. container:: paragraph - - Create item schemas with the following characteristics, - each with its own unique UUID: - - .. table:: Table 6. Item Schemas - - +-------------------+-----------------+-----------------+----------------------+ - | Name | Schema Flavour | Schema | Description | - | | | Definition | | - +===================+=================+=================+======================+ - | timestamp_type | Java | java.lang.Long | A type for | - | | | | ``time`` values | - +-------------------+-----------------+-----------------+----------------------+ - | sale_ID_type | Java | java.lang.Long | A type for | - | | | | ``sale_ID`` | - | | | | values | - +-------------------+-----------------+-----------------+----------------------+ - | price_type | Java | java.lang.Long | A type for | - | | | | ``amount``/``price`` | - | | | | values | - +-------------------+-----------------+-----------------+----------------------+ - | item_ID_type | Java | java.lang.Long | A type for | - | | | | ``item_ID`` | - | | | | values | - +-------------------+-----------------+-----------------+----------------------+ - | assistant_ID_type | Java | java.lang.Long | A type for | - | | | | ``assistant_ID`` | - | | | | values | - +-------------------+-----------------+-----------------+----------------------+ - | quantity_type | Java | java.lang.Integ | A type for | - | | | er | ``quantity`` | - | | | | values | - +-------------------+-----------------+-----------------+----------------------+ - | branch_ID_type | Java | java.lang.Long | A type for | - | | | | ``branch_ID`` | - | | | | values | - +-------------------+-----------------+-----------------+----------------------+ - | notes_type | Java | java.lang.Strin | A type for | - | | | g | ``notes`` | - | | | | values | - +-------------------+-----------------+-----------------+----------------------+ - | authorised_type | Java | java.lang.Boole | A type for | - | | | an | ``authorised`` | - | | | | values | - +-------------------+-----------------+-----------------+----------------------+ - | message_type | Java | java.lang.Strin | A type for | - | | | g | ``message`` | - | | | | values | - +-------------------+-----------------+-----------------+----------------------+ - - .. container:: imageblock - - .. container:: content - - |Create a new Item Schema| - - .. container:: title - - Figure 9. Create new Item Schemas - - .. container:: paragraph - - The item schemas can now be seen on the 'Context Item - Schemas' tab, and can be updated at any time by - right-clicking on the item schemas on the 'Context Item - Schemas' tab. Now we can go back to the event definitions - for ``SALE_INPUT`` and ``SALE_AUTH`` and add some - parameter fields. - - .. tip - - .. container:: title - - Field Schema types - - .. container:: paragraph - - APEX natively supports schema definitions in ``Java`` and ``Avro``. - - .. container:: paragraph - - ``Java`` schema definitions are simply the name of a Java Class. There are some restrictions: - - .. container:: ulist - - - the class must be instantiatable, i.e. not an Java interface or abstract class - - - primitive types are not supported, i.e. use ``java.lang.Integer`` instead of ``int``, etc. - - - it must be possible to find the class, i.e. the class must be contained in the Java classpath. - - .. container:: paragraph - - ``Avro`` schema definitions can be any valid `Avro <https://avro.apache.org/docs/current/spec.html>`__ - schema. For events using fields defined with ``Avro`` schemas, any incoming event containing that field must - contain a value that conforms to the Avro schema. - - .. container:: paragraph - - Click on the 'Events' tab, then right click the - ``SALE_INPUT`` row and select 'Edit Event - :literal:`SALE_INPUT’. To add a new event parameter use the 'Add Event Parameter' button at the bottom of the screen. For the `SALE_INPUT` - event add the following event parameters: - - .. table:: Table 7. Event Parameter Fields for the ``SALE_INPUT`` Event - - +----------------------+----------------------+-----------------------+ - | Parameter Name | Parameter Type | Optional | - +======================+======================+=======================+ - | time | timestamp_type | no | - +----------------------+----------------------+-----------------------+ - | sale_ID | sale_ID_type | no | - +----------------------+----------------------+-----------------------+ - | amount | price_type | no | - +----------------------+----------------------+-----------------------+ - | item_ID | item_ID_type | no | - +----------------------+----------------------+-----------------------+ - | quantity | quantity_type | no | - +----------------------+----------------------+-----------------------+ - | assistant_ID | assistant_ID_type | no | - +----------------------+----------------------+-----------------------+ - | branch_ID | branch_ID_type | no | - +----------------------+----------------------+-----------------------+ - | notes | notes_type | *yes* | - +----------------------+----------------------+-----------------------+ - - .. container:: paragraph - - Remember to click the 'Submit' button at the bottom of - the event definition pane. - - .. tip:: - Optional Fields in APEX Events - Parameter fields can be *optional* in events. If a parameter is not marked as *optional* then by default it - is *mandatory*, so it must appear in any input event passed to APEX. If an *optional* field is not set - for an output event then value will be set to ``null``. - - .. container:: imageblock - - .. container:: content - - |Add new event parameters to an event| - - .. container:: title - - Figure 10. Add typed parameter fields to an event - - .. container:: paragraph - - Select the ``SALE_AUTH`` event and add the following - event parameters: - - .. table:: Table 8. Event Parameter Fields for the ``SALE_AUTH`` Event - - +----------------------+----------------------+-----------------------+ - | Parameter Name | Parameter Type | no | - +======================+======================+=======================+ - | sale_ID | sale_ID_type | no | - +----------------------+----------------------+-----------------------+ - | time | timestamp_type | no | - +----------------------+----------------------+-----------------------+ - | authorised | authorised_type | no | - +----------------------+----------------------+-----------------------+ - | message | message_type | *yes* | - +----------------------+----------------------+-----------------------+ - | amount | price_type | no | - +----------------------+----------------------+-----------------------+ - | item_ID | item_ID_type | no | - +----------------------+----------------------+-----------------------+ - | assistant_ID | assistant_ID_type | no | - +----------------------+----------------------+-----------------------+ - | quantity | quantity_type | no | - +----------------------+----------------------+-----------------------+ - | branch_ID | branch_ID_type | no | - +----------------------+----------------------+-----------------------+ - | notes | notes_type | *yes* | - +----------------------+----------------------+-----------------------+ - - .. container:: paragraph - - Remember to click the 'Submit' button at the bottom of - the event definition pane. - - .. container:: paragraph - - The events for our policy are now defined. - -Create a new Policy and add the *"No Booze before 11:30"* check -############################################################### - - .. container:: paragraph - - APEX policies are defined using a state-machine model. - Each policy comprises one or more *states* that can be - individually executed. Where there is more than one - *state* the states are chained together to form a - `Directed Acyclic Graph - (DAG) <https://en.wikipedia.org/wiki/Directed_acyclic_graph>`__ - of states. A *state* is triggered by passing it a single - input (or 'trigger') event and once executed each state - then emits an output event. For each *state* the logic - for the *state* is embedded in one or more *tasks*. Each - *task* contains specific *task logic* that is executed by - the APEX execution environment each time the *task* is - invoked. Where there is more than one *task* in a *state* - then the *state* also defines some *task selection logic* - to select an appropriate task each time the *state* is - executed. - - .. container:: paragraph - - Therefore, to create a new policy we must first define - one or more tasks. - - .. container:: paragraph - - To create a new Task click on the 'Tasks' tab. In the - 'Tasks' pane, right click and select 'Create new Task'. - Create a new Task called ``MorningBoozeCheck``. Use the - 'Generate UUID' button to create a new unique ID for the - task, and fill in a description for the task. - - .. container:: imageblock - - .. container:: content - - |Right click to create a new task| - - .. container:: title - - Figure 11. Create a new Task - - .. container:: paragraph - - Tasks are configured with a set of *input fields* and a - set of *output fields*. To add new input/output fields - for a task use the 'Add Task Input Field' and 'Add Task - Output Field' button. The list of input and out fields to - add for the ``MorningBoozeCheck`` task are given below. - The input fields are drawn from the parameters in the - state’s input event, and the task’s output fields are - used to populate the state’s output event. The task’s - input and output fields must be a subset of the event - parameters defined for the input and output events for - any state that uses that task. (You may have noticed that - the input and output fields for the ``MorningBoozeCheck`` - task have the exact same names and reuse the item schemas - that we used for the parameters in the ``SALE_INPUT`` and - ``SALE_AUTH`` events respectively). - - .. table:: Table 9. Input fields for ``MorningBoozeCheck`` task - - +-----------------------------------+-----------------------------------+ - | Parameter Name | Parameter Type | - +===================================+===================================+ - | time | timestamp_type | - +-----------------------------------+-----------------------------------+ - | sale_ID | sale_ID_type | - +-----------------------------------+-----------------------------------+ - | amount | price_type | - +-----------------------------------+-----------------------------------+ - | item_ID | item_ID_type | - +-----------------------------------+-----------------------------------+ - | quantity | quantity_type | - +-----------------------------------+-----------------------------------+ - | assistant_ID | assistant_ID_type | - +-----------------------------------+-----------------------------------+ - | branch_ID | branch_ID_type | - +-----------------------------------+-----------------------------------+ - | notes | notes_type | - +-----------------------------------+-----------------------------------+ - - .. table:: Table 10. Output fields for ``MorningBoozeCheck`` task - - +-----------------------------------+-----------------------------------+ - | Parameter Name | Parameter Type | - +===================================+===================================+ - | sale_ID | sale_ID_type | - +-----------------------------------+-----------------------------------+ - | time | timestamp_type | - +-----------------------------------+-----------------------------------+ - | authorised | authorised_type | - +-----------------------------------+-----------------------------------+ - | message | message_type | - +-----------------------------------+-----------------------------------+ - | amount | price_type | - +-----------------------------------+-----------------------------------+ - | item_ID | item_ID_type | - +-----------------------------------+-----------------------------------+ - | assistant_ID | assistant_ID_type | - +-----------------------------------+-----------------------------------+ - | quantity | quantity_type | - +-----------------------------------+-----------------------------------+ - | branch_ID | branch_ID_type | - +-----------------------------------+-----------------------------------+ - | notes | notes_type | - +-----------------------------------+-----------------------------------+ - - .. container:: imageblock - - .. container:: content - - |Add input and out fields for the task| - - .. container:: title - - Figure 12. Add input and out fields for the Task - - .. container:: paragraph - - Each task must include some 'Task Logic' that implements - the behaviour for the task. Task logic can be defined in - a number of different ways using a choice of languages. - For this task we will author the logic using the - Java-like scripting language called - ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__. - - .. container:: paragraph - - For simplicity use the following code for the task logic. - Paste the script text into the 'Task Logic' box, and use - "MVEL" as the 'Task Logic Type / Flavour'. - - .. container:: paragraph - - This logic assumes that all items with ``item_ID`` - between 1000 and 2000 contain alcohol, which is not very - realistic, but we will see a better approach for this - later. It also uses the standard ``Java`` time utilities - to check if the current time is between ``00:00:00 GMT`` - and ``11:30:00 GMT``. For a detailed guide to how to - write your own logic in - ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__, - ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__ or one - of the other supported languages please refer to APEX - Programmers Guide. - - .. container:: listingblock - - .. container:: title - - MVEL code for the ``MorningBoozeCheck`` task - - .. container:: content - - .. code:: - - /* - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - import java.util.Date; - import java.util.Calendar; - import java.util.TimeZone; - import java.text.SimpleDateFormat; - - logger.info("Task Execution: '"+subject.id+"'. Input Fields: '"+inFields+"'"); - - outFields.put("amount" , inFields.get("amount")); - outFields.put("assistant_ID", inFields.get("assistant_ID")); - outFields.put("notes" , inFields.get("notes")); - outFields.put("quantity" , inFields.get("quantity")); - outFields.put("branch_ID" , inFields.get("branch_ID")); - outFields.put("item_ID" , inFields.get("item_ID")); - outFields.put("time" , inFields.get("time")); - outFields.put("sale_ID" , inFields.get("sale_ID")); - - item_id = inFields.get("item_ID"); - - //The events used later to test this task use GMT timezone! - gmt = TimeZone.getTimeZone("GMT"); - timenow = Calendar.getInstance(gmt); - df = new SimpleDateFormat("HH:mm:ss z"); - df.setTimeZone(gmt); - timenow.setTimeInMillis(inFields.get("time")); - - midnight = timenow.clone(); - midnight.set( - timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), - timenow.get(Calendar.DATE),0,0,0); - eleven30 = timenow.clone(); - eleven30.set( - timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), - timenow.get(Calendar.DATE),11,30,0); - - itemisalcohol = false; - if(item_id != null && item_id >=1000 && item_id < 2000) - itemisalcohol = true; - - if( itemisalcohol - && timenow.after(midnight) && timenow.before(eleven30)){ - outFields.put("authorised", false); - outFields.put("message", "Sale not authorised by policy task "+subject.taskName+ - " for time "+df.format(timenow.getTime())+ - ". Alcohol can not be sold between "+df.format(midnight.getTime())+ - " and "+df.format(eleven30.getTime())); - return true; - } - else{ - outFields.put("authorised", true); - outFields.put("message", "Sale authorised by policy task "+subject.taskName+ - " for time "+df.format(timenow.getTime())); - return true; - } - - /* - This task checks if a sale request is for an item that is an alcoholic drink. - If the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not - authorised. Otherwise the sale is authorised. - In this implementation we assume that items with item_ID value between 1000 and - 2000 are all alcoholic drinks :-) - */ - - .. container:: imageblock - - .. container:: content - - |Add task logic the task| - - .. container:: title - - Figure 13. Add Task Logic the Task - - .. container:: paragraph - - An alternative version of the same logic is available in - JavaScript. Just use "JAVASCRIPT" as the 'Task Logic Type - / Flavour' instead. - - .. container:: listingblock - - .. container:: title - - Javascript alternative for the ``MorningBoozeCheck`` - task - - .. container:: content - - .. code:: - - /* - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - - var returnValueType = Java.type("java.lang.Boolean"); - var returnValue = new returnValueType(true); - - // Load compatibility script for imports etc - load("nashorn:mozilla_compat.js"); - importPackage(java.text); - importClass(java.text.SimpleDateFormat); - - executor.logger.info("Task Execution: '"+executor.subject.id+"'. Input Fields: '"+executor.inFields+"'"); - - executor.outFields.put("amount" , executor.inFields.get("amount")); - executor.outFields.put("assistant_ID", executor.inFields.get("assistant_ID")); - executor.outFields.put("notes" , executor.inFields.get("notes")); - executor.outFields.put("quantity" , executor.inFields.get("quantity")); - executor.outFields.put("branch_ID" , executor.inFields.get("branch_ID")); - executor.outFields.put("item_ID" , executor.inFields.get("item_ID")); - executor.outFields.put("time" , executor.inFields.get("time")); - executor.outFields.put("sale_ID" , executor.inFields.get("sale_ID")); - - item_id = executor.inFields.get("item_ID"); - - //All times in this script are in GMT/UTC since the policy and events assume time is in GMT. - var timenow_gmt = new Date(Number(executor.inFields.get("time"))); - - var midnight_gmt = new Date(Number(executor.inFields.get("time"))); - midnight_gmt.setUTCHours(0,0,0,0); - - var eleven30_gmt = new Date(Number(executor.inFields.get("time"))); - eleven30_gmt.setUTCHours(11,30,0,0); - - var timeformatter = new java.text.SimpleDateFormat("HH:mm:ss z"); - - var itemisalcohol = false; - if(item_id != null && item_id >=1000 && item_id < 2000) - itemisalcohol = true; - - if( itemisalcohol - && timenow_gmt.getTime() >= midnight_gmt.getTime() - && timenow_gmt.getTime() < eleven30_gmt.getTime()) { - - executor.outFields.put("authorised", false); - executor.outFields.put("message", "Sale not authorised by policy task " + - executor.subject.taskName+ " for time " + timeformatter.format(timenow_gmt.getTime()) + - ". Alcohol can not be sold between " + timeformatter.format(midnight_gmt.getTime()) + - " and " + timeformatter.format(eleven30_gmt.getTime())); - } - else{ - executor.outFields.put("authorised", true); - executor.outFields.put("message", "Sale authorised by policy task " + - executor.subject.taskName + " for time "+timeformatter.format(timenow_gmt.getTime())); - } - - /* - This task checks if a sale request is for an item that is an alcoholic drink. - If the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not - authorised. Otherwise the sale is authorised. - In this implementation we assume that items with item_ID value between 1000 and - 2000 are all alcoholic drinks :-) - */ - - .. container:: paragraph - - The task definition is now complete so click the 'Submit' - button to save the task. The task can now be seen on the - 'Tasks' tab, and can be updated at any time by - right-clicking on the task on the 'Task' tab. Now that we - have created our task, we can can create a policy that - uses that task. - - .. container:: paragraph - - To create a new Policy click on the 'Policies' tab. In - the 'Policies' pane, right click and select 'Create new - Policy': - - .. container:: paragraph - - Create a new Policy called ``MyFirstPolicy``. Use the - 'Generate UUID' button to create a new unique ID for the - policy, and fill in a description for the policy. Use - 'FREEFORM' as the 'Policy Flavour'. - - .. container:: paragraph - - Each policy must have at least one state. Since this is - 'freeform' policy we can add as many states as we wish. - Let’s start with one state. Add a new state called - ``BoozeAuthDecide`` to this ``MyFirstPolicy`` policy - using the 'Add new State' button after filling in the - name of our new state. - - .. container:: imageblock - - .. container:: content - - |Create a new policy| - - .. container:: title - - Figure 14. Create a new Policy - - .. container:: paragraph - - Each state must uses one input event type. For this new - state select the ``SALE_INPUT`` event as the input event. - - .. container:: paragraph - - Each policy must define a 'First State' and a 'Policy - Trigger Event'. The 'Policy Trigger Event' is the input - event for the policy as a whole. This event is then - passed to the first state in the chain of states in the - policy, therefore the 'Policy Trigger Event' will be the - input event for the first state. Each policy can only - have one 'First State'. For our ``MyFirstPolicy`` policy, - select ``BoozeAuthDecide`` as the 'First State'. This - will automatically select ``SALE_INPUT`` as the 'Policy - Trigger Event' for our policy. - - .. container:: imageblock - - .. container:: content - - |Create a state| - - .. container:: title - - Figure 15. Create a new State - - .. container:: paragraph - - In this case we will create a reference the pre-existing - ``MorningBoozeCheck`` task that we defined above using - the 'Add New Task' button. Select the - ``MorningBoozeCheck`` task, and use the name of the task - as the 'Local Name' for the task. - - .. container:: paragraph - - in the case where a state references more than one task, - a 'Default Task' must be selected for the state and some - logic ('Task Selection Logic') must be specified to - select the appropriate task at execution time. Since our - new state ``BoozeAuthDecide`` only has one task the - default task is automatically selected and no 'Task - Selection Logic' is required. - - .. note:: - .. container:: title - - State Output Mappings - - .. container:: paragraph - - In a 'Policy' 'State' a 'State Output Mapping' has 3 roles: - 1) Select which 'State' should be executed next, 2) Select - the type of the state’s 'Outgoing Event', and 3) - Populate the state’s 'Outgoing Event'. This is how states are - chained together to form a (`Directed Acyclic Graph - (DAG) <https://en.wikipedia.org/wiki/Directed_acyclic_graph>`__ ) - of states. The final state(s) of a policy are those that do - not select any 'next' state. Since a 'State' can only - accept a single type of event, the type of the event emitted - by a previous 'State' must be match the incoming event type - of the next 'State'. This is also how the last state(s) in - a policy can emit events of different types. The 'State - Output Mapping' is also responsible for taking the - fields that are output by the task executed in the state and - populating the state’s output event before it is emitted. - - .. container:: paragraph - - Each 'Task' referenced in 'State' must have a defined - 'Output Mapping' to take the output of the task, select an - 'Outgoing Event' type for the state, populate the state’s - outgoing event, and then select the next state to be - executed (if any). - - .. container:: paragraph - - There are 2 basic types of output mappings: - - .. container:: olist arabic - - #. **Direct Output Mappings** have a single value for - 'Next State' and a single value for 'State Output - Event'. The outgoing event for the state is - automatically created, any outgoing event parameters - that were present in the incoming event are copied - into the outgoing event, then any task output fields - that have the same name and type as parameters in the - outgoing event are automatically copied into - the outgoing event. - - #. **Logic-based State Output Mappings / Finalizers** - have some logic defined that dynamically selects - and creates the 'State Outgoing Event', manages - the population of the outgoing event parameters - (perhaps changing or adding to the outputs from the - task), and then dynamically selects the next state to - be executed (if any). - - .. container:: paragraph - - Each task reference must also have an associated 'Output - State Mapping' so we need an 'Output State Mapping' for - the ``BoozeAuthDecide`` state to use when the - ``MorningBoozeCheck`` task is executed. The simplest type - of output mapping is a 'Direct Output Mapping'. - - .. container:: paragraph - - Create a new 'Direct Output Mapping' for the state called - ``MorningBoozeCheck_Output_Direct`` using the 'Add New - Direct State Output Mapping' button. Select ``SALE_AUTH`` - as the output event and select ``None`` for the next - state value. We can then select this output mapping for - use when the the ``MorningBoozeCheck`` task is executed. - Since there is only state, and only one task for that - state, this output mapping ensures that the - ``BoozeAuthDecide`` state is the only state executed and - the state (and the policy) can only emit events of type - ``SALE_AUTH``. (You may remember that the output fields - for the ``MorningBoozeCheck`` task have the exact same - names and reuse the item schemas that we used for the - parameters in ``SALE_AUTH`` event. The - ``MorningBoozeCheck_Output_Direct`` direct output mapping - can now automatically copy the values from the - ``MorningBoozeCheck`` task directly into outgoing - ``SALE_AUTH`` events.) - - .. container:: imageblock - - .. container:: content - - |Add a Task and Output Mapping| - - .. container:: title - - Figure 16. Add a Task and Output Mapping - - .. container:: paragraph - - Click the 'Submit' button to complete the definition of - our ``MyFirstPolicy`` policy. The policy - ``MyFirstPolicy`` can now be seen in the list of policies - on the 'Policies' tab, and can be updated at any time by - right-clicking on the policy on the 'Policies' tab. - - .. container:: paragraph - - The ``MyFirstPolicyModel``, including our - ``MyFirstPolicy`` policy can now be checked for errors. - Click on the 'Model' menu and select 'Validate'. The - model should validate without any 'Warning' or 'Error' - messages. If you see any 'Error' or 'Warning' messages, - carefully read the message as a hint to find where you - might have made a mistake when defining some aspect of - your policy model. - - .. container:: imageblock - - .. container:: content - - |Validate the policy model for error using the 'Model' - > 'Validate' menu item| - - .. container:: title - - Figure 17. Validate a Policy Model - - .. container:: paragraph - - Congratulations, you have now completed your first APEX - policy. The policy model containing our new policy can - now be exported from the editor and saved. Click on the - 'File' menu and select 'Download' to save the policy - model in JSON format. The exported policy model is then - available in the directory you selected, for instance - ``$APEX_HOME/examples/models/MyFirstPolicy/1/MyFirstPolicyModel_0.0.1.json``. - The exported policy can now be loaded into the APEX - Policy Engine, or can be re-loaded and edited by the APEX - Policy Editor. - - .. container:: imageblock - - .. container:: content - - |Download the completed policy model using the 'File' - > 'Download' menu item| - - .. container:: title - - Figure 18. Export a Policy Model - -Test Policy Step 1 -################## - - .. container:: paragraph - - To start a new APEX Engine you can use the following - configuration. In a full APEX installation you can find - this configuration in - ``$APEX_HOME/examples/config/MyFirstPolicy/1/MyFirstPolicyConfigStdin2StdoutJsonEvent.json``. - This configuration expects incoming events to be in - ``JSON`` format and to be passed into the APEX Engine - from ``stdin``, and result events will be printed in - ``JSON`` format to ``stdout``. This configuration loads - the policy model stored in the file - 'MyFirstPolicyModel_0.0.1.json' as exported from the APEX - Editor. Note, you may need to edit this file to provide - the full path to wherever you stored the exported policy - model file. - - .. container:: listingblock - - .. container:: title - - JSON to load and execute *My First Policy*, read input - JSON events from ``stdin``, and emit output events to - ``stdout`` - - .. container:: content - - .. code:: - - { - "engineServiceParameters" : { - "name" : "MyFirstPolicyApexEngine", - "version" : "0.0.1", - "id" : 101, - "instanceCount" : 4, - "deploymentPort" : 12345, - "policyModelFileName" : "examples/models/MyFirstPolicy/1/MyFirstPolicyModel_0.0.1.json", - "engineParameters" : { - "executorParameters" : { - "MVEL" : { - "parameterClassName" : "org.onap.policy.apex.plugins.executor.mvel.MVELExecutorParameters" - }, - "JAVASCRIPT" : { - "parameterClassName" : "org.onap.policy.apex.plugins.executor.javascript.JavascriptExecutorParameters" - } - } - } - }, - "eventOutputParameters": { - "FirstProducer": { - "carrierTechnologyParameters" : { - "carrierTechnology" : "FILE", - "parameters" : { - "standardIO" : true - } - }, - "eventProtocolParameters" : { - "eventProtocol" : "JSON" - } - } - }, - "eventInputParameters": { - "FirstConsumer": { - "carrierTechnologyParameters" : { - "carrierTechnology" : "FILE", - "parameters" : { - "standardIO" : true - } - }, - "eventProtocolParameters" : { - "eventProtocol" : "JSON" - } - } - } - } - - .. container:: paragraph - - To test the policy try paste the following events into - the console as the APEX engine executes: - - .. table:: Table 11. Inputs and Outputs when testing *My First Policy* - - +------------------------------------------+-------------------------------------------+-----------+ - | Input Event (JSON) | Output Event (JSON) | comment | - +==========================================+===========================================+===========+ - | .. container:: | .. container:: | Request | - | | | to buy a | - | .. container:: listingblock | .. container:: listingblock | non-alcoh | - | | | olic | - | | .. container:: content | item | - | .. container:: content | | (``item_I | - | | .. code:: | D=5123``) | - | | | at | - | .. code:: | { | *10:13:09 | - | | "name": "SALE_AUTH", | * | - | | | on | - | { | "version": "0.0.1", | *Tuesday, | - | "nameSpace": "com.hyperm", | "nameSpace": "com.hyperm", | 10 | - | "name" : "SALE_INPUT", | "source": "", | January | - | "version": "0.0.1", | "target": "", | 2017*. | - | "time" : 1483351989000, | "amount": 299, | Sale is | - | "sale_ID": 99999991, | "assistant_ID": 23, | authorize | - | "amount": 299, | "authorised": true, | d. | - | "item_ID": 5123, | "branch_ID": 1, | | - | "quantity": 1, | "item_ID": 5123, | | - | "assistant_ID": 23, | "message": "Sale authorised | | - | "branch_ID": 1, | by policy task MorningBo | | - | "notes": "Special Offer!!" | ozeCheck for time 10:13:09 | | - | } | GMT", | | - | | "notes": "Special Offer!!", | | - | | "quantity": 1, | | - | | "sale_ID": 99999991, | | - | | "time": 1483351989000 | | - | | } | | - | | | | - | | | | - | | | | - +------------------------------------------+-------------------------------------------+-----------+ - | .. container:: | .. container:: | Request | - | | | to buy | - | .. container:: listingblock | .. container:: listingblock | alcohol | - | | | item | - | .. container:: content | .. container:: content | (``item_I | - | | | D=1249``) | - | .. code:: | .. code:: | at | - | | | *08:41:06 | - | { | { | * | - | "nameSpace": "com.hyperm", | "nameSpace": "com.hyperm", | on | - | "name": "SALE_INPUT", | "name": "SALE_AUTH", | *Monday, | - | "version": "0.0.1", | "source": "", | 02 | - | "time": 1483346466000, | "target": "", | January | - | "sale_ID": 99999992, | "amount": 1249, | 2017*. | - | "version": "0.0.1", | "assistant_ID": 12, | | - | "amount": 1249, | "authorised": false, | Sale is | - | "item_ID": 1012, | "branch_ID": 2, | not | - | "quantity": 1, | "item_ID": 1012, | authorize | - | "assistant_ID": 12, | "message": "Sale not | d. | - | "branch_ID": 2 | authorised by policy task | | - | } | MorningBoozeCheck for time | | - | | 08:41:06 GMT. Alcohol can | | - | | not be sold between | | - | | 00:00:00 GMT and 11:30:00 | | - | | GMT", | | - | | "notes": null, | | - | | "quantity": 1, | | - | | "sale_ID": 99999992, | | - | | "time": 1483346466000 | | - | | } | | - +------------------------------------------+-------------------------------------------+-----------+ - | .. container:: | .. container:: | Request | - | | | to buy | - | .. container:: listingblock | .. container:: listingblock | alcohol | - | | | (``item_I | - | | .. container:: content | D=1943``) | - | .. container:: content | | at | - | | .. code:: | *20:17:13 | - | | | * | - | .. code:: | { | on | - | | "name": "SALE_AUTH", | *Tuesday, | - | { | "version": "0.0.1", | 20 | - | "nameSpace": "com.hyperm", | "nameSpace": "com.hyperm", | December | - | "name" : "SALE_INPUT", | "source": "", | 2016*. | - | "version": "0.0.1", | "target": "", | | - | "time" : 1482265033000, | "amount": 4799, | Sale is | - | "sale_ID": 99999993, | "assistant_ID": 9, | authorize | - | "amount": 4799, | "authorised": true, | d. | - | "item_ID": 1943, | "branch_ID": 3, | | - | "quantity": 2, | "item_ID": 1943, | | - | "assistant_ID": 9, | "message": "Sale authorised | | - | "branch_ID": 3 | by policy task MorningBo | | - | } | ozeCheck for time 20:17:13 | | - | | GMT", | | - | | "notes": null, | | - | | "quantity": 2, | | - | | "sale_ID": 99999993, | | - | | "time": 1482265033000 | | - | | } | | - +------------------------------------------+-------------------------------------------+-----------+ - -4.3.6. Policy 1 in CLI Editor -############################# - - .. container:: paragraph - - An equivalent version of the ``MyFirstPolicyModel`` - policy model can again be generated using the APEX CLI - editor. A sample APEX CLI script is shown below: - - .. container:: listingblock - - .. container:: title - - APEX CLI Editor code for Policy 1 - - .. container:: content - - .. code:: - - #------------------------------------------------------------------------------- - # ============LICENSE_START======================================================= - # Copyright (C) 2016-2018 Ericsson. All rights reserved. - # ================================================================================ - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. - # - # SPDX-License-Identifier: Apache-2.0 - # ============LICENSE_END========================================================= - #------------------------------------------------------------------------------- - - model create name=MyFirstPolicyModel version=0.0.1 uuid=540226fb-55ee-4f0e-a444-983a0494818e description="This is my first Apex Policy Model." - - schema create name=assistant_ID_type version=0.0.1 uuid=36df4c71-9616-4206-8b53-976a5cd4bd87 description="A type for 'assistant_ID' values" flavour=Java schema=java.lang.Long - - schema create name=authorised_type version=0.0.1 uuid=d48b619e-d00d-4008-b884-02d76ea4350b description="A type for 'authorised' values" flavour=Java schema=java.lang.Boolean - - schema create name=branch_ID_type version=0.0.1 uuid=6468845f-4122-4128-8e49-0f52c26078b5 description="A type for 'branch_ID' values" flavour=Java schema=java.lang.Long - - schema create name=item_ID_type version=0.0.1 uuid=4f227ff1-aee0-453a-b6b6-9a4b2e0da932 description="A type for 'item_ID' values" flavour=Java schema=java.lang.Long - - schema create name=message_type version=0.0.1 uuid=ad1431bb-3155-4e73-b5a3-b89bee498749 description="A type for 'message' values" flavour=Java schema=java.lang.String - - schema create name=notes_type version=0.0.1 uuid=eecfde90-896c-4343-8f9c-2603ced94e2d description="A type for 'notes' values" flavour=Java schema=java.lang.String - - schema create name=price_type version=0.0.1 uuid=52c2fc45-fd8c-463c-bd6f-d91b0554aea7 description="A type for 'amount'/'price' values" flavour=Java schema=java.lang.Long - - schema create name=quantity_type version=0.0.1 uuid=ac3d9842-80af-4a98-951c-bd79a431c613 description="A type for 'quantity' values" flavour=Java schema=java.lang.Integer - - schema create name=sale_ID_type version=0.0.1 uuid=cca47d74-7754-4a61-b163-ca31f66b157b description="A type for 'sale_ID' values" flavour=Java schema=java.lang.Long - - schema create name=timestamp_type version=0.0.1 uuid=fd594e88-411d-4a94-b2be-697b3a0d7adf description="A type for 'time' values" flavour=Java schema=java.lang.Long - - task create name=MorningBoozeCheck version=0.0.1 uuid=3351b0f4-cf06-4fa2-8823-edf67bd30223 description=LS - This task checks if the sales request is for an item that contains alcohol. - If the local time is between 00:00:00 and 11:30:00 then the sale is not authorised. Otherwise the sale is authorised. - In this implementation we assume that all items with item_ID values between 1000 and 2000 contain alcohol :-) - LE - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=amount schemaName=price_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=quantity schemaName=quantity_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=time schemaName=timestamp_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=amount schemaName=price_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=quantity schemaName=quantity_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=authorised schemaName=authorised_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=time schemaName=timestamp_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=message schemaName=message_type schemaVersion=0.0.1 optional=true - task logic create name=MorningBoozeCheck version=0.0.1 logicFlavour=MVEL logic=LS - /* - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - import java.util.Date; - import java.util.Calendar; - import java.util.TimeZone; - import java.text.SimpleDateFormat; - - logger.info("Task Execution: '"+subject.id+"'. Input Fields: '"+inFields+"'"); - - outFields.put("amount" , inFields.get("amount")); - outFields.put("assistant_ID", inFields.get("assistant_ID")); - outFields.put("notes" , inFields.get("notes")); - outFields.put("quantity" , inFields.get("quantity")); - outFields.put("branch_ID" , inFields.get("branch_ID")); - outFields.put("item_ID" , inFields.get("item_ID")); - outFields.put("time" , inFields.get("time")); - outFields.put("sale_ID" , inFields.get("sale_ID")); - - item_id = inFields.get("item_ID"); - - //The events used later to test this task use GMT timezone! - gmt = TimeZone.getTimeZone("GMT"); - timenow = Calendar.getInstance(gmt); - df = new SimpleDateFormat("HH:mm:ss z"); - df.setTimeZone(gmt); - timenow.setTimeInMillis(inFields.get("time")); - - midnight = timenow.clone(); - midnight.set( - timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), - timenow.get(Calendar.DATE),0,0,0); - eleven30 = timenow.clone(); - eleven30.set( - timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), - timenow.get(Calendar.DATE),11,30,0); - - itemisalcohol = false; - if(item_id != null && item_id >=1000 && item_id < 2000) - itemisalcohol = true; - - if( itemisalcohol - && timenow.after(midnight) && timenow.before(eleven30)){ - outFields.put("authorised", false); - outFields.put("message", "Sale not authorised by policy task "+subject.taskName+ - " for time "+df.format(timenow.getTime())+ - ". Alcohol can not be sold between "+df.format(midnight.getTime())+ - " and "+df.format(eleven30.getTime())); - return true; - } - else{ - outFields.put("authorised", true); - outFields.put("message", "Sale authorised by policy task "+subject.taskName+ - " for time "+df.format(timenow.getTime())); - return true; - } - - /* - This task checks if a sale request is for an item that is an alcoholic drink. - If the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not - authorised. Otherwise the sale is authorised. - In this implementation we assume that items with item_ID value between 1000 and - 2000 are all alcoholic drinks :-) - */ - LE - - event create name=SALE_AUTH version=0.0.1 uuid=c4500941-3f98-4080-a9cc-5b9753ed050b description="An event emitted by the Policy to indicate whether the sale of an item has been authorised" nameSpace=com.hyperm source="APEX" target="POS" - event parameter create name=SALE_AUTH version=0.0.1 parName=amount schemaName=price_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=authorised schemaName=authorised_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=message schemaName=message_type schemaVersion=0.0.1 optional=true - event parameter create name=SALE_AUTH version=0.0.1 parName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true - event parameter create name=SALE_AUTH version=0.0.1 parName=quantity schemaName=quantity_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=time schemaName=timestamp_type schemaVersion=0.0.1 - - event create name=SALE_INPUT version=0.0.1 uuid=4f04aa98-e917-4f4a-882a-c75ba5a99374 description="An event raised by the PoS system each time an item is scanned for purchase" nameSpace=com.hyperm source="POS" target="APEX" - event parameter create name=SALE_INPUT version=0.0.1 parName=amount schemaName=price_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true - event parameter create name=SALE_INPUT version=0.0.1 parName=quantity schemaName=quantity_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=time schemaName=timestamp_type schemaVersion=0.0.1 - - - policy create name=MyFirstPolicy version=0.0.1 uuid=6c5e410f-489a-46ff-964e-982ce6e8b6d0 description="This is my first Apex policy. It checks if a sale should be authorised or not." template=FREEFORM firstState=BoozeAuthDecide - policy state create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide triggerName=SALE_INPUT triggerVersion=0.0.1 defaultTaskName=MorningBoozeCheck defaultTaskVersion=0.0.1 - policy state output create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide outputName=MorningBoozeCheck_Output_Direct eventName=SALE_AUTH eventVersion=0.0.1 nextState=NULL - policy state taskref create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide taskLocalName=MorningBoozeCheck taskName=MorningBoozeCheck taskVersion=0.0.1 outputType=DIRECT outputName=MorningBoozeCheck_Output_Direct - -Policy Step 2 -------------- - -Scenario -######### - .. container:: paragraph - - *HyperM* have just opened a new branch in a different - country, but that country has different rules about when - alcohol can be sold! In this section we will go through - the necessary steps to extend our policy to enforce this - for *HyperM*. - - .. container:: ulist - - - In some branches alcohol cannot be sold before 1pm, - and not at all on Sundays. - - .. container:: paragraph - - Although there are a number of ways to accomplish this - the easiest approach for us is to define another task and - then select which task is appropriate at runtime - depending on the branch identifier in the incoming event. - -Extend the Policy with the new Scenario -####################################### - - .. container:: paragraph - - To create a new Task click on the 'Tasks' tab. In the - 'Tasks' pane, right click and select 'Create new Task': - - .. container:: paragraph - - Create a new Task called ``MorningBoozeCheckAlt1``. Use - the 'Generate UUID' button to create a new unique ID for - the task, and fill in a description for the task. Select - the same input and output fields that we used earlier - when we defined the ``MorningBoozeCheck`` task earlier. - - .. table:: Table 12. Input fields for ``MorningBoozeCheckAlt1`` task - - +-----------------------------------+-----------------------------------+ - | Parameter Name | Parameter Type | - +===================================+===================================+ - | time | timestamp_type | - +-----------------------------------+-----------------------------------+ - | sale_ID | sale_ID_type | - +-----------------------------------+-----------------------------------+ - | amount | price_type | - +-----------------------------------+-----------------------------------+ - | item_ID | item_ID_type | - +-----------------------------------+-----------------------------------+ - | quantity | quantity_type | - +-----------------------------------+-----------------------------------+ - | assistant_ID | assistant_ID_type | - +-----------------------------------+-----------------------------------+ - | branch_ID | branch_ID_type | - +-----------------------------------+-----------------------------------+ - | notes | notes_type | - +-----------------------------------+-----------------------------------+ - - .. table:: Table 13. Output fields for ``MorningBoozeCheckAlt1`` task - - +-----------------------------------+-----------------------------------+ - | Parameter Name | Parameter Type | - +===================================+===================================+ - | sale_ID | sale_ID_type | - +-----------------------------------+-----------------------------------+ - | time | timestamp_type | - +-----------------------------------+-----------------------------------+ - | authorised | authorised_type | - +-----------------------------------+-----------------------------------+ - | message | message_type | - +-----------------------------------+-----------------------------------+ - | amount | price_type | - +-----------------------------------+-----------------------------------+ - | item_ID | item_ID_type | - +-----------------------------------+-----------------------------------+ - | assistant_ID | assistant_ID_type | - +-----------------------------------+-----------------------------------+ - | quantity | quantity_type | - +-----------------------------------+-----------------------------------+ - | branch_ID | branch_ID_type | - +-----------------------------------+-----------------------------------+ - | notes | notes_type | - +-----------------------------------+-----------------------------------+ - - .. container:: paragraph - - This task also requires some 'Task Logic' to implement - the new behaviour for this task. - - .. container:: paragraph - - For simplicity use the following code for the task logic. - It again assumes that all items with ``item_ID`` between - 1000 and 2000 contain alcohol. We again use the standard - ``Java`` time utilities to check if the current time is - between ``00:00:00 CET`` and ``13:00:00 CET`` or if it is - ``Sunday``. - - .. container:: paragraph - - For this task we will again author the logic using the - ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__ - scripting language. Sample task logic code (specified in - ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__) is - given below. For a detailed guide to how to write your - own logic in - ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__, - ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__ or one - of the other supported languages please refer to APEX - Programmers Guide. - - .. container:: listingblock - - .. container:: title - - MVEL code for the ``MorningBoozeCheckAlt1`` task - - .. container:: content - - .. code:: - - /* - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - import java.util.Date; - import java.util.Calendar; - import java.util.TimeZone; - import java.text.SimpleDateFormat; - - logger.info("Task Execution: '"+subject.id+"'. Input Event: '"+inFields+"'"); - - outFields.put("amount" , inFields.get("amount")); - outFields.put("assistant_ID", inFields.get("assistant_ID")); - outFields.put("notes" , inFields.get("notes")); - outFields.put("quantity" , inFields.get("quantity")); - outFields.put("branch_ID" , inFields.get("branch_ID")); - outFields.put("item_ID" , inFields.get("item_ID")); - outFields.put("time" , inFields.get("time")); - outFields.put("sale_ID" , inFields.get("sale_ID")); - - item_id = inFields.get("item_ID"); - - //The events used later to test this task use CET timezone! - cet = TimeZone.getTimeZone("CET"); - timenow = Calendar.getInstance(cet); - df = new SimpleDateFormat("HH:mm:ss z"); - df.setTimeZone(cet); - timenow.setTimeInMillis(inFields.get("time")); - - midnight = timenow.clone(); - midnight.set( - timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), - timenow.get(Calendar.DATE),0,0,0); - onepm = timenow.clone(); - onepm.set( - timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), - timenow.get(Calendar.DATE),13,0,0); - - itemisalcohol = false; - if(item_id != null && item_id >=1000 && item_id < 2000) - itemisalcohol = true; - - if( itemisalcohol && - ( (timenow.after(midnight) && timenow.before(onepm)) - || - (timenow.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) - )){ - outFields.put("authorised", false); - outFields.put("message", "Sale not authorised by policy task "+subject.taskName+ - " for time "+df.format(timenow.getTime())+ - ". Alcohol can not be sold between "+df.format(midnight.getTime())+ - " and "+df.format(onepm.getTime()) +" or on Sunday"); - return true; - } - else{ - outFields.put("authorised", true); - outFields.put("message", "Sale authorised by policy task "+subject.taskName+ - " for time "+df.format(timenow.getTime())); - return true; - } - - /* - This task checks if a sale request is for an item that is an alcoholic drink. - If the local time is between 00:00:00 CET and 13:00:00 CET then the sale is not authorised. - Also alcohol sales are not allowed on Sundays. Otherwise the sale is authorised. - In this implementation we assume that items with item_ID between 1000 and 2000 are all alcoholic drinks :-) - */ - - .. container:: imageblock - - .. container:: content - - |Create a new alternative task MorningBoozeCheckAlt1| - - .. container:: title - - Figure 19. Create a new Task - - .. container:: paragraph - - The task definition is now complete so click the 'Submit' - button to save the task. Now that we have created our - task, we can can add this task to the single pre-existing - state (``BoozeAuthDecide``) in our policy. - - .. container:: paragraph - - To edit the ``BoozeAuthDecide`` state in our policy click - on the 'Policies' tab. In the 'Policies' pane, right - click on our ``MyFirstPolicy`` policy and select 'Edit'. - Navigate to the ``BoozeAuthDecide`` state in the 'states' - section at the bottom of the policy definition pane. - - .. container:: imageblock - - .. container:: content - - |Right click to edit a policy| - - .. container:: title - - Figure 20. Edit a Policy - - .. container:: paragraph - - To add our new task ``MorningBoozeCheckAlt1``, scroll - down to the ``BoozeAuthDecide`` state in the 'States' - section. In the 'State Tasks' section for - ``BoozeAuthDecide`` use the 'Add new task' button. Select - our new ``MorningBoozeCheckAlt1`` task, and use the name - of the task as the 'Local Name' for the task. The - ``MorningBoozeCheckAlt1`` task can reuse the same - ``MorningBoozeCheck_Output_Direct`` 'Direct State Output - Mapping' that we used for the ``MorningBoozeCheck`` task. - (Recall that the role of the 'State Output Mapping' is to - select the output event for the state, and select the - next state to be executed. These both remain the same as - before.) - - .. container:: paragraph - - Since our state has more than one task we must define - some logic to determine which task should be used each - time the state is executed. This *task selection logic* - is defined in the state definition. For our - ``BoozeAuthDecide`` state we want the choice of which - task to use to be based on the ``branch_ID`` from which - the ``SALE_INPUT`` event originated. For simplicity sake - let us assume that branches with ``branch_ID`` between - ``0`` and ``999`` should use the ``MorningBoozeCheck`` - task, and the branches with with ``branch_ID`` between - ``1000`` and ``1999`` should use the - ``MorningBoozeCheckAlt1`` task. - - .. container:: paragraph - - This time, for variety, we will author the task selection - logic using the - ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__ - scripting language. Sample task selection logic code - (specified in - ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__) - is given below. Paste the script text into the 'Task - Selection Logic' box, and use "JAVASCRIPT" as the 'Task - Selection Logic Type / Flavour'. It is necessary to mark - one of the tasks as the 'Default Task' so that the task - selection logic always has a fallback default option in - cases where a particular task cannot be selected. In this - case the ``MorningBoozeCheck`` task can be the default - task. - - .. container:: listingblock - - .. container:: title - - JavaScript code for the ``BoozeAuthDecide`` task - selection logic - - .. container:: content - - .. code:: - - /* - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - - - var returnValueType = Java.type("java.lang.Boolean"); - var returnValue = new returnValueType(true); - - executor.logger.info("Task Selection Execution: '"+executor.subject.id+ - "'. Input Event: '"+executor.inFields+"'"); - - branchid = executor.inFields.get("branch_ID"); - taskorig = executor.subject.getTaskKey("MorningBoozeCheck"); - taskalt = executor.subject.getTaskKey("MorningBoozeCheckAlt1"); - taskdef = executor.subject.getDefaultTaskKey(); - - if(branchid >=0 && branchid <1000){ - taskorig.copyTo(executor.selectedTask); - } - else if (branchid >=1000 && branchid <2000){ - taskalt.copyTo(executor.selectedTask); - } - else{ - taskdef.copyTo(executor.selectedTask); - } - - /* - This task selection logic selects task "MorningBoozeCheck" for branches with - 0<=branch_ID<1000 and selects task "MorningBoozeCheckAlt1" for branches with - 1000<=branch_ID<2000. Otherwise the default task is selected. - In this case the default task is also "MorningBoozeCheck" - */ - - .. container:: imageblock - - .. container:: content - - |State definition with 2 Tasks and Task Selection - Logic| - - .. container:: title - - Figure 21. State definition with 2 Tasks and Task - Selection Logic - - .. container:: paragraph - - When complete don’t forget to click the 'Submit' button - at the bottom of 'Policies' pane for our - ``MyFirstPolicy`` policy after updating the - ``BoozeAuthDecide`` state. - - .. container:: paragraph - - Congratulations, you have now completed the second step - towards your first APEX policy. The policy model - containing our new policy can again be validated and - exported from the editor and saved as shown in Step 1. - - .. container:: paragraph - - The exported policy model is then available in the - directory you selected, as - `MyFirstPolicyModel_0.0.1.json <files/mfp-files/2/MyFirstPolicyModel_0.0.1.json>`__. - The exported policy can now be loaded into the APEX - Policy Engine, or can be re-loaded and edited by the APEX - Policy Editor. - -Test Policy Step 2 -################## - - .. container:: paragraph - - To start a new APEX Engine you can use the following - configuration. In a full APEX installation you can find - this configuration in - ``$APEX_HOME/examples/config/MyFirstPolicy/2/MyFirstPolicyConfigStdin2StdoutJsonEvent.json``. - Note, this has changed from the configuration file in - Step 1 to enable the ``JAVASCRIPT`` executor for our new - 'Task Selection Logic'. - - .. container:: listingblock - - .. container:: title - - JSON to load and execute *My First Policy*, read input - JSON events from ``stdin``, and emit output events to - ``stdout`` - - .. container:: content - - .. code:: - - { - "engineServiceParameters" : { - "name" : "MyFirstPolicyApexEngine", - "version" : "0.0.1", - "id" : 102, - "instanceCount" : 4, - "deploymentPort" : 12345, - "policyModelFileName" : "examples/models/MyFirstPolicy/2/MyFirstPolicyModel_0.0.1.json", - "engineParameters" : { - "executorParameters" : { - "MVEL" : { - "parameterClassName" : "org.onap.policy.apex.plugins.executor.mvel.MVELExecutorParameters" - }, - "JAVASCRIPT" : { - "parameterClassName" : "org.onap.policy.apex.plugins.executor.javascript.JavascriptExecutorParameters" - } - } - } - }, - "eventOutputParameters": { - "FirstProducer": { - "carrierTechnologyParameters" : { - "carrierTechnology" : "FILE", - "parameters" : { - "standardIO" : true - } - }, - "eventProtocolParameters" : { - "eventProtocol" : "JSON" - } - } - }, - "eventInputParameters": { - "FirstConsumer": { - "carrierTechnologyParameters" : { - "carrierTechnology" : "FILE", - "parameters" : { - "standardIO" : true - } - }, - "eventProtocolParameters" : { - "eventProtocol" : "JSON" - } - } - } - } - - .. container:: paragraph - - To test the policy try paste the following events into - the console as the APEX engine executes. Note, all tests - from Step 1 will still work perfectly since none of those - events originate from a branch with ``branch_ID`` between - ``1000`` and ``2000``. The 'Task Selection Logic' will - therefore pick the ``MorningBoozeCheck`` task as - expected, and will therefore give the same results. - - .. table:: Table 14. Inputs and Outputs when testing *My First Policy* - - +----------------------------------------------+------------------------------------------------------------+---------------------------+ - | Input Event (JSON) | Output Event (JSON) | comment | - +==============================================+============================================================+===========================+ - | .. container:: | .. container:: | Request to buy | - | | | alcohol item | - | .. container:: listingblock | .. container:: listingblock | (``item_ID=1249``) | - | | | | - | | | at *08:41:06 | - | | .. container:: content | GMT* on *Monday, | - | .. container:: content | | 02 January | - | | .. code:: | 2017*. | - | | | | - | | { | Sale is not | - | .. code:: | "nameSpace": "com.hyperm", | authorized. Uses | - | | "name": "SALE_AUTH", | the | - | | "version": "0.0.1", | ``MorningBoozeCheck`` | - | { | "source": "", | | - | "nameSpace": "com.hyperm", | "target": "", | task. | - | "name": "SALE_INPUT", | "amount": 1249, | | - | "version": "0.0.1", | "assistant_ID":12, | Note this test | - | "time": 1483346466000, | "authorised": false, | is copied from | - | "sale_ID": 99999992, | "branch_ID": 2, | Step 1 above, | - | "amount": 1249, | "item_ID": 1012, | and demonstrates | - | "item_ID": 1012, | "message": "Sale not authorised by policy ta | that the | - | "quantity": 1, | sk MorningBoozeCheck for time 08:41:06 GMT.| original | - | "assistant_ID": 12, | Alcohol can not be sold between 00:00:00 | ``MorningBoozeCheck`` | - | "branch_ID": 2 | GMT and 11:30:00 GMT", | | - | } | "notes": null, | task is | - | | "quantity": 1, | executed. | - | | "sale_ID": 99999992, | | - | | "time": 1483346466000 | | - | | } | | - +----------------------------------------------+------------------------------------------------------------+---------------------------+ - | .. container:: | .. container:: | Request to buy | - | | | alcohol | - | .. container:: listingblock | .. container:: listingblock | (``item_ID=1047``) | - | | | | - | | | at *10:14:33* on | - | | .. container:: content | *Thursday, 22 | - | .. container:: content | | December 2016*. | - | | .. code:: | | - | | | Sale is not | - | | { | authorized. Uses | - | .. code:: | "nameSpace" : "com.hyperm", | the | - | | "name" : "SALE_AUTH", | ``MorningBoozeCheckAlt1`` | - | | "version" : "0.0.1", | task. | - | { | "source" : "", | | - | | "target" : "", | | - | "nameSpace": "com.hyperm", | "sale_ID" : 99999981, | | - | "name": "SALE_INPUT", | "amount" : 299, | | - | "version": "0.0.1", | "assistant_ID": 1212, | | - | "time": 1482398073000, | "notes" : null, | | - | "sale_ID": 99999981, | "quantity" : 1, | | - | "amount": 299, | "branch_ID" : 1002, | | - | "item_ID": 1047, | "item_ID" : 1047, | | - | "quantity": 1, | "authorised" : false, | | - | "assistant_ID": 1212, | "time" : 1482398073000, | | - | "branch_ID": 1002 | "message" : "Sale not authorised by policy t | | - | } | ask MorningBoozeCheckAlt1 fortime | | - | | 10:14:33 CET. Alcohol can not be sold | | - | | between 00:00:00 CET and 13:00:00 CET or on | | - | | Sunday" | | - | | } | | - +----------------------------------------------+------------------------------------------------------------+---------------------------+ - | .. container:: | .. container:: | Request to buy | - | | | alcohol | - | .. container:: listingblock | .. container:: listingblock | (``item_ID=1443``) | - | | | | - | | | at *17:19:37* on | - | | .. container:: content | *Sunday, 18 | - | .. container:: content | | December 2016*. | - | | .. code:: | | - | | | Sale is not | - | | { | authorized. Uses | - | .. code:: | "nameSpace" : "com.hyperm", | the | - | | | ``MorningBoozeCheckAlt1`` | - | | "name" : "SALE_AUTH", | task. | - | { | | | - | "nameSpace": "com.hyperm", | "version" : "0.0.1", | | - | "name": "SALE_INPUT", | "source" : "", | | - | "version": "0.0.1", | "target" : "", | | - | "time": 1482077977000, | "sale_ID" : 99999982, | | - | "sale_ID": 99999982, | "amount" : 2199, | | - | "amount": 2199, | "assistant_ID" : 94, | | - | "item_ID": 1443, | "notes" : "Buy 3, get 1 free!!", | | - | "quantity": 12, | "quantity" : 12, | | - | "assistant_ID": 94, | "branch_ID" : 1003, | | - | "branch_ID": 1003, | "item_ID" : 1443, | | - | "notes": "Buy 3, get 1 free!!" | "authorised" : false, | | - | } | "time" : 1482077977000, | | - | | "message" : "Sale not authorised by policy t | | - | | ask MorningBoozeCheckAlt1 for | | - | | time 17:19:37 CET. Alcohol c | | - | | an not be sold between 00:00: | | - | | 00 CET and 13:00:00 CET or on | | - | | Sunday" | | - +----------------------------------------------+------------------------------------------------------------+---------------------------+ - | .. container:: | .. container:: | Request to buy | - | | | non-alcoholic | - | .. container:: listingblock | .. container:: listingblock | item | - | | | (``item_ID=5321``) | - | | | | - | | .. container:: content | at *11:13:09* on | - | .. container:: content | | *Monday, 2 | - | | .. code:: | January 2017*. | - | | | | - | | { | Sale is | - | .. code:: | "nameSpace" : "com.hyperm", | authorized. Uses | - | | "name" : "SALE_AUTH", | the | - | { | "version" : "0.0.1", | ``MorningBoozeCheckAlt1`` | - | "nameSpace": "com.hyperm", | "source" : "", | task. | - | "name": "SALE_INPUT", | "target" : "", | | - | "version": "0.0.1", | "sale_ID" : 99999983, | | - | "time": 1483351989000, | "amount" : 699, | | - | "sale_ID": 99999983, | "assistant_ID" : 2323, | | - | "amount": 699, | "notes" : "", | | - | "item_ID": 5321, | "quantity" : 1, | | - | "quantity": 1, | "branch_ID" : 1001, | | - | "assistant_ID": 2323, | "item_ID" : 5321, | | - | "branch_ID": 1001, | "authorised" : true, | | - | "notes": "" | "time" : 1483351989000, | | - | } | "message" : "Sale authorised by policy task | | - | | MorningBoozeCheckAlt1 for time 11:13:09 CET"| | - | | } | | - +----------------------------------------------+------------------------------------------------------------+---------------------------+ - -Policy 2 in CLI Editor -###################### - - .. container:: paragraph - - An equivalent version of the ``MyFirstPolicyModel`` - policy model can again be generated using the APEX CLI - editor. A sample APEX CLI script is shown below: - - .. container:: listingblock - - .. container:: title - - APEX CLI Editor code for Policy 2 - - .. container:: content - - .. code:: - - #------------------------------------------------------------------------------- - # ============LICENSE_START======================================================= - # Copyright (C) 2016-2018 Ericsson. All rights reserved. - # ================================================================================ - # Licensed under the Apache License, Version 2.0 (the "License"); - # you may not use this file except in compliance with the License. - # You may obtain a copy of the License at - # - # http://www.apache.org/licenses/LICENSE-2.0 - # - # Unless required by applicable law or agreed to in writing, software - # distributed under the License is distributed on an "AS IS" BASIS, - # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - # See the License for the specific language governing permissions and - # limitations under the License. - # - # SPDX-License-Identifier: Apache-2.0 - # ============LICENSE_END========================================================= - #------------------------------------------------------------------------------- - - model create name=MyFirstPolicyModel version=0.0.1 uuid=540226fb-55ee-4f0e-a444-983a0494818e description="This is my first Apex Policy Model." - - schema create name=assistant_ID_type version=0.0.1 uuid=36df4c71-9616-4206-8b53-976a5cd4bd87 description="A type for 'assistant_ID' values" flavour=Java schema=java.lang.Long - - schema create name=authorised_type version=0.0.1 uuid=d48b619e-d00d-4008-b884-02d76ea4350b description="A type for 'authorised' values" flavour=Java schema=java.lang.Boolean - - schema create name=branch_ID_type version=0.0.1 uuid=6468845f-4122-4128-8e49-0f52c26078b5 description="A type for 'branch_ID' values" flavour=Java schema=java.lang.Long - - schema create name=item_ID_type version=0.0.1 uuid=4f227ff1-aee0-453a-b6b6-9a4b2e0da932 description="A type for 'item_ID' values" flavour=Java schema=java.lang.Long - - schema create name=message_type version=0.0.1 uuid=ad1431bb-3155-4e73-b5a3-b89bee498749 description="A type for 'message' values" flavour=Java schema=java.lang.String - - schema create name=notes_type version=0.0.1 uuid=eecfde90-896c-4343-8f9c-2603ced94e2d description="A type for 'notes' values" flavour=Java schema=java.lang.String - - schema create name=price_type version=0.0.1 uuid=52c2fc45-fd8c-463c-bd6f-d91b0554aea7 description="A type for 'amount'/'price' values" flavour=Java schema=java.lang.Long - - schema create name=quantity_type version=0.0.1 uuid=ac3d9842-80af-4a98-951c-bd79a431c613 description="A type for 'quantity' values" flavour=Java schema=java.lang.Integer - - schema create name=sale_ID_type version=0.0.1 uuid=cca47d74-7754-4a61-b163-ca31f66b157b description="A type for 'sale_ID' values" flavour=Java schema=java.lang.Long - - schema create name=timestamp_type version=0.0.1 uuid=fd594e88-411d-4a94-b2be-697b3a0d7adf description="A type for 'time' values" flavour=Java schema=java.lang.Long - - task create name=MorningBoozeCheck version=0.0.1 uuid=3351b0f4-cf06-4fa2-8823-edf67bd30223 description=LS - This task checks if the sales request is for an item that contains alcohol. - If the local time is between 00:00:00 and 11:30:00 then the sale is not authorised. Otherwise the sale is authorised. - In this implementation we assume that all items with item_ID values between 1000 and 2000 contain alcohol :-) - LE - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=amount schemaName=price_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=quantity schemaName=quantity_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheck version=0.0.1 fieldName=time schemaName=timestamp_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=amount schemaName=price_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=quantity schemaName=quantity_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=authorised schemaName=authorised_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=time schemaName=timestamp_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheck version=0.0.1 fieldName=message schemaName=message_type schemaVersion=0.0.1 optional=true - task logic create name=MorningBoozeCheck version=0.0.1 logicFlavour=MVEL logic=LS - /* - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - import java.util.Date; - import java.util.Calendar; - import java.util.TimeZone; - import java.text.SimpleDateFormat; - - logger.info("Task Execution: '"+subject.id+"'. Input Fields: '"+inFields+"'"); - - outFields.put("amount" , inFields.get("amount")); - outFields.put("assistant_ID", inFields.get("assistant_ID")); - outFields.put("notes" , inFields.get("notes")); - outFields.put("quantity" , inFields.get("quantity")); - outFields.put("branch_ID" , inFields.get("branch_ID")); - outFields.put("item_ID" , inFields.get("item_ID")); - outFields.put("time" , inFields.get("time")); - outFields.put("sale_ID" , inFields.get("sale_ID")); - - item_id = inFields.get("item_ID"); - - //The events used later to test this task use GMT timezone! - gmt = TimeZone.getTimeZone("GMT"); - timenow = Calendar.getInstance(gmt); - df = new SimpleDateFormat("HH:mm:ss z"); - df.setTimeZone(gmt); - timenow.setTimeInMillis(inFields.get("time")); - - midnight = timenow.clone(); - midnight.set( - timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), - timenow.get(Calendar.DATE),0,0,0); - eleven30 = timenow.clone(); - eleven30.set( - timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), - timenow.get(Calendar.DATE),11,30,0); - - itemisalcohol = false; - if(item_id != null && item_id >=1000 && item_id < 2000) - itemisalcohol = true; - - if( itemisalcohol - && timenow.after(midnight) && timenow.before(eleven30)){ - outFields.put("authorised", false); - outFields.put("message", "Sale not authorised by policy task "+subject.taskName+ - " for time "+df.format(timenow.getTime())+ - ". Alcohol can not be sold between "+df.format(midnight.getTime())+ - " and "+df.format(eleven30.getTime())); - return true; - } - else{ - outFields.put("authorised", true); - outFields.put("message", "Sale authorised by policy task "+subject.taskName+ - " for time "+df.format(timenow.getTime())); - return true; - } - - /* - This task checks if a sale request is for an item that is an alcoholic drink. - If the local time is between 00:00:00 GMT and 11:30:00 GMT then the sale is not - authorised. Otherwise the sale is authorised. - In this implementation we assume that items with item_ID value between 1000 and - 2000 are all alcoholic drinks :-) - */ - LE - - task create name=MorningBoozeCheckAlt1 version=0.0.1 uuid=bc6d90c9-c902-4686-afd3-925b30e39990 description=LS - This task checks if a sale request is for an item that is an alcoholic drink. - If the local time is between 00:00:00 CET and 13:00:00 CET then the sale is not authorised. - Also alcohol sales are not allowed on Sundays. Otherwise the sale is authorised. - In this implementation we assume that items with item_ID between 1000 and 2000 are all alcoholic drinks - LE - task inputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=amount schemaName=price_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true - task inputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=quantity schemaName=quantity_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 - task inputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=time schemaName=timestamp_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=amount schemaName=price_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true - task outputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=quantity schemaName=quantity_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=authorised schemaName=authorised_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=time schemaName=timestamp_type schemaVersion=0.0.1 - task outputfield create name=MorningBoozeCheckAlt1 version=0.0.1 fieldName=message schemaName=message_type schemaVersion=0.0.1 optional=true - task logic create name=MorningBoozeCheckAlt1 version=0.0.1 logicFlavour=MVEL logic=LS - /* - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - import java.util.Date; - import java.util.Calendar; - import java.util.TimeZone; - import java.text.SimpleDateFormat; - - logger.info("Task Execution: '"+subject.id+"'. Input Event: '"+inFields+"'"); - - outFields.put("amount" , inFields.get("amount")); - outFields.put("assistant_ID", inFields.get("assistant_ID")); - outFields.put("notes" , inFields.get("notes")); - outFields.put("quantity" , inFields.get("quantity")); - outFields.put("branch_ID" , inFields.get("branch_ID")); - outFields.put("item_ID" , inFields.get("item_ID")); - outFields.put("time" , inFields.get("time")); - outFields.put("sale_ID" , inFields.get("sale_ID")); - - item_id = inFields.get("item_ID"); - - //The events used later to test this task use CET timezone! - cet = TimeZone.getTimeZone("CET"); - timenow = Calendar.getInstance(cet); - df = new SimpleDateFormat("HH:mm:ss z"); - df.setTimeZone(cet); - timenow.setTimeInMillis(inFields.get("time")); - - midnight = timenow.clone(); - midnight.set( - timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), - timenow.get(Calendar.DATE),0,0,0); - onepm = timenow.clone(); - onepm.set( - timenow.get(Calendar.YEAR),timenow.get(Calendar.MONTH), - timenow.get(Calendar.DATE),13,0,0); - - itemisalcohol = false; - if(item_id != null && item_id >=1000 && item_id < 2000) - itemisalcohol = true; - - if( itemisalcohol && - ( (timenow.after(midnight) && timenow.before(onepm)) - || - (timenow.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) - )){ - outFields.put("authorised", false); - outFields.put("message", "Sale not authorised by policy task "+subject.taskName+ - " for time "+df.format(timenow.getTime())+ - ". Alcohol can not be sold between "+df.format(midnight.getTime())+ - " and "+df.format(onepm.getTime()) +" or on Sunday"); - return true; - } - else{ - outFields.put("authorised", true); - outFields.put("message", "Sale authorised by policy task "+subject.taskName+ - " for time "+df.format(timenow.getTime())); - return true; - } - - /* - This task checks if a sale request is for an item that is an alcoholic drink. - If the local time is between 00:00:00 CET and 13:00:00 CET then the sale is not authorised. - Also alcohol sales are not allowed on Sundays. Otherwise the sale is authorised. - In this implementation we assume that items with item_ID between 1000 and 2000 are all alcoholic drinks :-) - */ - LE - - event create name=SALE_AUTH version=0.0.1 uuid=c4500941-3f98-4080-a9cc-5b9753ed050b description="An event emitted by the Policy to indicate whether the sale of an item has been authorised" nameSpace=com.hyperm source="APEX" target="POS" - event parameter create name=SALE_AUTH version=0.0.1 parName=amount schemaName=price_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=authorised schemaName=authorised_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=message schemaName=message_type schemaVersion=0.0.1 optional=true - event parameter create name=SALE_AUTH version=0.0.1 parName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true - event parameter create name=SALE_AUTH version=0.0.1 parName=quantity schemaName=quantity_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_AUTH version=0.0.1 parName=time schemaName=timestamp_type schemaVersion=0.0.1 - - event create name=SALE_INPUT version=0.0.1 uuid=4f04aa98-e917-4f4a-882a-c75ba5a99374 description="An event raised by the PoS system each time an item is scanned for purchase" nameSpace=com.hyperm source="POS" target="APEX" - event parameter create name=SALE_INPUT version=0.0.1 parName=amount schemaName=price_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=assistant_ID schemaName=assistant_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=branch_ID schemaName=branch_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=item_ID schemaName=item_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=notes schemaName=notes_type schemaVersion=0.0.1 optional=true - event parameter create name=SALE_INPUT version=0.0.1 parName=quantity schemaName=quantity_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=sale_ID schemaName=sale_ID_type schemaVersion=0.0.1 - event parameter create name=SALE_INPUT version=0.0.1 parName=time schemaName=timestamp_type schemaVersion=0.0.1 - - - policy create name=MyFirstPolicy version=0.0.1 uuid=6c5e410f-489a-46ff-964e-982ce6e8b6d0 description="This is my first Apex policy. It checks if a sale should be authorised or not." template=FREEFORM firstState=BoozeAuthDecide - policy state create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide triggerName=SALE_INPUT triggerVersion=0.0.1 defaultTaskName=MorningBoozeCheck defaultTaskVersion=0.0.1 - policy state output create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide outputName=MorningBoozeCheck_Output_Direct eventName=SALE_AUTH eventVersion=0.0.1 nextState=NULL - policy state taskref create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide taskLocalName=MorningBoozeCheckAlt1 taskName=MorningBoozeCheckAlt1 taskVersion=0.0.1 outputType=DIRECT outputName=MorningBoozeCheck_Output_Direct - policy state taskref create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide taskLocalName=MorningBoozeCheck taskName=MorningBoozeCheck taskVersion=0.0.1 outputType=DIRECT outputName=MorningBoozeCheck_Output_Direct - policy state selecttasklogic create name=MyFirstPolicy version=0.0.1 stateName=BoozeAuthDecide logicFlavour=JAVASCRIPT logic=LS - /* - * ============LICENSE_START======================================================= - * Copyright (C) 2016-2018 Ericsson. All rights reserved. - * ================================================================================ - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * SPDX-License-Identifier: Apache-2.0 - * ============LICENSE_END========================================================= - */ - - var returnValueType = Java.type("java.lang.Boolean"); - var returnValue = new returnValueType(true); - - executor.logger.info("Task Selection Execution: '"+executor.subject.id+"'. Input Event: '"+executor.inFields+"'"); - - branchid = executor.inFields.get("branch_ID"); - taskorig = executor.subject.getTaskKey("MorningBoozeCheck"); - taskalt = executor.subject.getTaskKey("MorningBoozeCheckAlt1"); - taskdef = executor.subject.getDefaultTaskKey(); - - if(branchid >=0 && branchid <1000){ - taskorig.copyTo(executor.selectedTask); - } - else if (branchid >=1000 && branchid <2000){ - taskalt.copyTo(executor.selectedTask); - } - else{ - taskdef.copyTo(executor.selectedTask); - } - - /* - This task selection logic selects task "MorningBoozeCheck" for branches with 0<=branch_ID<1000 and selects task "MorningBoozeCheckAlt1" for branches with 1000<=branch_ID<2000. Otherwise the default task is selected. In this case the default task is also "MorningBoozeCheck" - */ - LE - -APEX Logging -^^^^^^^^^^^^ - -Introduction to APEX Logging ----------------------------- - - .. container:: paragraph - - All APEX components make extensive use of logging using the - logging façade `SLF4J <https://www.slf4j.org/>`__ with the - backend `Logback <https://logback.qos.ch/>`__. Both are used - off-the-shelve, so the standard documentation and - configuration apply to APEX logging. For details on how to - work with logback please see the `logback - manual <https://logback.qos.ch/manual/index.html>`__. - - .. container:: paragraph - - The APEX applications is the logback configuration file - ``$APEX_HOME/etc/logback.xml`` (Windows: - ``%APEX_HOME%\etc\logback.xml``). The logging backend is set - to no debug, i.e. logs from the logging framework should be - hidden at runtime. - - .. container:: paragraph - - The configurable log levels work as expected: - - .. container:: ulist - - - *error* (or *ERROR*) is used for serious errors in the - APEX runtime engine - - - *warn* (or *WARN*) is used for warnings, which in general - can be ignored but might indicate some deeper problems - - - *info* (or *INFO*) is used to provide generally - interesting messages for startup and policy execution - - - *debug* (or *DEBUG*) provides more details on startup and - policy execution - - - *trace* (or *TRACE*) gives full details on every aspect - of the APEX engine from start to end - - .. container:: paragraph - - The loggers can also be configured as expected. The standard - configuration (after installing APEX) uses log level *info* - on all APEX classes (components). - - .. container:: paragraph - - The applications and scripts in ``$APEX_HOME/bin`` (Windows: - ``%APEX_HOME\bin``) are configured to use the logback - configuration ``$APEX_HOME/etc/logback.xml`` (Windows: - ``%APEX_HOME\etc\logback.xml``). There are multiple ways to - use different logback configurations, for instance: - - .. container:: ulist - - - Maintain multiple configurations in ``etc``, for instance - a ``logback-debug.xml`` for deep debugging and a - ``logback-production.xml`` for APEX in production mode, - then copy the required configuration file to the used - ``logback.xml`` prior starting APEX - - - Edit the scripts in ``bin`` to use a different logback - configuration file (only recommended if you are familiar - with editing bash scripts or windows batch files) - -Standard Logging Configuration ------------------------------- - - .. container:: paragraph - - The standard logging configuration defines a context *APEX*, - which is used in the standard output pattern. The location - for log files is defined in the property ``VAR_LOG`` and set - to ``/var/log/onap/policy/apex-pdp``. The standard status - listener is set to *NOP* and the overall logback - configuration is set to no debug. - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - <configuration debug="false"> - <statusListener class="ch.qos.logback.core.status.NopStatusListener" /> - - <contextName>Apex</contextName> - <property name="VAR_LOG" value="/var/log/onap/policy/apex-pdp/" /> - - ...appenders - ...loggers - </configuration> - -.. container:: paragraph - - The first appender defined is called ``STDOUT`` for logs to standard - out. - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> - <encoder> - <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern> - </encoder> - </appender> - -.. container:: paragraph - - The root level logger then is set to the level *info* using the - standard out appender. - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - <root level="info"> - <appender-ref ref="STDOUT" /> - </root> - -.. container:: paragraph - - The second appender is called ``FILE``. It writes logs to a file - ``apex.log``. - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - <appender name="FILE" class="ch.qos.logback.core.FileAppender"> - <file>${VAR_LOG}/apex.log</file> - <encoder> - <pattern>%d %-5relative [procId=${processId}] [%thread] %-5level %logger{26} - %msg %n %ex{full}</pattern> - </encoder> - </appender> - -.. container:: paragraph - - The third appender is called ``CTXT_FILE``. It writes logs to a file - ``apex_ctxt.log``. - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - <appender name="CTXT_FILE" class="ch.qos.logback.core.FileAppender"> - <file>${VAR_LOG}/apex_ctxt.log</file> - <encoder> - <pattern>%d %-5relative [procId=${processId}] [%thread] %-5level %logger{26} - %msg %n %ex{full}</pattern> - </encoder> - </appender> - -.. container:: paragraph - - The last definitions are for specific loggers. The first logger - captures all standard APEX classes. It is configured for log level - *info* and uses the standard output and file appenders. The second - logger captures APEX context classes responsible for context - monitoring. It is configured for log level *trace* and uses the - context file appender. - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - - <logger name="org.onap.policy.apex" level="info" additivity="false"> - <appender-ref ref="STDOUT" /> - <appender-ref ref="FILE" /> - </logger> - - <logger name="org.onap.policy.apex.core.context.monitoring" level="TRACE" additivity="false"> - <appender-ref ref="CTXT_FILE" /> - </logger> - -Adding Logback Status and Debug -------------------------------- - - .. container:: paragraph - - To activate logback status messages change the status listener - from 'NOP' to for instance console. - - .. container:: listingblock - - .. container:: content - - .. code:: - - <statusListener class="ch.qos.logback.core.status.OnConsoleStatusListener" /> - - .. container:: paragraph - - To activate all logback debugging, for instance to debug a new - logback configuration, activate the debug attribute in the - configuration. - - .. container:: listingblock - - .. container:: content - - .. code:: - - <configuration debug="true"> - ... - </configuration> - -Logging External Components ---------------------------- - - .. container:: paragraph - - Logback can also be configured to log any other, external - components APEX is using, if they are using the common logging - framework. - - .. container:: paragraph - - For instance, the context component of APEX is using *Infinispan* - and one can add a logger for this external component. The - following example adds a logger for *Infinispan* using the - standard output appender. - - .. container:: listingblock - - .. container:: content - - .. code:: - - <logger name="org.infinispan" level="INFO" additivity="false"> - <appender-ref ref="STDOUT" /> - </logger> - - .. container:: paragraph - - Another example is Apache Zookeeper. The following example adds a - logger for Zookeeper using the standard outout appender. - - .. container:: listingblock - - .. container:: content - - .. code:: - - <logger name="org.apache.zookeeper.ClientCnxn" level="INFO" additivity="false"> - <appender-ref ref="STDOUT" /> - </logger> - -Configuring loggers for Policy Logic ------------------------------------- - - .. container:: paragraph - - The logging for the logic inside a policy (task logic, task - selection logic, state finalizer logic) can be configured separate - from standard logging. The logger for policy logic is - ``org.onap.policy.apex.executionlogging``. The following example - defines - - .. container:: ulist - - - a new appender for standard out using a very simple pattern - (simply the actual message) - - - a logger for policy logic to standard out using the new - appender and the already described file appender. - - .. container:: listingblock - - .. container:: content - - .. code:: - - <appender name="POLICY_APPENDER_STDOUT" class="ch.qos.logback.core.ConsoleAppender"> - <encoder> - <pattern>policy: %msg\n</pattern> - </encoder> - </appender> - - <logger name="org.onap.policy.apex.executionlogging" level="info" additivity="false"> - <appender-ref ref="POLICY_APPENDER_STDOUT" /> - <appender-ref ref="FILE" /> - </logger> - - .. container:: paragraph - - It is also possible to use specific logging for parts of policy - logic. The following example defines a logger for task logic. - - .. container:: listingblock - - .. container:: content - - .. code:: - - <logger name="org.onap.policy.apex.executionlogging.TaskExecutionLogging" level="TRACE" additivity="false"> - <appender-ref ref="POLICY_APPENDER_STDOUT" /> - </logger> - -Rolling File Appenders ----------------------- - - .. container:: paragraph - - Rolling file appenders are a good option for more complex logging - of a production or complex testing APEX installation. The standard - logback configuration can be used for these use cases. This - section gives two examples for the standard logging and for - context logging. - - .. container:: paragraph - - First the standard logging. The following example defines a - rolling file appender. The appender rolls over on a daily basis. - It allows for a file size of 100 MB. - - .. container:: listingblock - - .. container:: content - - .. code:: - - <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender"> - <file>${VAR_LOG}/apex.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <!-- rollover daily --> - <!-- <fileNamePattern>xstream-%d{yyyy-MM-dd}.%i.txt</fileNamePattern> --> - <fileNamePattern>${VAR_LOG}/apex_%d{yyyy-MM-dd}.%i.log.gz - </fileNamePattern> - <maxHistory>4</maxHistory> - <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> - <!-- or whenever the file size reaches 100MB --> - <maxFileSize>100MB</maxFileSize> - </timeBasedFileNamingAndTriggeringPolicy> - </rollingPolicy> - <encoder> - <pattern> - %d %-5relative [procId=${processId}] [%thread] %-5level %logger{26} - %msg %ex{full} %n - </pattern> - </encoder> - </appender> - - .. container:: paragraph - - A very similar configuration can be used for a rolling file - appender logging APEX context. - - .. container:: listingblock - - .. container:: content - - .. code:: - - <appender name="CTXT-FILE" - class="ch.qos.logback.core.rolling.RollingFileAppender"> - <file>${VAR_LOG}/apex_ctxt.log</file> - <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy"> - <fileNamePattern>${VAR_LOG}/apex_ctxt_%d{yyyy-MM-dd}.%i.log.gz - </fileNamePattern> - <maxHistory>4</maxHistory> - <timeBasedFileNamingAndTriggeringPolicy - class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP"> - <maxFileSize>100MB</maxFileSize> - </timeBasedFileNamingAndTriggeringPolicy> - </rollingPolicy> - <encoder> - <pattern> - %d %-5relative [procId=${processId}] [%thread] %-5level %logger{26} - %msg %ex{full} %n - </pattern> - </encoder> - </appender> - -Example Configuration for Logging Logic ---------------------------------------- - - .. container:: paragraph - - The following example shows a configuration that logs policy logic - to standard out and a file (*info*). All other APEX components are - logging to a file (*debug*).. This configuration an be used in a - pre-production phase with the APEX engine still running in a - separate terminal to monitor policy execution. This logback - configuration is in the APEX installation as - ``etc/logback-logic.xml``. - - .. container:: listingblock - - .. container:: content - - .. code:: - - <configuration debug="false"> - <statusListener class="ch.qos.logback.core.status.NopStatusListener" /> - - <contextName>Apex</contextName> - <property name="VAR_LOG" value="/var/log/onap/policy/apex-pdp/" /> - - <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender"> - <encoder> - <Pattern>%d %contextName [%t] %level %logger{36} - %msg%n</Pattern> - </encoder> - </appender> - - <appender name="FILE" class="ch.qos.logback.core.FileAppender"> - <file>${VAR_LOG}/apex.log</file> - <encoder> - <pattern> - %d %-5relative [procId=${processId}] [%thread] %-5level%logger{26} - %msg %n %ex{full} - </pattern> - </encoder> - </appender> - - <appender name="POLICY_APPENDER_STDOUT" class="ch.qos.logback.core.ConsoleAppender"> - <encoder> - <pattern>policy: %msg\n</pattern> - </encoder> - </appender> - - <root level="error"> - <appender-ref ref="STDOUT" /> - </root> - - <logger name="org.onap.policy.apex" level="debug" additivity="false"> - <appender-ref ref="FILE" /> - </logger> - - <logger name="org.onap.policy.apex.executionlogging" level="info" additivity="false"> - <appender-ref ref="POLICY_APPENDER_STDOUT" /> - <appender-ref ref="FILE" /> - </logger> - </configuration> - -Example Configuration for a Production Server ---------------------------------------------- - - .. container:: paragraph - - The following example shows a configuration that logs all APEX - components, including policy logic, to a file (*debug*). This - configuration an be used in a production phase with the APEX - engine being executed as a service on a system without console - output. This logback configuration is in the APEX installation as - ``logback-server.xml`` - - .. container:: listingblock - - .. container:: content - - .. code:: - - <configuration debug="false"> - <statusListener class="ch.qos.logback.core.status.NopStatusListener" /> - - <contextName>Apex</contextName> - <property name="VAR_LOG" value="/var/log/onap/policy/apex-pdp/" /> - - <appender name="FILE" class="ch.qos.logback.core.FileAppender"> - <file>${VAR_LOG}/apex.log</file> - <encoder> - <pattern> - %d %-5relative [procId=${processId}] [%thread] %-5level%logger{26} - %msg %n %ex{full} - </pattern> - </encoder> - </appender> - - <root level="debug"> - <appender-ref ref="FILE" /> - </root> - - <logger name="org.onap.policy.apex.executionlogging" level="debug" additivity="false"> - <appender-ref ref="FILE" /> - </logger> - </configuration> - -Building a System with Websocket Backend -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -Websockets ----------- - - .. container:: paragraph - - Websocket is a protocol to run sockets of HTTP. Since it in - essence a socket, the connection is realized between a - server (waiting for connections) and a client (connecting to - a server). Server/client separation is only important for - connection establishment, once connected, everyone can - send/receive on the same socket (as any standard socket - would allow). - - .. container:: paragraph - - Standard Websocket implementations are simple, no - publish/subscribe and no special event handling. Most - servers simply send all incoming messages to all - connections. There is a PubSub definition on top of - Websocket called `WAMP <http://wamp-proto.org/>`__. APEX - does not support WAMP at the moment. - -Websocket in Java ------------------ - - .. container:: paragraph - - In Java, `JSR - 356 <http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html>`__ - defines the standard Websocket API. This JSR is part of Jave - EE 7 standard. For Java SE, several implementations exist in - open source. Since Websockets are a stable standard and - simple, most implementations are stable and ready to use. A - lot of products support Websockets, like Spring, JBoss, - Netty, … there are also Kafka extensions for Websockets. - -Websocket Example Code for Websocket clients (FOSS) ---------------------------------------------------- - - .. container:: paragraph - - There are a lot of implementations and examples available on - Github for Websocket clients. If one is using Java EE 7, - then one can also use the native Websocket implementation. - Good examples for clients using simply Java SE are here: - - .. container:: ulist - - - `Websocket - implementation <https://github.com/TooTallNate/Java-WebSocket>`__ - - - `Websocket sending client example, using - AWT <https://github.com/TooTallNate/Java-WebSocket/blob/master/src/main/example/ChatClient.java>`__ - - - `Websocket receiving client example (simple echo - client) <https://github.com/TooTallNate/Java-WebSocket/blob/master/src/main/example/ExampleClient.java>`__ - - .. container:: paragraph - - For Java EE, the native Websocket API is explained here: - - .. container:: ulist - - - `Oracle - docs <http://www.oracle.com/technetwork/articles/java/jsr356-1937161.html>`__ - - - link: `An - example <http://www.programmingforliving.com/2013/08/jsr-356-java-api-for-websocket-client-api.html>`__ - -BCP: Websocket Configuration ----------------------------- - - .. container:: paragraph - - The probably best is to configure APEX for Websocket servers - for input (ingress, consume) and output (egress, produce) - interfaces. This means that APEX will start Websocket - servers on named ports and wait for clients to connect. - Advantage: once APEX is running all connectivity - infrastructure is running as well. Consequence: if APEX is - not running, everyone else is in the dark, too. - - .. container:: paragraph - - The best protocol to be used is JSON string. Each event on - any interface is then a string with a JSON encoding. JSON - string is a little bit slower than byte code, but we doubt - that this will be noticeable. A further advantage of JSON - strings over Websockets with APEX starting the servers: it - is very easy to connect web browsers to such a system. - Simple connect the web browser to the APEX sockets and - send/read JSON strings. - - .. container:: paragraph - - Once APEX is started you simply connect Websocket clients to - it, and send/receive event. When APEX is terminated, the - Websocket servers go down, and the clients will be - disconnected. APEX does not (yet) support auto-client - reconnect nor WAMP, so clients might need to be restarted or - reconnected manually after an APEX boot. - -Demo with VPN Policy Model --------------------------- - - .. container:: paragraph - - We assume that you have an APEX installation using the full - package, i.e. APEX with all examples, of version ``0.5.6`` - or higher. We will use the VPN policy from the APEX examples - here. - - .. container:: paragraph - - Now, have the following ready to start the demo: - - .. container:: ulist - - - 3 terminals on the host where APEX is running (we need 1 - for APEX and 1 for each client) - - - the events in the file - ``$APEX_HOME/examples/events/VPN/SetupEvents.json`` open - in an editor (we need to send those events to APEX) - - - the events in the file - ``$APEX_HOME/examples/events/VPN/Link09Events.json`` open - in an editor (we need to send those events to APEX) - -A Websocket Configuration for the VPN Domain -############################################ - - .. container:: paragraph - - Create a new APEX configuration using the VPN policy - model and configuring APEX as discussed above for - Websockets. Copy the following configuration into - ``$APEX_HOME/examples/config/VPN/Ws2WsServerAvroContextJsonEvent.json`` - (for Windows use - ``%APEX_HOME%\examples\config\VPN\Ws2WsServerAvroContextJsonEvent.json``): - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - { - "engineServiceParameters" : { - "name" : "VPNApexEngine", - "version" : "0.0.1", - "id" : 45, - "instanceCount" : 1, - "deploymentPort" : 12345, - "policyModelFileName" : "examples/models/VPN/VPNPolicyModelAvro.json", - "engineParameters" : { - "executorParameters" : { - "MVEL" : { - "parameterClassName" : "org.onap.policy.apex.plugins.executor.mvel.MVELExecutorParameters" - } - }, - "contextParameters" : { - "parameterClassName" : "org.onap.policy.apex.context.parameters.ContextParameters", - "schemaParameters":{ - "Avro":{ - "parameterClassName" : "org.onap.policy.apex.plugins.context.schema.avro.AvroSchemaHelperParameters" - } - } - } - } - }, - "producerCarrierTechnologyParameters" : { - "carrierTechnology" : "WEBSOCKET", - "parameterClassName" : "org.onap.policy.apex.plugins.event.carrier.websocket.WEBSOCKETCarrierTechnologyParameters", - "parameters" : { - "wsClient" : false, - "port" : 42452 - } - }, - "producerEventProtocolParameters" : { - "eventProtocol" : "JSON" - }, - "consumerCarrierTechnologyParameters" : { - "carrierTechnology" : "WEBSOCKET", - "parameterClassName" : "org.onap.policy.apex.plugins.event.carrier.websocket.WEBSOCKETCarrierTechnologyParameters", - "parameters" : { - "wsClient" : false, - "port" : 42450 - } - }, - "consumerEventProtocolParameters" : { - "eventProtocol" : "JSON" - } - } - -Start APEX Engine -################# - - .. container:: paragraph - - In a new terminal, start APEX with the new configuration for - Websocket-Server ingress/egress: - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - #: $APEX_HOME/bin/apexEngine.sh -c $APEX_HOME/examples/config/VPN/Ws2WsServerAvroContextJsonEvent.json - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - #: %APEX_HOME%\bin\apexEngine.bat -c %APEX_HOME%\examples\config\VPN\Ws2WsServerAvroContextJsonEvent.json - -.. container:: paragraph - - Wait for APEX to start, it takes a while to create all Websocket - servers (about 8 seconds on a standard laptop without cached - binaries). depending on your log messages, you will see no (some, a - lot) log messages. If APEX starts correctly, the last few messages - you should see are: - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - 2017-07-28 13:17:20,834 Apex [main] INFO c.e.a.s.engine.runtime.EngineService - engine model VPNPolicyModelAvro:0.0.1 added to the engine-AxArtifactKey:(name=VPNApexEngine-0,version=0.0.1) - 2017-07-28 13:17:21,057 Apex [Apex-apex-engine-service-0:0] INFO c.e.a.s.engine.runtime.EngineService - Engine AxArtifactKey:(name=VPNApexEngine-0,version=0.0.1) processing ... - 2017-07-28 13:17:21,296 Apex [main] INFO c.e.a.s.e.r.impl.EngineServiceImpl - Added the action listener to the engine - Started Apex service - -.. container:: paragraph - - APEX is running in the new terminal and will produce output when the - policy is triggered/executed. - -Run the Websocket Echo Client -############################# - - .. container:: paragraph - - The echo client is included in an APEX full installation. To run - the client, open a new shell (Unix, Cygwin) or command prompt - (``cmd`` on Windows). Then use the APEX application launcher to - start the client. - - .. important:: - APEX engine needs to run first - The example assumes that an APEX engine configured for *produce* carrier technology Websocket and *JSON* event protocol is executed first. - - +---------------------------------------------------------+-----------------------------------------------------------+ - | Unix, Cygwin | Windows | - +=========================================================+===========================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: listingblock | .. container:: listingblock | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | | | - | # $APEX_HOME/bin/apexApps.sh ws-echo [args] | > %APEX_HOME%\bin\apexApps.bat ws-echo [args] | - +---------------------------------------------------------+-----------------------------------------------------------+ - - .. container:: paragraph - - Use the following command line arguments for server and port of - the Websocket server. The port should be the same as configured in - the APEX engine. The server host should be the host on which the - APEX engine is running - - .. container:: ulist - - - ``-p`` defines the Websocket port to connect to (defaults to - ``8887``) - - - ``-s`` defines the host on which a Websocket server is running - (defaults to ``localhost``) - - .. container:: paragraph - - Let’s assume that there is an APEX engine running, configured for - produce Websocket carrier technology, as server, for port 42452, - with produce event protocol JSON,. If we start the console client - on the same host, we can omit the ``-s`` options. We start the - console client as: - - .. container:: listingblock - - .. container:: content - - .. code:: - - # $APEX_HOME/bin/apexApps.sh ws-echo -p 42452 (1) - > %APEX_HOME%\bin\apexApps.bat ws-echo -p 42452 (2) - - .. container:: colist arabic - - +-------+--------------------------------+ - | **1** | Start client on Unix or Cygwin | - +-------+--------------------------------+ - | **2** | Start client on Windows | - +-------+--------------------------------+ - - .. container:: paragraph - - Once started successfully, the client will produce the following - messages (assuming we used ``-p 42452`` and an APEX engine is - running on ``localhost`` with the same port: - - .. container:: listingblock - - .. container:: content - - .. code:: - - ws-simple-echo: starting simple event echo - --> server: localhost - --> port: 42452 - - Once started, the application will simply print out all received events to standard out. - Each received event will be prefixed by '---' and suffixed by '====' - - - ws-simple-echo: opened connection to APEX (Web Socket Protocol Handshake) - -Run the Websocket Console Client -################################ - - .. container:: paragraph - - The console client is included in an APEX full installation. To - run the client, open a new shell (Unix, Cygwin) or command prompt - (``cmd`` on Windows). Then use the APEX application launcher to - start the client. - - .. important:: - APEX engine needs to run first - The example assumes that an APEX engine configured for *consume* carrier technology Websocket and *JSON* event - protocol is executed first. - - +------------------------------------------------------------+--------------------------------------------------------------+ - | Unix, Cygwin | Windows | - +============================================================+==============================================================+ - | .. container:: | .. container:: | - | | | - | .. container:: listingblock | .. container:: listingblock | - | | | - | .. container:: content | .. container:: content | - | | | - | .. code:: | .. code:: | - | | | - | # $APEX_HOME/bin/apexApps.sh ws-console [args] | > %APEX_HOME%\bin\apexApps.bat ws-console [args] | - +------------------------------------------------------------+--------------------------------------------------------------+ - - .. container:: paragraph - - Use the following command line arguments for server and port of - the Websocket server. The port should be the same as configured in - the APEX engine. The server host should be the host on which the - APEX engine is running - - .. container:: ulist - - - ``-p`` defines the Websocket port to connect to (defaults to - ``8887``) - - - ``-s`` defines the host on which a Websocket server is running - (defaults to ``localhost``) - - .. container:: paragraph - - Let’s assume that there is an APEX engine running, configured for - consume Websocket carrier technology, as server, for port 42450, - with consume event protocol JSON,. If we start the console client - on the same host, we can omit the ``-s`` options. We start the - console client as: - - .. container:: listingblock - - .. container:: content - - .. code:: - - # $APEX_HOME/bin/apexApps.sh ws-console -p 42450 (1) - > %APEX_HOME%\bin\apexApps.sh ws-console -p 42450 (2) - - .. container:: colist arabic - - +-------+--------------------------------+ - | **1** | Start client on Unix or Cygwin | - +-------+--------------------------------+ - | **2** | Start client on Windows | - +-------+--------------------------------+ - - .. container:: paragraph - - Once started successfully, the client will produce the following - messages (assuming we used ``-p 42450`` and an APEX engine is - running on ``localhost`` with the same port: - - .. container:: listingblock - - .. container:: content - - .. code:: - - ws-simple-console: starting simple event console - --> server: localhost - --> port: 42450 - - - terminate the application typing 'exit<enter>' or using 'CTRL+C' - - events are created by a non-blank starting line and terminated by a blank line - - - ws-simple-console: opened connection to APEX (Web Socket Protocol Handshake) - -Send Events -########### - - .. container:: paragraph - - Now you have the full system up and running: - - .. container:: ulist - - - Terminal 1: APEX ready and loaded - - - Terminal 2: an echo client, printing received messages produced - by the VPN policy - - - Terminal 2: a console client, waiting for input on the console - (standard in) and sending text to APEX - - .. container:: paragraph - - We started the engine with the VPN policy example. So all the - events we are using now are located in files in the following - example directory: - - .. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - #: $APEX_HOME/examples/events/VPN - > %APEX_HOME%\examples\events\VPN - -.. container:: paragraph - - To sends events, simply copy the content of the event files into - Terminal 3 (the console client). It will read multi-line JSON text - and send the events. So copy the content of ``SetupEvents.json`` into - the client. APEX will trigger a policy and produce some output, the - echo client will also print some events created in the policy. In - Terminal 1 (APEX) you’ll see some status messages from the policy as: - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - {Link=L09, LinkUp=true} - L09 true - outFields: {Link=L09, LinkUp=true} - {Link=L10, LinkUp=true} - L09 true - L10 true - outFields: {Link=L10, LinkUp=true} - {CustomerName=C, LinkList=L09 L10, SlaDT=300, YtdDT=300} - *** Customers *** - C 300 300 [L09, L10] - outFields: {CustomerName=C, LinkList=L09 L10, SlaDT=300, YtdDT=300} - {CustomerName=A, LinkList=L09 L10, SlaDT=300, YtdDT=50} - *** Customers *** - A 300 50 [L09, L10] - C 300 300 [L09, L10] - outFields: {CustomerName=A, LinkList=L09 L10, SlaDT=300, YtdDT=50} - {CustomerName=D, LinkList=L09 L10, SlaDT=300, YtdDT=400} - *** Customers *** - A 300 50 [L09, L10] - C 300 300 [L09, L10] - D 300 400 [L09, L10] - outFields: {CustomerName=D, LinkList=L09 L10, SlaDT=300, YtdDT=400} - {CustomerName=B, LinkList=L09 L10, SlaDT=300, YtdDT=299} - *** Customers *** - A 300 50 [L09, L10] - B 300 299 [L09, L10] - C 300 300 [L09, L10] - D 300 400 [L09, L10] - outFields: {CustomerName=B, LinkList=L09 L10, SlaDT=300, YtdDT=299} - -.. container:: paragraph - - In Terminal 2 (echo-client) you see the received events, the last two - should look like: - -.. container:: listingblock - - .. container:: content - - .. code:: - :number-lines: - - ws-simple-echo: received - --------------------------------- - { - "name": "VPNCustomerCtxtActEvent", - "version": "0.0.1", - "nameSpace": "org.onap.policy.apex.domains.vpn.events", - "source": "Source", - "target": "Target", - "CustomerName": "C", - "LinkList": "L09 L10", - "SlaDT": 300, - "YtdDT": 300 - } - ================================= - - ws-simple-echo: received - --------------------------------- - { - "name": "VPNCustomerCtxtActEvent", - "version": "0.0.1", - "nameSpace": "org.onap.policy.apex.domains.vpn.events", - "source": "Source", - "target": "Target", - "CustomerName": "D", - "LinkList": "L09 L10", - "SlaDT": 300, - "YtdDT": 400 - } - ================================= - -.. container:: paragraph - - Congratulations, you have triggered a policy in APEX using - Websockets, the policy did run through, created events, picked up by - the echo-client. - -.. container:: paragraph - - Now you can send the Link 09 and Link 10 events, they will trigger - the actual VPN policy and some calculations are made. Let’s take the - Link 09 events from ``Link09Events.json``, copy them all into - Terminal 3 (the console). APEX will run the policy (with some status - output), and the echo client will receive and print events. - -.. container:: paragraph - - To terminate the applications, simply press ``CTRL+C`` in Terminal 1 - (APEX). This will also terminate the echo-client in Terminal 2. Then - type ``exit<enter>`` in Terminal 3 (or ``CTRL+C``) to terminate the - console-client. - -.. container:: - :name: footer - - .. container:: - :name: footer-text - - 2.0.0-SNAPSHOT - Last updated 2018-09-10 15:38:16 IST - -.. |Extract the TAR archive| image:: images/install-guide/win-extract-tar-gz.png -.. |Extract the APEX distribution| image:: images/install-guide/win-extract-tar.png -.. |REST Editor Start Screen| image:: images/install-guide/rest-start.png -.. |REST Editor with loaded SampleDomain Policy Model| image:: images/install-guide/rest-loaded.png -.. |APEX Configuration Matrix| image:: images/apex-intro/ApexEngineConfig.png -.. |File > New to create a new Policy Model| image:: images/mfp/MyFirstPolicy_P1_newPolicyModel1.png -.. |Create a new Policy Model| image:: images/mfp/MyFirstPolicy_P1_newPolicyModel2.png -.. |Right click to create a new event| image:: images/mfp/MyFirstPolicy_P1_newEvent1.png -.. |Fill in the necessary information for the 'SALE_INPUT' event and click 'Submit'| image:: images/mfp/MyFirstPolicy_P1_newEvent2.png -.. |Right click to create a new Item Schema| image:: images/mfp/MyFirstPolicy_P1_newItemSchema1.png -.. |Create a new Item Schema| image:: images/mfp/MyFirstPolicy_P1_newItemSchema2.png -.. |Add new event parameters to an event| image:: images/mfp/MyFirstPolicy_P1_newEvent3.png -.. |Right click to create a new task| image:: images/mfp/MyFirstPolicy_P1_newTask1.png -.. |Add input and out fields for the task| image:: images/mfp/MyFirstPolicy_P1_newTask2.png -.. |Add task logic the task| image:: images/mfp/MyFirstPolicy_P1_newTask3.png -.. |Create a new policy| image:: images/mfp/MyFirstPolicy_P1_newPolicy1.png -.. |Create a state| image:: images/mfp/MyFirstPolicy_P1_newState1.png -.. |Add a Task and Output Mapping| image:: images/mfp/MyFirstPolicy_P1_newState2.png -.. |Validate the policy model for error using the 'Model' > 'Validate' menu item| image:: images/mfp/MyFirstPolicy_P1_validatePolicyModel.png -.. |Download the completed policy model using the 'File' > 'Download' menu item| image:: images/mfp/MyFirstPolicy_P1_exportPolicyModel1.png -.. |Create a new alternative task MorningBoozeCheckAlt1| image:: images/mfp/MyFirstPolicy_P2_newTask1.png -.. |Right click to edit a policy| image:: images/mfp/MyFirstPolicy_P2_editPolicy1.png -.. |State definition with 2 Tasks and Task Selection Logic| image:: images/mfp/MyFirstPolicy_P2_editState1.png - |