summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--INFO.yaml28
-rw-r--r--docs/apex/APEX-Developer-Guide.rst1471
-rw-r--r--docs/apex/APEX-Install-Guide.rst1418
-rw-r--r--docs/apex/APEX-Policy-Guide.rst3267
-rw-r--r--docs/apex/apex.rst4
-rw-r--r--docs/api/api.rst9
-rw-r--r--docs/api/swagger/policy-api.json281
-rw-r--r--docs/offeredapis.rst24
-rw-r--r--integration/pom.xml38
9 files changed, 1795 insertions, 4745 deletions
diff --git a/INFO.yaml b/INFO.yaml
index 30df0f67..d353d831 100644
--- a/INFO.yaml
+++ b/INFO.yaml
@@ -28,22 +28,7 @@ meetings:
repeats: 'weekly'
time: '13:00 UTC'
repositories:
- - 'policy-apex-pdp'
- - 'policy-api'
- - 'policy-common'
- - 'policy-core'
- - 'policy-distribution'
- - 'policy-docker'
- - 'policy-drools-applications'
- - 'policy-drools-pdp'
- - 'policy-engine'
- - 'policy-gui'
- - 'policy-models'
- - 'policy-oom'
- - 'policy-pap'
- - 'policy-parent'
- - 'policy-pdp'
- - 'policy-xacml-pdp'
+ - 'policy/parent'
committers:
- <<: *onap_releng_ptl
- name: 'Jorge Hernandez'
@@ -66,11 +51,20 @@ committers:
company: 'Ericsson'
id: 'ramverma'
timezone: 'Europe/Ireland'
+ - name: 'Ajith Sreekumar'
+ email: 'ajith.sreekumar@bell.ca'
+ company: 'Ericsson'
+ id: 'a.sreekumar'
+ timezone: 'Europe/Ireland'
tsc:
approval: 'https://lists.onap.org/pipermail/onap-tsc'
changes:
- type: 'Addition'
name: 'Jim Hahn'
+ link: https://lists.onap.org/g/onap-tsc/message/4976
+ - type: 'Addition'
name: 'Ram Krishna Verma'
link: https://lists.onap.org/g/onap-tsc/message/4977
- link: https://lists.onap.org/g/onap-tsc/message/4976
+ - type: 'Addition'
+ name: 'Ajith Sreekumar'
+ link: https://lists.onap.org/g/onap-tsc/message/6869
diff --git a/docs/apex/APEX-Developer-Guide.rst b/docs/apex/APEX-Developer-Guide.rst
deleted file mode 100644
index b247ab83..00000000
--- a/docs/apex/APEX-Developer-Guide.rst
+++ /dev/null
@@ -1,1471 +0,0 @@
-.. This work is licensed under a Creative Commons Attribution 4.0 International License.
-.. http://creativecommons.org/licenses/by/4.0
-
-
-APEX Developer Guide
-********************
-
-.. contents::
- :depth: 3
-
-Build APEX from Source
-^^^^^^^^^^^^^^^^^^^^^^
-
-Introduction to building APEX
------------------------------
-
- .. container:: paragraph
-
- APEX is written 100% in Java and uses `Apache
- Maven <https://maven.apache.org/>`__ as the build system.
- The requirements for building APEX are:
-
- .. container:: ulist
-
- - An installed Java development kit for Java version 8
- or higher
-
- .. container:: ulist
-
- - To install a Java SDK please follow these
- guidelines `Oracle Java 8
- SDK <https://docs.oracle.com/javase/8/docs/technotes/guides/install/install_overview.html>`__.
-
- - Maven 3
-
- .. container:: ulist
-
- - To get Maven 3 running please follow the
- guidelines for
- `Download <https://maven.apache.org/download.cgi>`__
- and
- `Install <https://maven.apache.org/install.html>`__,
- and `Run <https://maven.apache.org/run.html>`__
- Maven
-
- - A clone of the APEX source repositories
-
- .. container:: paragraph
-
- To get a clone of the APEX source repositories, please
- see the APEX Installation Guide or the APEX User manual.
-
- .. container:: paragraph
-
- Once all requirements are in place, APEX can be build.
- There are several different artifacts one can create
- building APEX, most of them defined in their own
- *profile*. APEX can also be built in a standard way with
- standard tests (``mvn clean install``) or without
- standard tests (``mvn clean install -DskipTests``).
-
- .. container:: paragraph
-
- The examples in this document assume that the APEX source
- repositories are cloned to:
-
- .. container:: ulist
-
- - Unix, Cygwin: ``/usr/local/src/apex``
-
- - Windows: ``C:\dev\apex``
-
- - Cygwin: ``/cygdrive/c/dev/apex``
-
- .. 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 to download all dependencies and plugins)
- 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 built if the ``rpm`` package is installed (Unix). To install ``rpm``
- run ``sudo apt-get install rpm``, then build APEX.
-
-Standard Build
---------------
-
- .. container:: paragraph
-
- Use Maven to for a standard build without any tests.
-
- +-----------------------------------+------------------------------------+
- | Unix, Cygwin | Windows |
- +===================================+====================================+
- | :: | :: |
- | | |
- | >c: | # cd /usr/local/src/apex |
- | >cd \dev\apex | # mvn clean install -DskipTests |
- | >mvn clean install -DskipTests | |
- | | |
- +-----------------------------------+------------------------------------+
-
-.. container:: paragraph
-
- The build takes about 6 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
-
- .. code:: bash
- :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.
-
-+-----------------------------------------------------------------------------------------------------------------------------+
-| Unix, Cygwin |
-+=============================================================================================================================+
-| .. container:: |
-| |
-| .. container:: listingblock |
-| |
-| .. code:: bash |
-| :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:: bash |
-| :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 |
-+-----------------------------------------------------------------------------------------------------------------------------+
-
-
-Checkstyle with Maven
----------------------
-
- .. container:: paragraph
-
- The codestyle for all APEX java projects can be checked
- automatically. The checks include empty or non-existing Javadocs.
- Any checkstyle run should complete without any errors, some
- warnings are acceptable.
-
- .. container:: paragraph
-
- To run checkstyle on an APEX Maven project use:
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- mvn checkstyle:check
-
- .. container:: paragraph
-
- To run checkstyle on all modules use:
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- mvn checkstyle:checkstyle -DapexAll
-
-Build with standard Tests
--------------------------
-
- .. container:: paragraph
-
- Use Maven for a standard build with standard tests.
-
- .. important::
- Some tests have specific timing Requirements
- Some of the tests have very specific timing requirements. If run on a low-powered build machine, or if the build
- machine is on high load, those tests might fail and the whole build might fail as well. If this happens, reduce the load
- on your build machine and restart the build.
-
- +-----------------------------------+-----------------------------------+
- | Unix, Cygwin | Windows |
- +===================================+===================================+
- | .. container:: | .. container:: |
- | | |
- | .. container:: content | .. container:: content |
- | | |
- | .. code:: bash | .. code:: bash |
- | :number-lines: | :number-lines: |
- | | |
- | >c: | # cd /usr/local/src/apex |
- | >cd \dev\apex | # mvn clean install |
- | >mvn clean install | |
- +-----------------------------------+-----------------------------------+
-
-
-.. container:: paragraph
-
- The build takes about 10 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 built 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
- successfully.
-
-Build with all Tests
---------------------
-
- .. container:: paragraph
-
- Use Maven to for a standard build with *all* tests.
-
- .. important::
- Some tests have specific timing Requirements.
- Some of the tests have very specific timing requirements. If run on a low-powered build machine, or if the build
- machine is on high load, those tests might fail and the whole build might fail as well. If this happens, reduce the load
- on your build machine and restart the build.
-
- .. important::
- Might require specific software.
- When running all tests, some modules require specific software installed on the build machine. For instance,
- testing the full capabilities of context (with distribution and persistence) will require Hazelcast and Infinispan
- installed on the build machine.
-
- +----------------------------------------------+----------------------------------------------+
- | Unix, Cygwin | Windows |
- +==============================================+==============================================+
- | .. container:: | .. container:: |
- | | |
- | .. container:: content | .. container:: content |
- | | |
- | .. code:: bash | .. code:: bash |
- | :number-lines: | :number-lines: |
- | | |
- | >c: | # cd /usr/local/src/apex |
- | >cd \dev\apex | # mvn clean install -DallTests |
- | >mvn clean install -DallTests | |
- +----------------------------------------------+----------------------------------------------+
-
-Build with all Components
--------------------------
-
- .. container:: paragraph
-
- A standard APEX build will not build all components. Some parts
- are for specific deployments, only. Use Maven for a standard
- build with *all* components.
-
- .. important::
- Might require specific software.
- When building all components, some modules require specific software to be installed on the build machine.
-
- +----------------------------------------------+----------------------------------------------+
- | Unix, Cygwin | Windows |
- +==============================================+==============================================+
- | .. container:: | .. container:: |
- | | |
- | .. container:: content | .. container:: content |
- | | |
- | .. code:: bash | .. code:: bash |
- | :number-lines: | :number-lines: |
- | | |
- | >c: | # cd /usr/local/src/apex |
- | >cd \dev\apex | # mvn clean install -DapexAll |
- | >mvn clean install -DapexAll | |
- +----------------------------------------------+----------------------------------------------+
-
-
-Build the APEX Documentation
-----------------------------
-
- .. container:: paragraph
-
- The APEX Maven build also includes stand-alone documentation,
- such as the HowTo documents, the Installation Guide, and the User
- Manual. Use Maven to build the APEX Documentation. The Maven
- option ``-N`` prevents Maven from going through all APEX modules,
- which is not necessary for the documentation. The final documents
- will be in ``target/generated-docs`` (Windows:
- ``target\generated-docs``). The *HTML* documents are in the
- ``html/`` folder, the *PDF* documents are in the ``pdf/`` folder.
- Once the documentation is built, copy the *HTML* and *PDF*
- documents to a folder of choice
-
- +-------------------------------------------------------+--------------------------------------------------------+
- | Unix, Cygwin | Windows |
- +=======================================================+========================================================+
- | .. container:: | .. container:: |
- | | |
- | .. container:: content | .. container:: content |
- | | |
- | .. code:: bash | .. code:: bash |
- | :number-lines: | :number-lines: |
- | | |
- | >c: | # cd /usr/local/src/apex |
- | >cd \dev\apex | # mvn clean generate-resources -N -DapexDocs |
- | >mvn clean generate-resources -N -DapexDocs | |
- +-------------------------------------------------------+--------------------------------------------------------+
-
-Build APEX Site
----------------
-
- .. container:: paragraph
-
- The APEX Maven build comes with full support to build a web site
- using Maven Site. Use Maven to build the APEX Site. Stage the APEX
- web site. The target folder for the staged site is
-
- .. container:: ulist
-
- - Unix: ``/usr/local/src/apex/target/ad-site``
-
- - Windows: ``C:\dev\apex\target\ad-site``
-
- - Cygwin: ``/cygdrive/c/dev/apex/target/ad-site``
-
- .. container:: paragraph
-
- Once the web site is staged, copy the full site to a folder of
- choice or into a web server.
-
- .. important::
- Building a Site takes Time.
- Building and staging the APEX web site can take very long. The stand-alone documentation will take about 2 minutes. The
- sites for all modules and projects and the main APEX site can take between 10-30 minutes depending on your build machine (~10 minutes
- without generating source and test-source reports, closer to 30 minutes with all reports).
-
- .. container:: paragraph
-
- Start the build deleting the staging directory that might have
- been created by a previous site build. Then go to the APEX
- packaging directory.
-
- +--------------------------------+-----------------------------------+----------------------------------+
- | Unix | Windows | Cygwin |
- +================================+===================================+==================================+
- | .. container:: | .. container:: | .. container:: |
- | | | |
- | .. container:: content | .. container:: content | .. container:: content |
- | | | |
- | .. code:: bash | .. code:: bash | .. code:: bash |
- | :number-lines: | :number-lines: | :number-lines: |
- | | | |
- | cd /usr/local/src/apex | c: | cd /cygdrive/c/dev/apex |
- | rm -fr target/ad-site | cd \dev\apex | rm -fr target/ad-site |
- | | rmdir /s/q target\ad-site | |
- +--------------------------------+-----------------------------------+----------------------------------+
-
- .. container:: paragraph
-
- the workflow for building a complete site then is as follows:
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- mvn clean -DapexAll (1)
- mvn install -DskipTests (2)
- mvn generate-resources -N -DapexDocs (3)
- mvn initialize site:attach-descriptor site site:stage -DapexSite (4)
-
- .. container:: olist arabic
-
- #. First clean all modules to remove any site artifacts, use the
- *apexXtext* profile to make sure these modules are processed as
- well
-
- #. Next run a simple install without tests
-
- #. Now generate the APEX stand-alone documentation, they are in
- the local package only so we can use the *-N* switch
-
- #. Last build the actual sites and stage (copy to the staging
- directory) with the profile *apexSite* (do not forget the
- initialize goal, otherwise the staging directory will not be
- correctly set and sites are staged in every model in a
- directory called ``docs``).
-
- .. container:: paragraph
-
- If you want to build the site for a particular project for
- testing, the Maven command is simpler. Since only the main project
- has APEX documentation (stand-alone), you can use Maven as follow.
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- mvn clean site -DapexSite
-
- .. container:: paragraph
-
- If you want to stage the tested site, then use
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- mvn clean initialize site:attach-descriptor site site:stage -DapexSite
-
-APEX Codestyle
-^^^^^^^^^^^^^^
-
-Introduction: APEX Codestyle
-----------------------------
-
- .. container:: paragraph
-
- This page describes how to apply a code style to the APEX
- Java projects. The provided code templates are guidelines
- and are provided for references and as examples. We will not
- engage in "holy war" on style for coding. As long as the
- style of a particular block of code is understandable,
- consistent, and readable, please feel free to adapt or
- modify these guides or use other guides as you see fit.
-
- .. container:: paragraph
-
- The JAutoDoc and Checkstyle Eclipse Plugins and tools are
- useful and remove a lot of the tedium from code
- documentation. Use them to check your code and please fix
- any issues they identify with your code.
-
- .. container:: paragraph
-
- Since APEX is part of ONAP, the general ONAP rules and
- guideliness for development do apply. Please see `ONAP
- Wiki <https://wiki.onap.org/display/DW/Developing+ONAP>`__
- for details.
-
-Java coding Rules
------------------
-
- .. container:: ulist
-
- - APEX is (in large parts) a platform (or middleware), so
- `Software Design
- Patterns <https://en.wikipedia.org/wiki/Software_design_pattern>`__
- are a good thing
-
- - The `Solid
- Principles <https://en.wikipedia.org/wiki/SOLID_(object-oriented_design)>`__
- apply
-
- - Avoid class fields scoped as ``protected``
-
- .. container:: ulist
-
- - They break a lot of good design rules, e.g. most
- SOLID rules
-
- - For a discussion see this `Stackoverflow
- Question <https://softwareengineering.stackexchange.com/questions/162643/why-is-clean-code-suggesting-avoiding-protected-variables>`__
-
- - If you absolutely need ``protected`` class fields they
- should be ``final``
-
- - Avoid ``default`` scope for class fields and methods
-
- .. container:: ulist
-
- - For fields: use ``public`` or ``private`` (see also
- above)
-
- - For methods: use ``public`` for general use,
- ``protected`` for specialization using inheritance
- (ideally ``final``), ``private`` for everything
- else
-
- - Method parameters that are not changed in the method
- should be marked ``final``
-
- - Every package must have a ``package-info.java`` file with
- an appropriate description, minimum a descriptive one
- liner
-
- - Every class must have
-
- .. container:: ulist
-
- - The common header (copyright, file, date)
-
- - Javadoc header for the class with description of
- the class and author
-
- - Javadoc for *all public\_* fields
-
- - If possible, Javadoc for *private* fields, at least
- some documentation for private fields
-
- - Javadoc for *all* methods
-
- - All projects must build with all tests on Unix, Windows,
- *and* Cygwin
-
- .. container:: ulist
-
- - Support all line endings in files, e.g. ``\n`` and
- ``\r\n``
-
- - Be aware of potential differences in exception
- messages, if testing against a message
-
- - Support all types of paths: Unix with ``/``,
- Windows with an optinal drive ``C:\`` and ``\``,
- Cygwin with mixed paths
-
-Eclipse Plugin: JAutodoc
-------------------------
-
- .. container:: paragraph
-
- This plugin is a helper plugin for writing Javadoc. It will
- automatically create standard headers on files, create
- package-info.java files and will put in remarkably good stub
- Javadoc comments in your code, using class names and method
- names as hints.
-
- .. container:: paragraph
-
- Available from the Eclipse Marketplace. In Eclipse
- Help→Eclipse Marketplace…​ and type ``JAutodoc``. Select
- JAutodoc when the search returns and install it.
-
- .. container:: paragraph
-
- You must configure JAutoDoc in order to get the most out of
- it. Ideally JAutoDoc should be configured with templates
- that cooperate with the inbuilt Eclipse Code Formatter for
- best results.
-
-Eclipse Plugin: Checkstyle
---------------------------
-
- .. container:: paragraph
-
- This plugin integrates
- `Checkstyle <http://checkstyle.sourceforge.net/>`__ into
- Eclipse. It will check your code and flag any checkstyle
- issues as warnings in the code.
-
- .. container:: paragraph
-
- Available from the Eclipse Marketplace. In Eclipse
- Help→Eclipse Marketplace…​ and type "Checkstyle". Select
- "Checkstyle Plug-in" when the search returns and install it.
- Note that "Checkstyle Plug-in" may not be the first result
- in the list of items returned.
-
- .. container:: paragraph
-
- For APEX, the ONAP checkstyle rules do apply. The
- configuration is part of the ONAP parent. See `ONAP
- Git <https://git.onap.org/oparent/plain/checkstyle/src/main/resources/onap-checkstyle/>`__
- for details and updates. All settings for checkstyle are
- already part of the code (POM files).
-
-Configure Eclipse
------------------
-
- .. container:: ulist
-
- - Set the template for Eclipse code clean up
-
- .. container:: olist arabic
-
- #. Eclipse  Window  Preferences  Java  Code Style
- Clean Up → Import…​
-
- #. Select your template file
- (``ApexCleanUpTemplate.xml``) and apply it
-
- - Set the Eclipse code templates
-
- .. container:: olist arabic
-
- #. Eclipse  Window  Preferences  Java  Code Style
- Code Templates → Import…​
-
- #. Select your templates file
- (``ApexCodeTemplates.xml``) and apply it
-
- .. container:: ulist
-
- - Make sure to set your email address in
- generated comments by selecting
- "Comments→Types" in the "Configure generated
- code and comments:" pane, then change the
- email address on the @author tag to be your
- email address
-
- - Set the Eclipse Formatter profile
-
- .. container:: olist arabic
-
- #. Eclipse  Window  Preferences  Java  Code Style
- Formatter → Import…​
-
- #. Select your formatter profile file
- (``ApexFormatterProfile.xml``) and apply it
-
- .. container:: paragraph
-
- The templates mentioned above can be found in
- ``apex-model/apex-model.build-tools/src/main/resources/eclipse``
-
-Configure JAutodoc (Eclipse)
-----------------------------
-
- .. container:: paragraph
-
- Import the settings for JAutodoc:
-
- .. container:: olist arabic
-
- #. Eclipse  Window  Preferences  Java  JAutodoc → Import
- All…​ (at bottom of the JAutodoc preferences window)
-
- #. Leave all the preferences ticked to import all
- preferences, browse to the JAutodoc setting file
- (``ApexJautodocSettings.xml``) and press OK
-
- #. Set your email address in the package Javadoc template
-
- .. container:: ulist
-
- - Press Edit Template…​ in the Package Javadoc area
- of the JAutodoc preferences window, and change the
- email address on the ``@author`` tag to be your
- email address
-
- #. Now, apply the JAutodoc settings
-
- .. container:: paragraph
-
- The templates mentioned above can be found in
- ``apex-model/apex-model.build-tools/src/main/resources/eclipse``
-
-Configure Checkstyle (Maven)
-----------------------------
-
- .. container:: paragraph
-
- When using a custom style configuration with Checkstyle, the
- definition of that style must of course be available to
- Checkstyle. In order not to have to distribute style files
- for checkstyle into all Maven modules, it is recommended
- that a special Maven module be built that contains the
- checkstyle style definition. That module is then used as a
- dependency in the *POM* for all other modules that wish to
- use that checkstyle style. For a full explanation see `the
- explanation of Checkstyle multi-module
- configuration <https://maven.apache.org/plugins/maven-checkstyle-plugin/examples/multi-module-config.html>`__.
-
- .. container:: paragraph
-
- For APEX, the ONAP checkstyle rules do apply. The
- configuration is part of the ONAP parent. See `ONAP
- Git <https://git.onap.org/oparent/plain/checkstyle/src/main/resources/onap-checkstyle/>`__
- for details and updates.
-
-Run Checkstyle (Maven)
-----------------------
-
- .. container:: paragraph
-
- Run Checkstyle using Maven on the command line with the
- command:
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- mvn checkstyle:check
-
- .. container:: paragraph
-
- On the main APEX project, run a full checkstyle check as:
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- mvn checkstyle:checkstyle -DapexAll
-
-Configure Checkstyle (Eclipse, globally)
-----------------------------------------
-
- .. container:: olist arabic
-
- #. Set up a module with the Checkstyle style files (see
- above)
-
- #. In Eclipse  Window  Preferences go to Checkstyle
-
- #. Import the settings for Checkstyle
-
- .. container:: ulist
-
- - Press New…​ to create a new *Global Check
- Configurations* entry
-
- - Give the configuration a name such as *Apex
- Checkstyle Configuration* and select the *External
- Configuration File* form in the *Type* drop down
- menu
-
- - Browse to the Checckstyle setting file
- (``ApexCheckstyleSettings.xml``) and press OK
-
- #. Press OK
-
- .. container:: ulist
-
- - You may now get an *Unresolved Properties found*
- dialogue
-
- - This is because there is a second Checkstyle
- configuration file required to check file headers
-
- #. Press Edit Properties…​ and press Find unresolved
- properties on the next dialogue window
-
- #. The plugin will find the ``${checkstyle.header.file}``
- property is unresolved and will ask should it be added to
- the properties, click yes
-
- #. Now, select the row on the dialogue for the
- ``checkstyle.header.file property`` and click Edit…​
-
- #. Set the value of the ``checkstyle.header.file property``
- to
- ``<your-apex-git-location>/apex-model/apex-model.build-tools/src/main/resources/checkstyle/apex_header.txt``
-
- .. container:: ulist
-
- - Of course replacing the tag
- ``<your-apex-git-location>`` with the location of
- your Apex GIT repository
-
- #. Press OK, OK, OK to back out to the main Checkstyle
- properties window
-
- #. Select the *Apex Checkstyle Configuration* as your
- default configuration by selecting its line in the
- *Global Check Configuraitons* list and clicking Set as
- Default
-
- #. Press Apply and Close to finish Checkstyle global
- configuration
-
- .. container:: paragraph
-
- The templates mentioned above can be found in
- ``apex-model/apex-model.build-tools/src/main/resources/eclipse``
-
-2.10. Configure Checkstyle Blueprint
-------------------------------------
-
- .. container:: paragraph
-
- As well as being configured globally, Checkstyle must be
- configured and activated for each project in Eclipse. In
- order to make this process less tedious, set up the first
- project you apply Checkstye to as a blueprint project and
- then use this blueprint for all other projects.
-
- .. container:: olist arabic
-
- #. Select the project you want to use as a blueprint
-
- .. container:: ulist
-
- - For example, ``apex-model.basic-model`` in ``apex``
- and enter the project properties by right clicking
- and selecting **Properties**
-
- #. Click *Checkstyle* on the properties to get the
- Checkstyle project configuration window
-
- #. Click the box *Checkstyle active for this project* and in
- the *Exclude from checking…​* list check the boxes:
-
- .. container:: ulist checklist
-
- - *files outside source directories*
-
- - *derived (generated) files*
-
- - *files from packages:*
-
- #. Now, in order to turn off checking on resource
- directories and on JUnit tests
-
- .. container:: ulist
-
- - Select the line *files from packages:* in the
- *Exclude from checking…​* list and click Change…​
-
- #. On the *Filter packages* dialogue
-
- .. container:: ulist
-
- - Check all the boxes except the top box, which is
- the box for *src/main/java*
-
- - Ensure that the *recursively exclude sub-packages*
- check box is ticked
-
- .. container:: ulist checklist
-
- - *recursively exclude sub-packages*
-
- - Press OK
-
- #. Press Apply and Close to apply the changes
-
-Use Eclipse Source Operations
------------------------------
-
- .. container:: paragraph
-
- Eclipse Source Operations can be carried out on individual
- files or on all the files in a package but do not recurse
- into sub-packages. They are available as a menu in Eclipse
- by selecting a file or package and right clicking on
- *Source*. Note that running *Clean Up…​* with the Apex clean
- up profile will run *Format* and *Organize Imports*. So if
- you run a clean up on a file or package, you need not run
- *Format* or *Organize Imports*.
-
- .. container:: paragraph
-
- We recommend you use the following Eclipse Source
- Operations:
-
- .. container:: olist arabic
-
- #. *Format* applies the current format definition to the
- file or all files in a package
-
- #. *Organize Imports* sorts the imports on each file in
- standard order
-
- #. *Clean Up* runs a number of cleaning operations on each
- file. The Apex clean up template
-
- .. container:: ulist
-
- - Remove ``this`` qualifier for non static field
- accesses
-
- - Change non static accesses to static members using
- declaring type
-
- - Change indirect accesses to static members to
- direct accesses (accesses through subtypes)
-
- - Convert control statement bodies to block
-
- - Convert ``for`` loops to enhanced ``for`` loops
-
- - Add final modifier to private fields
-
- - Add final modifier to local variables
-
- - Remove unused imports
-
- - Remove unused private methods
-
- - Remove unused private constructors
-
- - Remove unused private types
-
- - Remove unused private fields
-
- - Remove unused local variables
-
- - Add missing ``@Override`` annotations
-
- - Add missing ``@Override`` annotations to
- implementations of interface methods
-
- - Add missing ``@Deprecated`` annotations
-
- - Add missing serial version ID (generated)
-
- - Remove unnecessary casts
-
- - Remove unnecessary ``$NON-NLS$`` tags
-
- - Organize imports
-
- - Format source code
-
- - Remove trailing white spaces on all lines
-
- - Correct indentation
-
- - Remove redundant type arguments
-
- - Add file header (JAutodoc)
-
-Using JAutodoc
---------------
-
- .. container:: paragraph
-
- Similar to Eclipse Source Operations, JAutodoc operations
- can be carried out on individual files or on all the files
- in a package but do not recurse into sub-packages. The
- JAutodoc operations are available by selecting a file or
- package and right clicking on *JAutodoc*:
-
- .. container:: olist arabic
-
- #. To add a ``package-info.java`` file to a package, select
- the package and right-click Jautodoc  Add Package Javadoc
-
- #. To add headers to files select on a file (or on the
- package to do all files) and right click JAutodoc  Add
- Header
-
- #. To add JAutodoc stubs to files, select on a file (or on
- the package to do all files) and right click JAutodoc
- Add Javadoc
-
-Using Checkstyle
-----------------
-
- .. container:: paragraph
-
- In order to use Checkstyle, you must configure it per
- project and then activate it per project. The easiest way to
- do this is to set up one project as a blueprint and use that
- blueprint for other projects (see above). Once you have a
- blueprint project, you can use Checkstyle on other projects
- as follows
-
- .. container:: olist arabic
-
- #. Set up Checkstyle on projects by selecting one or more
- projects
-
- .. container:: ulist
-
- - Right clicking and selecting Checkstyle  Configure
- project(s) from *blueprint…​* and then selecting
- your blueprint project
-
- - (for example ``apex-model.basic-model``) from the
- list of projects and pressing OK
-
- #. Activate Checkstyle on projects by selecting one or more
- projects
-
- .. container:: ulist
-
- - Right clicking and selecting Checkstyle  Activate
- Checkstyle
-
- - Now Checkstyle warnings will appear on the selected
- projects if they have warnings
-
- #. You can disable Checkstyle checking on a file or a
- package (recursively) by selecting a file or package
-
- .. container:: ulist
-
- - Right clicking and selecting Checkstyle  Clear
- Checkstyle violations
-
- #. You can enable Checkstyle checking on a file or a package
- (recursively) by selecting a file or package
-
- .. container:: ulist
-
- - Right clicking and selecting Checkstyle  Check Code
- with Checkstyle
-
- #. On individual files, you can apply fixes that clear some
- Checkstyle warnings
-
- .. container:: ulist
-
- - Select the file, right click and select **Apply
- Checkstyle fixes**
-
-Disable Eclipse Formatting (partially)
---------------------------------------
-
- .. container:: paragraph
-
- Sometimes, the Eclipse code formatting results in correct
- but untidy indentation, for example when Java Persistence
- annotations or long sequences of lined-up assignments are
- formatted. You can disable formatting for sections of code.
-
- .. container:: olist arabic
-
- #. Ensure that Off/On Tags are enabled in Eclipse
-
- #. In Eclipse  Window  Preferences  Java  Code Style
- Formatter window press Edit…​
-
- #. Click on the *Off/On Tags* tab
-
- #. Ensure that the *Enable Off/On Tags* checkbox is checked
-
- #. Surround the section of code that you do not want the
- formatter to act on with comments containing the Off/On
- tags
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- // @formatter:off
- // Plugin Parameters
- private DistributorParameters distributorParameters = new DistributorParameters();
- private SchemaParameters schemaParameters = new SchemaParameters();
- private LockManagerParameters lockManagerParameters = new LockManagerParameters();
- private PersistorParameters persistorParameters = new PersistorParameters();
- // @formatter:on
-
-Supress Checkstyle (partially)
-------------------------------
-
- .. container:: paragraph
-
- Sometimes Checkstyle checks identify code that does not comply
- with Checkstyle rules. In limited cases Checkstyle rules can be
- suppressed, for example where it is impossible to design the code
- in a way that complies with Checkstyle or where the Checkstyle
- rule is impossible to apply. Checkstyle rules are suppressed as is
- explained in this `Stackoverflow
- post <https://stackoverflow.com/questions/4023185/how-to-disable-a-particular-checkstyle-rule-for-a-particular-line-of-code>`__.
-
- .. container:: paragraph
-
- The example below illustrates how to suppress a Checkstyle rule
- that specifies all methods must have seven parameters or less.
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- // CHECKSTYLE:OFF: checkstyle:ParameterNumber
- public myMethod(final int par1, final int par2, final int par3, final int par4,
- final int par5, final int par6, final int par7, final int par8) {
- }
- // CHECKSTYLE:ON: checkstyle:ParameterNumber
-
-apex-apps.utilities
-^^^^^^^^^^^^^^^^^^^
-
-CLI Example
------------
-
- .. container:: paragraph
-
- Using the APEX CLI utilities can be done as follows. First,
- add the dependency of the utility project to your POM file.
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- <dependency>
- <groupId>org.onap.policy.apex-pdp.tools</groupId>
- <artifactId>tools-common</artifactId>
- <version>2.0.0-SNAPSHOT</version>
- </dependency>
-
- .. container:: paragraph
-
- Now, create a new application project, for instance
- ``MyApp``. In this project, create a new main application
- class as ``Application.java``. In this class, create a new
- main method as ``public static void main(String[] args)``.
-
- .. container:: paragraph
-
- Now use the provided ``CliOptions`` and ``CliParser``.
- Manually importing means to add the following lines to the
- start of your application (in Eclipse this import will be
- done automatically):
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- import org.onap.policy.apex.tools.common.CliOptions;
- import org.onap.policy.apex.tools.common.CliParser;
-
-.. container:: paragraph
-
- Now, inside your ``main()`` method, start setting some general
- application properties. Important are the application name and some
- description of your application. For instance:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- String appName = "test-app";
- final String appDescription = "a test app for documenting how to use the CLI utilities";
-
-.. container:: paragraph
-
- Next, create a new CLI Parser and add a few CLI options from the
- standard ``CliOptions``. The following example adds options for help,
- version, and a model file:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- final CliParser cli = new CliParser();
- cli.addOption(CliOptions.HELP);
- cli.addOption(CliOptions.VERSION);
- cli.addOption(CliOptions.MODELFILE);
-
-.. container:: paragraph
-
- Next, parse the given CLI arguments:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- final CommandLine cmd = cli.parseCli(args);
-
-.. container:: paragraph
-
- Once the command line is parsed, we can look into the individual
- options, check if they are set, and then act accordingly. We start
- with the option for *help*. If the option is present, we print a help
- screen and return:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- // help is an exit option, print usage and exit
- if (cmd.hasOption('h') || cmd.hasOption("help")) {
- final HelpFormatter formatter = new HelpFormatter();
- LOGGER.info(appName + " v" + cli.getAppVersion() + " - " + appDescription);
- formatter.printHelp(appName, cli.getOptions());
- return;
- }
-
-.. container:: paragraph
-
- Next, we process the option for *version*. Here, we want to print a
- version for our application and return. The CLI Parser already
- provides a method to obtain the correct version for an APEX build, so
- we use that:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- // version is an exit option, print version and exit
- if (cmd.hasOption('v') || cmd.hasOption("version")) {
- LOGGER.info(appName + " " + cli.getAppVersion());
- return;
- }
-
-.. container:: paragraph
-
- Once help and version arguments are processed, we can proceed to look
- at all other options. We have added an option for a model file, so
- check this option and test if we can actually load a model file with
- the given argument. If we can load a model, everything is ok. If we
- cannot load a model, we print an error and return.
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- String modelFile = cmd.getOptionValue('m');
- if (modelFile == null) {
- modelFile = cmd.getOptionValue("model");
- }
- if (modelFile == null) {
- LOGGER.error(appName + ": no model file given, cannot proceed (try -h for help)");
- return;
- }
-
-.. container:: paragraph
-
- With a model file being loadable, we finish parsing command line
- arguments. We also print some status messages to note that the
- application now is ready to start:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- LOGGER.info(appName + ": starting");
- LOGGER.info(" --> model file: " + modelFile);
-
-.. container:: paragraph
-
- The last action now is to run the actual application. The example
- below is taken from a version of the ``Model2Cli`` application, which
- creates a new object and runs it in a ``try`` block, since exceptions
- might be thrown by the object:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- // your code for the application here
- // e.g.
- // try {
- // Model2Cli app = new Model2Cli(modelFile, !cmd.hasOption("sv"), appName);
- // app.runApp();
- // }
- // catch(ApexException aex) {
- // LOGGER.error(appName + ": caught APEX exception with message: " + aex.getMessage());
- // }
-
-.. container:: paragraph
-
- If this new application is now called with the command line ``-h`` or
- ``--help`` it will print the following help screen:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- test-app v2.0.0-SNAPSHOT - a test app for documenting how to use the CLI utilities
- usage: test-app
- -h,--help prints this help and usage screen
- -m,--model <MODEL-FILE> set the input policy model file
- -v,--version prints the application version
-
-.. container:: paragraph
-
- If this new application is called with the option ``-v`` or
- ``--version`` it will print its version information as:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- test-app 2.0.0-SNAPSHOT
-
-Autoversioning an Application
------------------------------
-
- .. container:: paragraph
-
- The APEX utilities project provides a means to version an
- application automatically towards the APEX version for which it is
- written. This is realized by generating a file called
- ``app-version.txt`` that includes the Maven project version. This
- file is then automatically deployed in the folder ``etc`` of a
- full APEX distribution. The CLI Parser here provides a method to
- access this version for an application.
-
- .. container:: paragraph
-
- First, create a new CLI Parser object, add some options (in the
- example an option for version, but any options will do), then
- parse the command line:
-
- .. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- final CliParser cli = new CliParser();
- cli.addOption(CliOptions.VERSION);
- final CommandLine cmd = cli.parseCli(args);
-
-.. container:: paragraph
-
- Next, we check if the version option was used in the command line and
- print application name and version if it was used:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- // version is an exit option, print version and exit
- if (cmd.hasOption('v') || cmd.hasOption("version")) {
- LOGGER.info("myApp" + " " + cli.getAppVersion());
- return;
- }
-
-.. container:: paragraph
-
- The output will be:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
-
- myApp 2.0.0-SNAPSHOT
-
-.. container:: paragraph
-
- The auto-version information comes from the method call
- ``cli.getAppVersion()`` in line 2 in the example above. The method is
- defined in the ``CliParser`` class as:
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: java
- :number-lines:
-
- public String getAppVersion() {
- return new Scanner(CliParser.class.getResourceAsStream("/app-version.txt"), "UTF-8").useDelimiter("\\A").next();
- }
-
-.. container:: paragraph
-
- The file ``app-version.txt`` is automatically added to an APEX full
- distribution, as described above (for details on this see the POM
- files in the APEX application packaging projects).
-
-.. container::
- :name: footer
-
- .. container::
- :name: footer-text
-
- 2.0.0-SNAPSHOT
- Last updated 2018-09-04 16:04:24 IST
diff --git a/docs/apex/APEX-Install-Guide.rst b/docs/apex/APEX-Install-Guide.rst
deleted file mode 100644
index 0cff1317..00000000
--- a/docs/apex/APEX-Install-Guide.rst
+++ /dev/null
@@ -1,1418 +0,0 @@
-.. This work is licensed under a Creative Commons Attribution 4.0 International License.
-.. http://creativecommons.org/licenses/by/4.0
-
-
-APEX Installation Guide
-***********************
-
-.. contents::
- :depth: 3
-
-Requirements
-^^^^^^^^^^^^
-
- .. container:: sectionbody
-
- .. 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:: sectionbody
-
- .. 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:: bash
- :number-lines:
-
- git clone https://gerrit.onap.org/r/policy/apex-pdp
-
-Build APEX
-^^^^^^^^^^
-
- .. container:: sectionbody
-
- .. 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 built if the ``rpm`` package is installed (Unix). To install ``rpm`` run ``sudo apt-get install rpm``,
- then build APEX.
-
- .. container:: paragraph
-
- Use Maven for a standard build without any tests.
-
- +-------------------------------------------------------+--------------------------------------------------------+
- | Unix, Cygwin | Windows |
- +=======================================================+========================================================+
- | .. container:: | .. container:: |
- | | |
- | .. container:: content | .. container:: content |
- | | |
- | .. code:: bash | .. code:: bash |
- | :number-lines: | :number-lines: |
- | | |
- | >c: | # cd /usr/local/src/apex-pdp |
- | >cd \dev\apex | # mvn clean install -Pdocker -DskipTests |
- | >mvn clean install -Pdocker -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:: bash
- :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.
-
-+----------------------------------------------------------------------------------------------------------------------------+
-| Unix, Cygwin |
-+============================================================================================================================+
-| .. container:: |
-| |
-| .. container:: listingblock |
-| |
-| .. container:: content |
-| |
-| .. code:: bash |
-| :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:: bash |
-| :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:: bash |
- | :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:: bash |
-| :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:: bash
- :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:: bash
- :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 copy 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 save some time. It
- assumes that the APEX 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:: bash | .. code:: bash |
- | :number-lines: | :number-lines: |
- | | |
- | >c: | # cd /usr/local/src/apex |
- | >cd \dev\apex | # mvn clean install -Pdocker -DskipTests |
- | >mvn clean install -Pdocker -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
- built 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 successfully.
-
-.. 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:: bash
- :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:: bash |
-| :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:: bash |
-| :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:: bash
- :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 whose 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 temporarily (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:: bash | .. code:: bash |
- | :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:: bash | .. code:: bash |
- | :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 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 is installed manually or when the log directory is changed
- in the settings (see above).
-
- +------------------------------------------------------------------+-------------------------------------------------------+
- | Unix, Cygwin | Windows |
- +==================================================================+=======================================================+
- | .. container:: | .. container:: |
- | | |
- | .. container:: content | .. container:: content |
- | | |
- | .. code:: bash | .. code:: bash |
- | :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:: sectionbody
-
- .. 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:: bash
- :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:: bash
- :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 changed (default level is ``info``), the output should look
- similar to this (last few lines)
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
- :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 lines, 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. Paste 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:: bash | .. code:: bash |
-| :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:: bash
- :number-lines:
-
- # $APEX_HOME/bin/apexApps.sh rest-editor
-
-.. container:: listingblock
-
- .. container:: content
-
- .. code:: bash
- :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:: bash
- :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:: sectionbody
-
- .. 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 using
- `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 have 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:: sectionbody
-
- .. 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:: bash
- :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
-
-.. 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
-
diff --git a/docs/apex/APEX-Policy-Guide.rst b/docs/apex/APEX-Policy-Guide.rst
index cb2388e0..4b11413f 100644
--- a/docs/apex/APEX-Policy-Guide.rst
+++ b/docs/apex/APEX-Policy-Guide.rst
@@ -1,2107 +1,1792 @@
-.. This work is licensed under a Creative Commons Attribution 4.0 International License.
-.. http://creativecommons.org/licenses/by/4.0
-
+ .. This work is licensed under a Creative Commons Attribution 4.0 International License.
+ .. http://creativecommons.org/licenses/by/4.0
+#################
APEX Policy Guide
-*****************************
+#################
+
.. contents::
- :depth: 3
+ :depth: 5
+******************
APEX Policy Matrix
-^^^^^^^^^^^^^^^^^^
+******************
-APEX Policy Matrix
-------------------
+.. container:: paragraph
- .. container:: paragraph
+ APEX offers a lot of flexibility for defining, deploying, and executing policies. Based on a theoretic model, it
+ supports virtually any policy model and supports translation of legacy policies into the APEX execution format.
+ However, the most important aspect for using APEX is to decide what policy is needed, what underlying policy concepts
+ should be used, and how the decision logic should be realized. Once these aspects are decided, APEX can be used to
+ execute the policies. If the policy evolves, say from a simple decision table to a fully adaptable policy, only the
+ policy definition requires change. APEX supports all of that.
- APEX offers a lot of flexibility for defining, deploying,
- and executing policies. Based on a theoretic model, it
- supports virtually any policy model and supports
- translation of legacy policies into the APEX execution format.
- However, the most important aspect for using APEX is to
- decide what policy is needed, what underlying policy
- concepts should be used, and how the decision logic
- should be realized. Once these aspects are decided, APEX
- can be used to execute the policies. If the policy
- evolves, say from a simple decision table to a fully
- adaptable policy, only the policy definition requires
- change. APEX supports all of that.
+.. container:: paragraph
- .. container:: paragraph
+ The figure below shows a (non-exhaustive) matrix, which will help to decide what policy is required to solve your
+ problem. Read the matrix from left to right choosing one cell in each column.
- The figure below shows a (non-exhaustive) matrix, which
- will help to decide what policy is required to solve your
- problem. Read the matrix from left to right choosing one
- cell in each column.
+.. container:: imageblock
- .. container:: imageblock
+ .. container:: content
- .. container:: content
+ |APEX Policy Matrix|
- |APEX Policy Matrix|
+ .. container:: title
- .. container:: title
-
- Figure 1. APEX Policy Matrix
-
- .. container:: paragraph
-
- The policy can support one of a number of stimuli with an
- associated purpose/model of the policy, for instance:
-
- .. container:: ulist
-
- - Configuration, i.e. what should happen. An example is
- an event that states an intended network configuration
- and the policy should provide the detailed actions for
- it. The policy can be realized for instance as an
- obligation policy, a promise or an intent.
-
- - Report, i.e. something did happen. An example is an
- event about an error or fault and the policy needs to
- repair that problem. The policy would usually be an
- obligation, utility function, or goal policy.
-
- - Monitoring, i.e. something does happen. An example is
- a notification about certain network conditions, to
- which the policy might (or might not) react. The
- policy will mitigate the monitored events or permit
- (deny) related actions as an obligation or
- authorization.
-
- - Analysis, i.e. why did something happen. An example is
- an analytic component sends insights of a situation
- requiring a policy to act on it. The policy can solve
- the problem, escalate it, or delegate it as a refrain
- or delegation policy.
-
- - Prediction, i.e. what will happen next. An example are
- events that a policy uses to predict a future network
- condition. The policy can prevent or enforce the
- prediction as an adaptive policy, a utility function,
- or a goal.
-
- - Feedback, i.e. why did something happen or not happen.
- Similar to analysis, but here the feedback will be in
- the input event and the policy needs to something with
- that information. Feedback can be related to history
- or experience, for instance a previous policy
- execution. The policy needs to be context-aware or be
- a meta-policy.
-
- .. container:: paragraph
-
- Once the purpose of the policy is decided, the next step
- is to look into what context information the policy will
- require to do its job. This can range from very simple to
- a lot of different information, for instance:
-
- .. container:: ulist
-
- - No context, nothing but a trigger event, e.g. a string
- or a number, is required
-
- - Event context, the incoming event provides all
- information (more than a string or number) for the
- policy
-
- - Policy context (read only), the policy has access to
- additional information related to its class but cannot
- change/alter them
-
- - Policy context (read and write), the policy has access
- to additional information related to its class and can
- alter this information (for instance to record
- historic information)
-
- - Global context (read only), the policy has access to
- additional information of any kind but cannot
- change/alter them
-
- - Global context (read and write), the policy the policy
- has access to additional information of any kind and
- can alter this information (for instance to record
- historic information)
+ Figure 1. APEX Policy Matrix
- .. container:: paragraph
+.. container:: paragraph
- The next step is to decide how the policy should do its
- job, i.e. what flavor it has, how many states are needed,
- and how many tasks. There are many possible combinations,
- for instance:
+ The policy can support one of a number of stimuli with an associated purpose/model of the policy, for instance:
- .. container:: ulist
+.. container:: ulist
- - Simple / God: a simple policy with 1 state and 1 task,
- which is doing everything for the decision-making.
- This is the ideal policy for simple situation, e.g.
- deciding on configuration parameters or simple access
- control.
+ - Configuration, i.e. what should happen. An example is an event that states an intended network configuration
+ and the policy should provide the detailed actions for it. The policy can be realized for instance as an
+ obligation policy, a promise or an intent.
- - Simple sequence: a simple policy with a number of
- states each having a single task. This is a very good
- policy for simple decision-making with different
- steps. For instance, a classic action policy (ECA)
- would have 3 states (E, C, and A) with some logic (1
- task) in each state.
-
- - Simple selective: a policy with 1 state but more than
- one task. Here, the appropriate task (and it’s logic)
- will be selected at execution time. This policy is
- very good for dealing with similar (or the same)
- situation in different contexts. For instance, the
- tasks can be related to available external software,
- or to current work load on the compute node, or to
- time of day.
-
- - Selective: any number of states having any number of
- tasks (usually more than 1 task). This is a
- combination of the two policies above, for instance an
- ECA policy with more than one task in E, C, and A.
-
- - Classic directed: a policy with more than one state,
- each having one task, but a non-sequential execution.
- This means that the sequence of the states is not
- pre-defined in the policy (as would be for all cases
- above) but calculated at runtime. This can be good to
- realize decision trees based on contextual
- information.
-
- - Super Adaptive: using the full potential of the APEX
- policy model, states and tasks and state execution are
- fully flexible and calculated at runtime (per policy
- execution). This policy is very close to a general
- programming system (with only a few limitations), but
- can solve very hard problems.
-
- .. container:: paragraph
-
- The final step is to select a response that the policy
- creates. Possible responses have been discussed in the
- literature for a very long time. A few examples are:
-
- .. container:: ulist
-
- - Obligation (deontic for what should happen)
-
- - Authorization (e.g. for rule-based or other access
- control or security systems)
+ - Report, i.e. something did happen. An example is an event about an error or fault and the policy needs to
+ repair that problem. The policy would usually be an obligation, utility function, or goal policy.
- - Intent (instead of providing detailed actions the
- response is an intent statement and a further system
- processes that)
+ - Monitoring, i.e. something does happen. An example is a notification about certain network conditions, to
+ which the policy might (or might not) react. The policy will mitigate the monitored events or permit (deny)
+ related actions as an obligation or authorization.
- - Delegation (hand the problem over to someone else,
- possibly with some information or instructions)
+ - Analysis, i.e. why did something happen. An example is an analytic component sends insights of a situation
+ requiring a policy to act on it. The policy can solve the problem, escalate it, or delegate it as a refrain or
+ delegation policy.
- - Fail / Error (the policy has encountered a problem,
- and reports it)
+ - Prediction, i.e. what will happen next. An example are events that a policy uses to predict a future network
+ condition. The policy can prevent or enforce the prediction as an adaptive policy, a utility function, or a goal.
- - Feedback (why did the policy make a certain decision)
+ - Feedback, i.e. why did something happen or not happen. Similar to analysis, but here the feedback will be in
+ the input event and the policy needs to something with that information. Feedback can be related to history or
+ experience, for instance a previous policy execution. The policy needs to be context-aware or be a meta-policy.
-APEX Policy Model
-^^^^^^^^^^^^^^^^^
+.. container:: paragraph
+
+ Once the purpose of the policy is decided, the next step is to look into what context information the policy will
+ require to do its job. This can range from very simple to a lot of different information, for instance:
+
+.. container:: ulist
+
+ - No context, nothing but a trigger event, e.g. a string or a number, is required
+
+ - Event context, the incoming event provides all information (more than a string or number) for the policy
+
+ - Policy context (read only), the policy has access to additional information related to its class but cannot
+ change/alter them
+
+ - Policy context (read and write), the policy has access to additional information related to its class and can
+ alter this information (for instance to record historic information)
+
+ - Global context (read only), the policy has access to additional information of any kind but cannot
+ change/alter them
+
+ - Global context (read and write), the policy the policy has access to additional information of any kind and
+ can alter this information (for instance to record historic information)
+
+.. container:: paragraph
+
+ The next step is to decide how the policy should do its job, i.e. what flavor it has, how many states are needed,
+ and how many tasks. There are many possible combinations, for instance:
+
+.. container:: ulist
+
+ - Simple / God: a simple policy with 1 state and 1 task, which is doing everything for the decision-making. This
+ is the ideal policy for simple situation, e.g. deciding on configuration parameters or simple access control.
+
+ - Simple sequence: a simple policy with a number of states each having a single task. This is a very good policy
+ for simple decision-making with different steps. For instance, a classic action policy (ECA) would have 3 states
+ (E, C, and A) with some logic (1 task) in each state.
+
+ - Simple selective: a policy with 1 state but more than one task. Here, the appropriate task (and it’s logic)
+ will be selected at execution time. This policy is very good for dealing with similar (or the same) situation in
+ different contexts. For instance, the tasks can be related to available external software, or to current work load
+ on the compute node, or to time of day.
+
+ - Selective: any number of states having any number of tasks (usually more than 1 task). This is a combination
+ of the two policies above, for instance an ECA policy with more than one task in E, C, and A.
+
+ - Classic directed: a policy with more than one state, each having one task, but a non-sequential execution.
+ This means that the sequence of the states is not pre-defined in the policy (as would be for all cases above) but
+ calculated at runtime. This can be good to realize decision trees based on contextual information.
+
+ - Super Adaptive: using the full potential of the APEX policy model, states and tasks and state execution are
+ fully flexible and calculated at runtime (per policy execution). This policy is very close to a general
+ programming system (with only a few limitations), but can solve very hard problems.
+
+.. container:: paragraph
-Introduction
-------------
+ The final step is to select a response that the policy creates. Possible responses have been discussed in the
+ literature for a very long time. A few examples are:
- .. container:: paragraph
+.. container:: ulist
- The APEX policy model is shown in UML notation in the
- figure below. A policy model can be stored in JSON or XML
- format in a file or can be held in a database. The APEX
- editor creates and modifies APEX policy models. APEX
- deployment deploys policy models, and a policy model is
- loaded into APEX engines so that the engines can run the
- policies in the policy model.
+ - Obligation (deontic for what should happen)
- .. container:: paragraph
+ - Authorization (e.g. for rule-based or other access control or security systems)
- The figure shows four different views of the policy
- model:
+ - Intent (instead of providing detailed actions the response is an intent statement and a further system
+ processes that)
- .. container:: ulist
+ - Delegation (hand the problem over to someone else, possibly with some information or instructions)
- - The general model view shows the main parts of a
- policy: state, state output, event, and task. A task
- can also have parameters. Data types can be defined on
- a per-model basis using either standard atomic types
- (such as character, string, numbers) or complex types
- from a policy domain.
+ - Fail / Error (the policy has encountered a problem, and reports it)
- - The logic model view emphasizes how decision-making
- logic is injected into a policy. There are essentially
- three different types of logic: task logic (for
- decision making in a task), task selection logic (to
- select a task if more than one is defined in a state),
- and state finalizer logic (to compute the final output
- event of a state and select an appropriate next state
- from the policy model).
+ - Feedback (why did the policy make a certain decision)
- - The context model view shows how context is injected
- into a policy. States collect all context from their
- tasks. A task can define what context it requires for
- the decision making, i.e. what context the task logic
- will process. Context itself is a collection of items
- (individual context information) with data types.
- Context can be templated.
+*****************
+APEX Policy Model
+*****************
+
+.. container:: paragraph
+
+ The APEX policy model is shown in UML notation in the figure below. A policy model can be stored in JSON or XML
+ format in a file or can be held in a database. The APEX editor creates and modifies APEX policy models. APEX
+ deployment deploys policy models, and a policy model is loaded into APEX engines so that the engines can run the
+ policies in the policy model.
+
+.. container:: paragraph
+
+ The figure shows four different views of the policy model:
+
+.. container:: ulist
- - The event and field model view shows the events in the
- policy model. Tasks define what information they
- consume (input) and produce (output). This information
- is modeled as fields, essentially a key/type tuple in
- the model and a key/type/value triple at execution.
- Events then are collection of fields.
+ - The general model view shows the main parts of a policy: state, state output, event, and task. A task can also
+ have parameters. Data types can be defined on a per-model basis using either standard atomic types (such as
+ character, string, numbers) or complex types from a policy domain.
- .. container:: imageblock
+ - The logic model view emphasizes how decision-making logic is injected into a policy. There are essentially
+ three different types of logic: task logic (for decision making in a task), task selection logic (to select a task
+ if more than one is defined in a state), and state finalizer logic (to compute the final output event of a state
+ and select an appropriate next state from the policy model).
- .. container:: content
+ - The context model view shows how context is injected into a policy. States collect all context from their
+ tasks. A task can define what context it requires for the decision making, i.e. what context the task logic will
+ process. Context itself is a collection of items (individual context information) with data types. Context can be
+ templated.
- |APEX Policy Model for Execution|
+ - The event and field model view shows the events in the policy model. Tasks define what information they
+ consume (input) and produce (output). This information is modeled as fields, essentially a key/type tuple in the
+ model and a key/type/value triple at execution. Events then are collection of fields.
- .. container:: title
+.. container:: imageblock
- Figure 2. APEX Policy Model for Execution
+ .. container:: content
+
+ |APEX Policy Model for Execution|
+
+ .. container:: title
+
+ Figure 2. APEX Policy Model for Execution
Concepts and Keys
-#################
+=================
- .. container:: paragraph
+.. container:: paragraph
- Each element of the policy model is called a
- *concept*. Each *concept* is a subclass of the
- abstract *Concept* class, as shown in the next figure.
- Every concept implements the following abstract
- methods:
+ Each element of the policy model is called a *concept*. Each *concept* is a subclass of the abstract *Concept*
+ class, as shown in the next figure. Every concept implements the following abstract methods:
- .. container:: imageblock
+.. container:: imageblock
- .. container:: content
+ .. container:: content
- |Concepts and Keys|
+ |Concepts and Keys|
- .. container:: title
+ .. container:: title
- Figure 3. Concepts and Keys
+ Figure 3. Concepts and Keys
- .. container:: ulist
+.. container:: ulist
- - ``getKey()`` - gets the unique key for this concept
- instance in the system
+ - ``getKey()`` - gets the unique key for this concept instance in the system
- - ``validate()`` - validates the structure of this
- concept, its sub-concepts and its relationships
+ - ``validate()`` - validates the structure of this concept, its sub-concepts and its relationships
- - ``clean()`` - carries out housekeeping on the
- concept such as trimming strings, remove any
- hanging references
+ - ``clean()`` - carries out housekeeping on the concept such as trimming strings, remove any hanging references
- - ``clone()`` - creates a deep copy of an instance of
- this concept
+ - ``clone()`` - creates a deep copy of an instance of this concept
- - ``equals()`` - checks if two instances of this
- concept are equal
+ - ``equals()`` - checks if two instances of this concept are equal
- - ``toString()`` - returns a string representation of
- the concept
+ - ``toString()`` - returns a string representation of the concept
- - ``hashCode()`` - returns a hash code for the
- concept
+ - ``hashCode()`` - returns a hash code for the concept
- - ``copyTo()`` - carries out a deep copy of one
- instance of the concept to another instance,
- overwriting the target fields.
+ - ``copyTo()`` - carries out a deep copy of one instance of the concept to another instance, overwriting the
+ target fields.
- .. container:: paragraph
+.. container:: paragraph
- All concepts must have a *key*, which uniquely
- identifies a concept instance. The *key* of a subclass
- of an *Concept* must either be an ``ArtifactKey`` or
- an ``ReferenceKey``. Concepts that have a stand-alone
- independent existence such as *Policy*, *Task*, and
- *Event* must have an ``ArtifctKey`` key. Concepts that
- are contained in other concepts, that do not exist as
- stand-alone concepts must have an ``ReferenceKey``
- key. Examples of such concepts are *State* and
- *EventParameter*.
+ All concepts must have a *key*, which uniquely identifies a concept instance. The *key* of a subclass of an *Concept*
+ must either be an ``ArtifactKey`` or an ``ReferenceKey``. Concepts that have a stand-alone independent existence such
+ as *Policy*, *Task*, and *Event* must have an ``ArtifctKey`` key. Concepts that are contained in other concepts, that
+ do not exist as stand-alone concepts must have an ``ReferenceKey`` key. Examples of such concepts are *State* and
+ *EventParameter*.
- .. container:: paragraph
+.. container:: paragraph
- An ``ArticactKey`` has two fields; the *Name* of the
- concept it is the key for and the concept’s *Version*.
- A concept’s name must be unique in a given
- PolicyModel. A concept version is represented using
- the well known *major.minor.path* scheme as used in
- semantic versioning.
+ An ``ArticactKey`` has two fields; the *Name* of the concept it is the key for and the concept’s *Version*. A
+ concept’s name must be unique in a given PolicyModel. A concept version is represented using the well known
+ *major.minor.path* scheme as used in semantic versioning.
- .. container:: paragraph
+.. container:: paragraph
- A ``ReferenceKey`` has three fields. The *UserKeyName*
- and *UserKeyVersion* fields identify the
- ``ArtifactKey`` of the concept in which the concept
- keyed by the ``ReferenceKey`` is contained. The
- *LocalName* field identifies the contained concept
- instance. The *LocalName* must be unique in the
- concepts of a given type contained by a parent.
+ A ``ReferenceKey`` has three fields. The *UserKeyName* and *UserKeyVersion* fields identify the ``ArtifactKey`` of
+ the concept in which the concept keyed by the ``ReferenceKey`` is contained. The *LocalName* field identifies the
+ contained concept instance. The *LocalName* must be unique in the concepts of a given type contained by a parent.
- .. container:: paragraph
+.. container:: paragraph
- For example, a policy called ``SalesPolicy`` with a
- Version of ``1.12.4`` has a state called ``Decide``.
- The ``Decide`` state is linked to the ``SalesPolicy``
- with a ``ReferenceKey`` with fields *UserKeyName* of
- ``SalesPolicy``, *UserKeyVersion* of ``1.12.4``, and
- *LocalName* of ``Decide``. There must not be another
- state called ``Decide`` in the policy ``SalesPolicy``.
- However, there may well be a state called ``Decide``
- in some other policy called ``PurchasingPolicy``.
+ For example, a policy called ``SalesPolicy`` with a Version of ``1.12.4`` has a state called ``Decide``. The
+ ``Decide`` state is linked to the ``SalesPolicy`` with a ``ReferenceKey`` with fields *UserKeyName* of
+ ``SalesPolicy``, *UserKeyVersion* of ``1.12.4``, and *LocalName* of ``Decide``. There must not be another state
+ called ``Decide`` in the policy ``SalesPolicy``. However, there may well be a state called ``Decide`` in some other
+ policy called ``PurchasingPolicy``.
- .. container:: paragraph
+.. container:: paragraph
- Each concept in the model is also a JPA (`Java
- Persistence
- API <https://en.wikipedia.org/wiki/Java_Persistence_API>`__)
- Entity. This means that every concept can be
- individually persisted or the entire model can be
- persisted en-bloc to any persistence mechanism using
- an JPA framework such as
- `Hibernate <http://hibernate.org/>`__ or
- `EclipseLink <http://www.eclipse.org/eclipselink/>`__.
+ Each concept in the model is also a JPA
+ (`Java Persistence API <https://en.wikipedia.org/wiki/Java_Persistence_API>`__) Entity. This means that every concept
+ can be individually persisted or the entire model can be persisted en-bloc to any persistence mechanism using an JPA
+ framework such as `Hibernate <http://hibernate.org/>`__ or `EclipseLink <http://www.eclipse.org/eclipselink/>`__.
Concept: PolicyModel
-####################
+====================
- .. container:: paragraph
+.. container:: paragraph
- The *PolicyModel* concept is a container that holds
- the definition of a set of policies and their
- associated events, context maps, and tasks. A
- *PolicyModel* is implemented as four maps for
- policies, events, context maps, and tasks. Each map is
- indexed by the key of the policy, event, context map,
- or task. Any non-empty policy model must have at least
- one entry in its policy, event, and task map because
- all policies must have at least one input and output
- event and must execute at least one task.
+ The *PolicyModel* concept is a container that holds the definition of a set of policies and their associated events,
+ context maps, and tasks. A *PolicyModel* is implemented as four maps for policies, events, context maps, and tasks.
+ Each map is indexed by the key of the policy, event, context map, or task. Any non-empty policy model must have at
+ least one entry in its policy, event, and task map because all policies must have at least one input and output event
+ and must execute at least one task.
- .. container:: paragraph
+.. container:: paragraph
- A *PolicyModel* concept is keyed with an
- ``ArtifactKey key``. Because a *PolicyModel* is an
- ``AxConcept``, calling the ``validate()`` method on a
- policy model validates the concepts, structure, and
- relationships of the entire policy model.
+ A *PolicyModel* concept is keyed with an ``ArtifactKey key``. Because a *PolicyModel* is an ``AxConcept``, calling
+ the ``validate()`` method on a policy model validates the concepts, structure, and relationships of the entire policy
+ model.
Concept: DataType
-#################
+=================
+
+.. container:: paragraph
- .. container:: paragraph
-
- Data types are tightly controlled in APEX in order to
- provide a very high degree of consistency in policies
- and to facilitate tracking of changes to context as
- policies execute. All context is modeled as a
- *DataType* concept. Each DataType concept instance is
- keyed with an ``ArtifactKey`` key. The DataType field
- identifies the Java class of objects that is used to
- represent concept instances that use this data type.
- All context has a *DataType*; incoming and outgoing
- context is represented by *EventField* concepts and
- all other context is represented by *ContextItem*
- concepts.
+ Data types are tightly controlled in APEX in order to provide a very high degree of consistency in policies and to
+ facilitate tracking of changes to context as policies execute. All context is modeled as a *DataType* concept. Each
+ DataType concept instance is keyed with an ``ArtifactKey`` key. The DataType field identifies the Java class of
+ objects that is used to represent concept instances that use this data type. All context has a *DataType*; incoming
+ and outgoing context is represented by *EventField* concepts and all other context is represented by *ContextItem*
+ concepts.
Concept: Event
-##############
+==============
- .. container:: paragraph
+.. container:: paragraph
- An *Event* defines the structure of a message that
- passes into or out of an APEX engine or that passes
- between two states in an APEX engine. APEX supports
- message reception and sending in many formats and all
- messages are translated into an *Event* prior to
- processing by an APEX engine. Event concepts are keyed
- with an ``ArtifactKey`` key. The parameters of an
- event are held as a map of *EventField* concept
- instances with each parameter indexed by the
- *LocalName* of its ``ReferenceKey``. An *Event* has
- three fields:
+ An *Event* defines the structure of a message that passes into or out of an APEX engine or that passes between two
+ states in an APEX engine. APEX supports message reception and sending in many formats and all messages are translated
+ into an *Event* prior to processing by an APEX engine. Event concepts are keyed with an ``ArtifactKey`` key. The
+ parameters of an event are held as a map of *EventField* concept instances with each parameter indexed by the
+ *LocalName* of its ``ReferenceKey``. An *Event* has three fields:
- .. container:: ulist
+.. container:: ulist
- - The *NameSpace* identifies the domain of
- application of the event
+ - The *NameSpace* identifies the domain of application of the event
- - The *Source* of the event identifies the system
- that emitted the event
+ - The *Source* of the event identifies the system that emitted the event
- - The *Target* of the event identifies the system
- that the event was sent to
+ - The *Target* of the event identifies the system that the event was sent to
- .. container:: paragraph
+.. container:: paragraph
- A *PolicyModel* contains a map of all the events known
- to a given policy model. Although an empty model may
- have no events in its event map, any sane policy model
- must have at least one *Event* defined.
+ A *PolicyModel* contains a map of all the events known to a given policy model. Although an empty model may have no
+ events in its event map, any sane policy model must have at least one *Event* defined.
Concept: EventField
-###################
+===================
- .. container:: paragraph
+.. container:: paragraph
- The incoming context and outgoing context of an event
- are the fields of the event. Each field representing a
- single piece of incoming or outgoing context. Each
- field of an *Event* is represented by an instance of
- the *EventField* concept. Each *EventField* concept
- instance in an event is keyed with a ``ReferenceKey``
- key, which references the event. The *LocalName* field
- of the ``ReferenceKey`` holds the name of the field A
- reference to a *DataType* concept defines the data
- type that values of this parameter have at run time.
+ The incoming context and outgoing context of an event are the fields of the event. Each field representing a single
+ piece of incoming or outgoing context. Each field of an *Event* is represented by an instance of the *EventField*
+ concept. Each *EventField* concept instance in an event is keyed with a ``ReferenceKey`` key, which references the
+ event. The *LocalName* field of the ``ReferenceKey`` holds the name of the field A reference to a *DataType* concept
+ defines the data type that values of this parameter have at run time.
Concept: ContextMap
-###################
-
- .. container:: paragraph
-
- The set of context that is available for use by the
- policies of a *PolicyModel* is defined as *ContextMap*
- concept instances. The *PolicyModel* holds a map of
- all the *ContextMap* definitions. A *ContextMap* is
- itself a container for a group of related context
- items, each of which is represented by a *ContextItem*
- concept instance. *ContextMap* concepts are keyed with
- an ``ArtifactKey`` key. A developer can use the APEX
- Policy Editor to create context maps for their
- application domain.
-
- .. container:: paragraph
-
- A *ContextMap* uses a map to hold the context items.
- The ContextItem concept instances in the map are
- indexed by the *LocalName* of their ``ReferenceKey``.
-
- .. container:: paragraph
-
- The *ContextMapType* field of a *ContextMap* defines
- the type of a context map. The type can have either of
- two values:
-
- .. container:: ulist
-
- - A *BAG* context map is a context map with fixed
- content. Each possible context item in the context
- map is defined at design time and is held in the
- *ContextMap* context instance as *ContextItem*
- concept definitions and only the values of the
- context items in the context map can be changed at
- run time. The context items in a *BAG* context map
- have mixed types and distinct *ContextItem* concept
- instances of the same type can be defined. A *BAG*
- context map is convenient for defining a group of
- context items that are diverse but are related by
- domain, such as the characteristics of a device. A
- fully defined *BAG* context map has a fully
- populated *ContextItem* map but its
- *ContextItemTemplate* reference is not defined.
-
- - A *SAMETYPE* context map is used to represent a
- group of *ContextItem* instances of the same type.
- Unlike a *BAG* context map, the *ContextItem*
- concept instances of a *SAMETYPE* context map can
- be added, modified, and deleted at runtime. All
- *ContextItem* concept instances in a *SAMETYPE*
- context map must be of the same type, and that
- context item is defined as a single
- *ContextItemTemplate* concept instances at design
- time. At run time, the *ContextItemTemplate*
- definition is used to create new *ContextItem*
- concept instances for the context map on demand. A
- fully defined *SAMETYPE context map has an empty
- ContextItem map and its ContextItemTemplate\_*
- reference is defined.
-
- .. container:: paragraph
-
- The *Scope* of a *ContextMap* defines the range of
- applicability of a context map in APEX. The following
- scopes of applicability are defined:
-
- .. container:: ulist
-
- - *EPHEMERAL* scope means that the context map is
- owned, used, and modified by a single application,
- but the context map only exists while that
- application is running
-
- - *APPLICATION* scope specifies that the context map
- is owned, used, and modified by a single
- application, the context map is persistent
-
- - *GLOBAL* scope specifies that the context map is
- globally owned and is used and modified by any
- application, the context map is persistent
-
- - *EXTERNAL* scope specifies that the context map is
- owned by an external system and may be used in a
- read-only manner by any application, the context
- map is persistent
-
- .. container:: paragraph
-
- A much more sophisticated scoping mechanism for
- context maps is envisaged for Apex in future work. In
- such a mechanism, the scope of a context map would
- work somewhat like the way roles work in security
- authentication systems.
+===================
+
+.. container:: paragraph
+
+ The set of context that is available for use by the policies of a *PolicyModel* is defined as *ContextMap* concept
+ instances. The *PolicyModel* holds a map of all the *ContextMap* definitions. A *ContextMap* is itself a container
+ for a group of related context items, each of which is represented by a *ContextItem* concept instance. *ContextMap*
+ concepts are keyed with an ``ArtifactKey`` key. A developer can use the APEX Policy Editor to create context maps for
+ their application domain.
+
+.. container:: paragraph
+
+ A *ContextMap* uses a map to hold the context items. The ContextItem concept instances in the map are indexed by the
+ *LocalName* of their ``ReferenceKey``.
+
+.. container:: paragraph
+
+ The *ContextMapType* field of a *ContextMap* defines the type of a context map. The type can have either of two
+ values:
+
+.. container:: ulist
+
+ - A *BAG* context map is a context map with fixed content. Each possible context item in the context map is
+ defined at design time and is held in the *ContextMap* context instance as *ContextItem* concept definitions and
+ only the values of the context items in the context map can be changed at run time. The context items in a *BAG*
+ context map have mixed types and distinct *ContextItem* concept instances of the same type can be defined. A *BAG*
+ context map is convenient for defining a group of context items that are diverse but are related by domain, such as
+ the characteristics of a device. A fully defined *BAG* context map has a fully populated *ContextItem* map but its
+ *ContextItemTemplate* reference is not defined.
+
+ - A *SAMETYPE* context map is used to represent a group of *ContextItem* instances of the same type. Unlike a
+ *BAG* context map, the *ContextItem* concept instances of a *SAMETYPE* context map can be added, modified, and
+ deleted at runtime. All *ContextItem* concept instances in a *SAMETYPE* context map must be of the same type, and
+ that context item is defined as a single *ContextItemTemplate* concept instances at design time. At run time, the
+ *ContextItemTemplate* definition is used to create new *ContextItem* concept instances for the context map on
+ demand. A fully defined *SAMETYPE context map has an empty ContextItem map and its ContextItemTemplate\_*
+ reference is defined.
+
+.. container:: paragraph
+
+ The *Scope* of a *ContextMap* defines the range of applicability of a context map in APEX. The following scopes of
+ applicability are defined:
+
+.. container:: ulist
+
+ - *EPHEMERAL* scope means that the context map is owned, used, and modified by a single application but the
+ context map only exists while that application is running
+
+ - *APPLICATION* scope specifies that the context map is owned, used, and modified by a single application, the
+ context map is persistent
+
+ - *GLOBAL* scope specifies that the context map is globally owned and is used and modified by any application,
+ the context map is persistent
+
+ - *EXTERNAL* scope specifies that the context map is owned by an external system and may be used in a read-only
+ manner by any application, the context map is persistent
+
+.. container:: paragraph
+
+ A much more sophisticated scoping mechanism for context maps is envisaged for Apex in future work. In such a
+ mechanism, the scope of a context map would work somewhat like the way roles work in security authentication systems.
Concept: ContextItem
-####################
-
- .. container:: paragraph
-
- Each piece of context in a *ContextMap* is represented
- by an instance of the *ContextItem* concept. Each
- *ContextItem* concept instance in a context map keyed
- with a ``ReferenceKey`` key, which references the
- context map of the context item. The *LocalName* field
- of the ``ReferenceKey`` holds the name of the context
- item in the context map A reference to a *DataType*
- concept defines the data type that values of this
- context item have at run time. The *WritableFlag*
- indicates if the context item is read only or
- read-write at run time.
+====================
+
+.. container:: paragraph
+
+ Each piece of context in a *ContextMap* is represented by an instance of the *ContextItem* concept. Each
+ *ContextItem* concept instance in a context map keyed with a ``ReferenceKey`` key, which references the context map
+ of the context item. The *LocalName* field of the ``ReferenceKey`` holds the name of the context item in the context
+ map A reference to a *DataType* concept defines the data type that values of this context item have at run time. The
+ *WritableFlag* indicates if the context item is read only or read-write at run time.
Concept: ContextItemTemplate
-############################
-
- .. container:: paragraph
-
- In a *SAMETYPE* *ContextMap*, the
- *ContextItemTemplate* definition provides a template
- for the *ContextItem* instances that will be created
- on the context map at run time. Each *ContextItem*
- concept instance in the context map is created using
- the *ContextItemTemplate* template. It is keyed with a
- ``ReferenceKey`` key, which references the context map
- of the context item. The *LocalName* field of the
- ``ReferenceKey``, supplied by the creator of the
- context item at run time, holds the name of the
- context item in the context map. A reference to a
- *DataType* concept defines the data type that values
- of this context item have at run time. The
- *WritableFlag* indicates if the context item is read
- only or read-write at run time.
+============================
+
+.. container:: paragraph
+
+ In a *SAMETYPE* *ContextMap*, the *ContextItemTemplate* definition provides a template for the *ContextItem*
+ instances that will be created on the context map at run time. Each *ContextItem* concept instance in the context map
+ is created using the *ContextItemTemplate* template. It is keyed with a ``ReferenceKey`` key, which references the
+ context map of the context item. The *LocalName* field of the ``ReferenceKey``, supplied by the creator of the
+ context item at run time, holds the name of the context item in the context map. A reference to a *DataType* concept
+ defines the data type that values of this context item have at run time. The *WritableFlag* indicates if the context
+ item is read only or read-write at run time.
Concept: Task
-#############
-
- .. container:: paragraph
-
- The smallest unit of logic in a policy is a *Task*. A
- task encapsulates a single atomic unit of logic, and
- is designed to be a single indivisible unit of
- execution. A task may be invoked by a single policy or
- by many policies. A task has a single trigger event,
- which is sent to the task when it is invoked. Tasks
- emit one or more outgoing events, which carry the
- result of the task execution. Tasks may use or modify
- context as they execute.
-
- .. container:: paragraph
-
- The Task concept definition captures the definition of
- an APEX task. Task concepts are keyed with an
- ``ArtifactKey`` key. The Trigger of the task is a
- reference to the *Event* concept that triggers the
- task. The *OutgoingEvents* of a task are a set of
- references to *Event* concepts that may be emitted by
- the task.
-
- .. container:: paragraph
-
- All tasks have logic, some code that is programmed to
- execute the work of the task. The *Logic* concept of
- the task holds the definition of that logic.
-
- .. container:: paragraph
-
- The *Task* definition holds a set of *ContextItem* and
- *ContextItemTemplate* context items that the task is
- allow to access, as defined by the task developer at
- design time. The type of access (read-only or read
- write) that a task has is determined by the
- *WritableFlag* flag on the individual context item
- definitions. At run time, a task may only access the
- context items specified in its context item set, the
- APEX engine makes only the context items in the task
- context item set is available to the task.
-
- .. container:: paragraph
-
- A task can be configured with startup parameters. The
- set of parameters that can be configured on a task are
- defined as a set of *TaskParameter* concept
- definitions.
+=============
+
+.. container:: paragraph
+
+ The smallest unit of logic in a policy is a *Task*. A task encapsulates a single atomic unit of logic, and is
+ designed to be a single indivisible unit of execution. A task may be invoked by a single policy or by many policies.
+ A task has a single trigger event, which is sent to the task when it is invoked. Tasks emit one or more outgoing
+ events, which carry the result of the task execution. Tasks may use or modify context as they execute.
+
+.. container:: paragraph
+
+ The Task concept definition captures the definition of an APEX task. Task concepts are keyed with an ``ArtifactKey``
+ key. The Trigger of the task is a reference to the *Event* concept that triggers the task. The *OutgoingEvents* of a
+ task are a set of references to *Event* concepts that may be emitted by the task.
+
+.. container:: paragraph
+
+ All tasks have logic, some code that is programmed to execute the work of the task. The *Logic* concept of the task
+ holds the definition of that logic.
+
+.. container:: paragraph
+
+ The *Task* definition holds a set of *ContextItem* and *ContextItemTemplate* context items that the task is allow to
+ access, as defined by the task developer at design time. The type of access (read-only or read write) that a task has
+ is determined by the *WritableFlag* flag on the individual context item definitions. At run time, a task may only
+ access the context items specified in its context item set, the APEX engine makes only the context items in the task
+ context item set is available to the task.
+
+.. container:: paragraph
+
+ A task can be configured with startup parameters. The set of parameters that can be configured on a task are defined
+ as a set of *TaskParameter* concept definitions.
Concept: TaskParameter
-######################
+======================
- .. container:: paragraph
+.. container:: paragraph
- Each configuration parameter of a task are represented
- as a *Taskparameter* concept keyed with a
- ``ReferenceKey`` key, which references the task. The
- *LocalName* field of the ``ReferenceKey`` holds the
- name of the parameter. The *DefaultValue* field
- defines the default value that the task parameter is
- set to. The value of *TaskParameter* instances can be
- overridden at deployment time by specifying their
- values in the configuration information passed to APEX
- engines.
+ Each configuration parameter of a task are represented as a *Taskparameter* concept keyed with a ``ReferenceKey``
+ key, which references the task. The *LocalName* field of the ``ReferenceKey`` holds the name of the parameter. The
+ *DefaultValue* field defines the default value that the task parameter is set to. The value of *TaskParameter*
+ instances can be overridden at deployment time by specifying their values in the configuration information passed to
+ APEX engines.
- .. container:: paragraph
+.. container:: paragraph
- The *taskParameters* field is specified under *engineParameters*
- in the ApexConfig. It can contain one or more task parameters, where each
- item can contain the parameter key, value as well as the taskId to which it is associated.
- If the taskId is not specified, then the parameters are added to all tasks.
+ The *taskParameters* field is specified under *engineParameters* in the ApexConfig. It can contain one or more task
+ parameters, where each item can contain the parameter key, value as well as the taskId to which it is associated. If
+ the taskId is not specified, then the parameters are added to all tasks.
Concept: Logic
-##############
-
- .. container:: paragraph
-
- The *Logic* concept instance holds the actual
- programmed task logic for a task defined in a *Task*
- concept or the programmed task selection logic for a
- state defined in a *State* concept. It is keyed with a
- ``ReferenceKey`` key, which references the task or
- state that owns the logic. The *LocalName* field of
- the Logic concept is the name of the logic.
-
- .. container:: paragraph
-
- The *LogicCode* field of a Logic concept definition is
- a string that holds the program code that is to be
- executed at run time. The *LogicType* field defines
- the language of the code. The standard values are the
- logic languages supported by APEX:
- `JAVASCRIPT <https://en.wikipedia.org/wiki/JavaScript>`__,
- `JAVA <https://java.com/en/>`__,
- `JYTHON <http://www.jython.org/>`__,
- `JRUBY <http://jruby.org/>`__, or
- `MVEL <https://en.wikibooks.org/wiki/Transwiki:MVEL_Language_Guide>`__.
-
- .. container:: paragraph
-
- The APEX engine uses the *LogicType* field value to
- decide which language interpreter to use for a task
- and then sends the logic defined in the *LogicCode*
- field to that interpreter.
+==============
+
+.. container:: paragraph
+
+ The *Logic* concept instance holds the actual programmed task logic for a task defined in a *Task* concept or the
+ programmed task selection logic for a state defined in a *State* concept. It is keyed with a ``ReferenceKey`` key,
+ which references the task or state that owns the logic. The *LocalName* field of the Logic concept is the name of the
+ logic.
+
+.. container:: paragraph
+
+ The *LogicCode* field of a Logic concept definition is a string that holds the program code that is to be executed
+ at run time. The *LogicType* field defines the language of the code. The standard values are the logic languages
+ supported by APEX: `JAVASCRIPT <https://en.wikipedia.org/wiki/JavaScript>`__, `JAVA <https://java.com/en/>`__,
+ `JYTHON <http://www.jython.org/>`__, `JRUBY <http://jruby.org/>`__, or
+ `MVEL <https://en.wikibooks.org/wiki/Transwiki:MVEL_Language_Guide>`__.
+
+.. container:: paragraph
+
+ The APEX engine uses the *LogicType* field value to decide which language interpreter to use for a task and then
+ sends the logic defined in the *LogicCode* field to that interpreter.
Concept: Policy
-###############
-
- .. container:: paragraph
-
- The *Policy* concept defines a policy in APEX. The
- definition is rather straightforward. A policy is made
- up of a set of states with the flavor of the policy
- determining the structure of the policy states and the
- first state defining what state in the policy executes
- first. *Policy* concepts are keyed with an
- ``ArtifactKey`` key.
-
- .. container:: paragraph
-
- The *PolicyFlavour* of a *Policy* concept specifies
- the structure that will be used for the states in the
- policy. A number of commonly used policy patterns are
- supported as APEX policy flavors. The standard policy
- flavors are:
-
- .. container:: ulist
-
- - The *MEDA* flavor supports policies written to the
- `MEDA policy
- pattern <https://www.researchgate.net/publication/282576518_Dynamically_Adaptive_Policies_for_Dynamically_Adaptive_Telecommunications_Networks>`__
- and require a sequence of four states: namely
- *Match*, *Establish*, *Decide* and *Act*.
-
- - The *OODA* flavor supports policies written to the
- `OODA loop
- pattern <https://en.wikipedia.org/wiki/OODA_loop>`__
- and require a sequence of four states: namely
- *Observe*, *Orient*, *Decide* and *Act*.
-
- - The *ECA* flavor supports policies written to the
- `ECA active rule
- pattern <https://en.wikipedia.org/wiki/Event_condition_action>`__
- and require a sequence of three states: namely
- *Event*, *Condition* and *Action*
-
- - The *XACML* flavor supports policies written in
- `XACML <https://en.wikipedia.org/wiki/XACML>`__ and
- require a single state: namely *XACML*
-
- - The *FREEFORM* flavor supports policies written in
- an arbitrary style. A user can define a *FREEFORM*
- policy as an arbitrarily long chain of states.
-
- .. container:: paragraph
-
- The *FirstState* field of a *Policy* definition is the
- starting point for execution of a policy. Therefore,
- the trigger event of the state referenced in the
- *FirstState* field is also the trigger event for the
- entire policy.
+===============
+
+.. container:: paragraph
+
+ The *Policy* concept defines a policy in APEX. The definition is rather straightforward. A policy is made up of a
+ set of states with the flavor of the policy determining the structure of the policy states and the first state
+ defining what state in the policy executes first. *Policy* concepts are keyed with an ``ArtifactKey`` key.
+
+.. container:: paragraph
+
+ The *PolicyFlavour* of a *Policy* concept specifies the structure that will be used for the states in the policy. A
+ number of commonly used policy patterns are supported as APEX policy flavors. The standard policy flavors are:
+
+.. container:: ulist
+
+ - The *MEDA* flavor supports policies written to the
+ `MEDA policy pattern <https://www.researchgate.net/publication/282576518_Dynamically_Adaptive_Policies_for_Dynamically_Adaptive_Telecommunications_Networks>`__
+ and require a sequence of four states: namely *Match*, *Establish*, *Decide* and *Act*.
+
+ - The *OODA* flavor supports policies written to the
+ `OODA loop pattern <https://en.wikipedia.org/wiki/OODA_loop>`__ and require a sequence of four states: namely
+ *Observe*, *Orient*, *Decide* and *Act*.
+
+ - The *ECA* flavor supports policies written to the
+ `ECA active rule pattern <https://en.wikipedia.org/wiki/Event_condition_action>`__ and require a sequence of three
+ states: namely *Event*, *Condition* and *Action*
+
+ - The *XACML* flavor supports policies written in `XACML <https://en.wikipedia.org/wiki/XACML>`__ and require a
+ single state: namely *XACML*
+
+ - The *FREEFORM* flavor supports policies written in an arbitrary style. A user can define a *FREEFORM* policy
+ as an arbitrarily long chain of states.
+
+.. container:: paragraph
+
+ The *FirstState* field of a *Policy* definition is the starting point for execution of a policy. Therefore, the
+ trigger event of the state referenced in the *FirstState* field is also the trigger event for the entire policy.
Concept: State
-##############
-
- .. container:: paragraph
-
- The *State* concept represents a phase or a stage in a
- policy, with a policy being composed of a series of
- states. Each state has at least one but may have many
- tasks and, on each run of execution, a state executes
- one and only one of its tasks. If a state has more
- than one task, then its task selection logic is used
- to select which task to execute. Task selection logic
- is programmable logic provided by the state designer.
- That logic can use incoming, policy, global, and
- external context to select which task best
- accomplishes the purpose of the state in a give
- situation if more than one task has been specified on
- a state. A state calls one and only one task when it
- is executed.
-
- .. container:: paragraph
-
- Each state is triggered by an event, which means that
- all tasks of a state must also be triggered by that
- same event. The set of output events for a state is
- the union of all output events from all tasks for that
- task. In practice at the moment, because a state can
- only have a single input event, a state that is not
- the final state of a policy may only output a single
- event and all tasks of that state may also only output
- that single event. In future work, the concept of
- having a less restrictive trigger pattern will be
- examined.
-
- .. container:: paragraph
-
- A *State* concept is keyed with a ``ReferenceKey``
- key, which references the *Policy* concept that owns
- the state. The *LocalName* field of the
- ``ReferenceKey`` holds the name of the state. As a
- state is part of a chain of states, the *NextState*
- field of a state holds the ``ReferenceKey`` key of the
- state in the policy to execute after this state.
-
- .. container:: paragraph
-
- The *Trigger* field of a state holds the
- ``ArtifactKey`` of the event that triggers this state.
- The *OutgoingEvents* field holds the ``ArtifactKey``
- references of all possible events that may be output
- from the state. This is a set that is the union of all
- output events of all tasks of the state.
-
- .. container:: paragraph
-
- The *Task* concepts that hold the definitions of the
- task for the state are held as a set of
- ``ArtifactKey`` references in the state. The
- *DefaultTask* field holds a reference to the default
- task for the state, a task that is executed if no task
- selection logic is specified. If the state has only
- one task, that task is the default task.
-
- .. container:: paragraph
-
- The *Logic* concept referenced by a state holds the
- task selection logic for a state. The task selection
- logic uses the incoming context (parameters of the
- incoming event) and other context to determine the
- best task to use to execute its goals. The state holds
- a set of references to *ContextItem* and
- *ContextItemTemplate* definitions for the context used
- by its task selection logic.
+==============
+
+.. container:: paragraph
+
+ The *State* concept represents a phase or a stage in a policy, with a policy being composed of a series of states.
+ Each state has at least one but may have many tasks and, on each run of execution, a state executes one and only one
+ of its tasks. If a state has more than one task, then its task selection logic is used to select which task to
+ execute. Task selection logic is programmable logic provided by the state designer. That logic can use incoming,
+ policy, global, and external context to select which task best accomplishes the purpose of the state in a give
+ situation if more than one task has been specified on a state. A state calls one and only one task when it is
+ executed.
+
+.. container:: paragraph
+
+ Each state is triggered by an event, which means that all tasks of a state must also be triggered by that same
+ event. The set of output events for a state is the union of all output events from all tasks for that task. In
+ practice at the moment, because a state can only have a single input event, a state that is not the final state of a
+ policy may only output a single event and all tasks of that state may also only output that single event. In future
+ work, the concept of having a less restrictive trigger pattern will be examined.
+
+.. container:: paragraph
+
+ A *State* concept is keyed with a ``ReferenceKey`` key, which references the *Policy* concept that owns the state.
+ The *LocalName* field of the ``ReferenceKey`` holds the name of the state. As a state is part of a chain of states,
+ the *NextState* field of a state holds the ``ReferenceKey`` key of the state in the policy to execute after this
+ state.
+
+.. container:: paragraph
+
+ The *Trigger* field of a state holds the ``ArtifactKey`` of the event that triggers this state. The *OutgoingEvents*
+ field holds the ``ArtifactKey`` references of all possible events that may be output from the state. This is a set
+ that is the union of all output events of all tasks of the state.
+
+.. container:: paragraph
+ The *Task* concepts that hold the definitions of the task for the state are held as a set of ``ArtifactKey``
+ references in the state. The *DefaultTask* field holds a reference to the default task for the state, a task that is
+ executed if no task selection logic is specified. If the state has only one task, that task is the default task.
+
+.. container:: paragraph
+
+ The *Logic* concept referenced by a state holds the task selection logic for a state. The task selection logic uses
+ the incoming context (parameters of the incoming event) and other context to determine the best task to use to
+ execute its goals. The state holds a set of references to *ContextItem* and *ContextItemTemplate* definitions for the
+ context used by its task selection logic.
+
+*************
Writing Logic
-^^^^^^^^^^^^^
+*************
Writing APEX Task Logic
------------------------
-
- .. container:: paragraph
-
- Task logic specifies the behavior of an Apex Task. This
- logic can be specified in a number of ways, exploiting
- Apex’s plug-in architecture to support a range of logic
- executors. In Apex scripted Task Logic can be written in
- any of these languages:
-
- .. container:: ulist
-
- - ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__,
-
- - ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__,
-
- - ```JRuby`` <https://en.wikipedia.org/wiki/JRuby>`__ or
-
- - ```Jython`` <https://en.wikipedia.org/wiki/Jython>`__.
-
- .. container:: paragraph
-
- These languages were chosen because the scripts can be
- compiled into Java bytecode at runtime and then
- efficiently executed natively in the JVM. Task Logic an
- also be written directly in Java but needs to be
- compiled, with the resulting classes added to the
- classpath. There are also a number of other Task Logic
- types (e.g. Fuzzy Logic), but these are not supported as
- yet. This guide will focus on the scripted Task Logic
- approaches, with MVEL and JavaScript being our favorite
- languages. In particular this guide will focus on the
- Apex aspects of the scripts. However, this guide does not
- attempt to teach you about the scripting languages
- themselves …​ that is up to you!
-
- .. tip::
- JVM-based scripting languages
- For more more information on scripting for the Java platform see: https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/index.html
-
- .. note::
- What do Tasks do?
- The function of an Apex Task is to provide the logic that can be executed for an Apex State as one of the steps in
- an Apex Policy. Each task receives some *incoming fields*, executes some logic (e.g: make a decision based on
- *shared state* or *context*, *incoming fields*, *external context*, etc.), perhaps set some *shared state* or
- *context* and then emits *outgoing fields*. The state that uses the task is responsible for extracting the
- *incoming fields* from the state input event. The state also has an *output mapper* associated with the task, and
- this *output mapper* is responsible for mapping the *outgoing fields* from the task into an appropriate
- output event for the state.
-
- .. container:: paragraph
-
- First lets start with a sample task, drawn from the "My
- First Apex Policy" example: The task "MorningBoozeCheck"
- from the "My First Apex Policy" example is available in
- both MVEL and JavaScript:
-
- .. container:: listingblock
-
- .. container:: title
-
- Javascript code for the ``MorningBoozeCheck`` task
-
- .. container:: content
-
- .. code:: javascript
- :number-lines:
-
- /*
- * ============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:: listingblock
-
- .. container:: title
-
- MVEL code for the ``MorningBoozeCheck`` task
-
- .. container:: content
-
- .. code:: javascript
- :number-lines:
-
- /*
- * ============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:: paragraph
-
- The role of the task in this simple example is to copy
- the values in the incoming fields into the outgoing
- fields, then examine the values in some incoming fields
- (``item_id`` and ``time``), then set the values in some
- other outgoing fields (``authorised`` and ``message``).
-
- .. container:: paragraph
-
- Both MVEL and JavaScript like most JVM-based scripting
- languages can use standard Java libraries to perform
- complex tasks. Towards the top of the scripts you will
- see how to import Java classes and packages to be used
- directly in the logic. Another thing to notice is that
- Task Logic should return a ``java.lang.Boolean`` value
- ``true`` if the logic executed correctly. If the logic
- fails for some reason then ``false`` can be returned, but
- this will cause the policy invoking this task will fail
- and exit.
-
- .. note::
- How to return a value from task logic
- Some languages explicitly support returning values from the script (e.g. MVEL and JRuby) using an explicit
- return statement (e.g. ``return true``), other languages do not (e.g. JavaScript and Jython). For
- languages that do not support the ``return`` statement, a special field called ``returnValue`` must be
- created to hold the result of the task logic operation (i.e. assign a ``java.lang.Boolean``
- value to the ``returnValue`` field before completing the task).
- Also, in MVEL if there is no explicit return statement then the return value of the last executed statement will return
- (e.g. the statement a=(1+2) will return the value 3).
-
- .. container:: paragraph
-
- Besides these imported classes and normal language
- features Apex provides some natively available parameters
- and functions that can be used directly. At run-time
- these parameters are populated by the Apex execution
- environment and made natively available to logic scripts
- each time the logic script is invoked. (These can be
- accessed using the ``executor`` keyword for most
- languages, or can be accessed directly without the
- ``executor`` keyword in MVEL):
-
- Table 1. The ``executor`` Fields / Methods
-
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| Name | Type | Java type | Description |
-+============+=============+================================+=====================================================================================+
-| inFields | Fields | java.util.Map <String,Object> | .. container:: paragraph |
-| | | | |
-| | | | The incoming task fields. This is implemented as a standard Java |
-| | | | Java (unmodifiable) Map |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | executor.logger.debug("Incoming fields: " |
-| | | | +executor.inFields.entrySet()); |
-| | | | var item_id = executor.incomingFields["item_ID"]; |
-| | | | if (item_id >=1000) { ... } |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| outFields | Fields | java.util.Map <String,Object> | .. container:: paragraph |
-| | | | |
-| | | | The outgoing task fields. This is implemented as a standard initially empty Java |
-| | | | (modifiable) Map. To create a new schema-compliant instance of a field object |
-| | | | see the utility method subject.getOutFieldSchemaHelper() below |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | executor.outFields["authorised"] = false; |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| logger | Logger | org.slf4j.ext.XLogger | .. container:: paragraph |
-| | | | |
-| | | | A helpful logger |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | executor.logger.info("Executing task: " |
-| | | | +executor.subject.id); |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| TRUE/FALSE | boolean | java.lang.Boolean | .. container:: paragraph |
-| | | | |
-| | | | 2 helpful constants. These are useful to retrieve correct return values for the |
-| | | | task logic |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | var returnValue = executor.isTrue; |
-| | | | var returnValueType = Java.type("java.lang.Boolean"); |
-| | | | var returnValue = new returnValueType(true); |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| subject | Task | TaskFacade | .. container:: paragraph |
-| | | | |
-| | | | This provides some useful information about the task that contains this task |
-| | | | logic. This object has some useful fields and methods : |
-| | | | |
-| | | | .. container:: ulist |
-| | | | |
-| | | | - **AxTask task** to get access to the full task definition of |
-| | | | the host task |
-| | | | |
-| | | | - **String getTaskName()** to get the name of the host task |
-| | | | |
-| | | | - **String getId()** to get the ID of the host task |
-| | | | |
-| | | | - **SchemaHelper getInFieldSchemaHelper( String fieldName )** to |
-| | | | get a ``SchemaHelper`` helper object to manipulate incoming |
-| | | | task fields in a schema-aware manner |
-| | | | |
-| | | | - **SchemaHelper getOutFieldSchemaHelper( String fieldName )** to |
-| | | | get a ``SchemaHelper`` helper object to manipulate outgoing |
-| | | | task fields in a schema-aware manner, e.g. to instantiate new |
-| | | | schema-compliant field objects to populate the |
-| | | | ``executor.outFields`` outgoing fields map |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | executor.logger.info("Task name: " |
-| | | | +executor.subject.getTaskName()); |
-| | | | executor.logger.info("Task id: " |
-| | | | +executor.subject.getId()); |
-| | | | executor.logger.info("Task inputs definitions: " |
-| | | | +"executor.subject.task.getInputFieldSet()); |
-| | | | executor.logger.info("Task outputs definitions: " |
-| | | | +"executor.subject.task.getOutputFieldSet()); |
-| | | | executor.outFields["authorised"] = executor.subject |
-| | | | .getOutFieldSchemaHelper("authorised") |
-| | | | .createNewInstance("false"); |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| ContextAlbum getContextAlbum(String ctxtAlbumName ) | .. container:: paragraph |
-| | |
-| | A utility method to retrieve a ``ContextAlbum`` for use in the task. |
-| | This is how you access the context used by the task. The returned |
-| | ``ContextAlbum`` implements the ``java.util.Map <String,Object>`` |
-| | interface to get and set context as appropriate. The returned |
-| | ``ContextAlbum`` also has methods to lock context albums, get |
-| | information about the schema of the items to be stored in a context |
-| | album, and get a ``SchemaHelper`` to manipulate context album items. How |
-| | to define and use context in a task is described in the Apex |
-| | Programmer’s Guide and in the My First Apex Policy guide. |
-| | |
-| | .. container:: |
-| | |
-| | .. container:: content |
-| | |
-| | .. container:: paragraph |
-| | |
-| | **Example:** |
-| | |
-| | .. code:: javascript |
-| | |
-| | var bkey = executor.inFields.get("branch_ID"); |
-| | var cnts = executor.getContextMap("BranchCounts"); |
-| | cnts.lockForWriting(bkey); |
-| | cnts.put(bkey, cnts.get(bkey) + 1); |
-| | cnts.unlockForWriting(bkey); |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
+=======================
-Writing APEX Task Selection Logic
----------------------------------
+.. container:: paragraph
+
+ Task logic specifies the behavior of an Apex Task. This logic can be specified in a number of ways, exploiting
+ Apex’s plug-in architecture to support a range of logic executors. In Apex scripted Task Logic can be written in any
+ of these languages:
+
+.. container:: ulist
+
+ - ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__,
+
+ - ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__,
+
+ - ```JRuby`` <https://en.wikipedia.org/wiki/JRuby>`__ or
+
+ - ```Jython`` <https://en.wikipedia.org/wiki/Jython>`__.
- .. container:: paragraph
-
- The function of Task Selection Logic is to choose which task
- should be executed for an Apex State as one of the steps in an
- Apex Policy. Since each state must define a default task there is
- no need for Task Selection Logic unless the state uses more than
- one task. This logic can be specified in a number of ways,
- exploiting Apex’s plug-in architecture to support a range of logic
- executors. In Apex scripted Task Selection Logic can be written in
- any of these languages:
-
- .. container:: ulist
-
- - ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__,
-
- - ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__,
-
- - ```JRuby`` <https://en.wikipedia.org/wiki/JRuby>`__ or
-
- - ```Jython`` <https://en.wikipedia.org/wiki/Jython>`__.
-
- .. container:: paragraph
-
- These languages were chosen because the scripts can be compiled
- into Java bytecode at runtime and then efficiently executed
- natively in the JVM. Task Selection Logic an also be written
- directly in Java but needs to be compiled, with the resulting
- classes added to the classpath. There are also a number of other
- Task Selection Logic types but these are not supported as yet.
- This guide will focus on the scripted Task Selection Logic
- approaches, with MVEL and JavaScript being our favorite languages.
- In particular this guide will focus on the Apex aspects of the
- scripts. However, this guide does not attempt to teach you about
- the scripting languages themselves …​ that is up to you!
-
- .. tip::
- JVM-based scripting languages
- For more more information on Scripting for the Java platform see:
- https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/index.html
-
- .. note::
- What does Task Selection Logic do?
- When an Apex state references multiple tasks, there must be a way to dynamically decide
- which task should be chosen and executed. This can depend on the many factors, e.g. the
- *incoming event for the state*, *shared state* or *context*, *external context*,
- etc.. This is the function of a state’s Task Selection Logic. Obviously, if there is
- only one task then Task only one task then Task Selection Logic is not needed.
- Each state must also select one of the tasks a the *default state*. If the Task
- Selection Logic is unable to select an appropriate task, then it should select the
- *default task*. Once the task has been selected the Apex Engine will then execute that
- task.
-
- .. container:: paragraph
-
- First lets start with some simple Task Selection Logic, drawn from
- the "My First Apex Policy" example: The Task Selection Logic from
- the "My First Apex Policy" example is specified in JavaScript
- here:
-
- .. container:: listingblock
-
- .. container:: title
-
- Javascript code for the "My First Policy" Task Selection Logic
-
- .. container:: content
-
- .. code:: javascript
-
- /*
- * ============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:: paragraph
-
- The role of the Task Selection Logic in this simple example is to
- examine the value in one incoming field (``branchid``), then
- depending on that field’s value set the value for the selected
- task to the appropriate task (``MorningBoozeCheck``,
- ``MorningBoozeCheckAlt1``, or the default task).
-
- .. container:: paragraph
-
- Another thing to notice is that Task Selection Logic should return
- a ``java.lang.Boolean`` value ``true`` if the logic executed
- correctly. If the logic fails for some reason then ``false`` can
- be returned, but this will cause the policy invoking this task
- will fail and exit.
-
- .. note::
- How to return a value from Task Selection Logic
- Some languages explicitly support returning values from the script (e.g. MVEL and
- JRuby) using an explicit return statement (e.g. ``return true``), other languages do not (e.g.
- JavaScript and Jython). For languages that do not support the ``return`` statement, a special field called
- ``returnValue`` must be created to hold the result of the task logic operation (i.e. assign a ``java.lang.Boolean``
- value to the ``returnValue`` field before completing the task).
- Also, in MVEL if there is not explicit return statement then the return value of the last executed statement will
- return (e.g. the statement a=(1+2) will return the value 3).
-
- .. container:: paragraph
-
- Each of the scripting languages used in Apex can import and use
- standard Java libraries to perform complex tasks. Besides imported
- classes and normal language features Apex provides some natively
- available parameters and functions that can be used directly. At
- run-time these parameters are populated by the Apex execution
- environment and made natively available to logic scripts each time
- the logic script is invoked. (These can be accessed using the
- ``executor`` keyword for most languages, or can be accessed
- directly without the ``executor`` keyword in MVEL):
-
- Table 2. The ``executor`` Fields / Methods
- +-------------------------------------------------------+--------------------------------------------------------+
- | Unix, Cygwin | Windows |
- +=======================================================+========================================================+
- | .. container:: | .. container:: |
- | | |
- | .. container:: content | .. container:: content |
- | | |
- | .. code:: bash | .. code:: bash |
- | :number-lines: | :number-lines: |
- | | |
- | >c: | # cd /usr/local/src/apex-pdp |
- | >cd \dev\apex | # mvn clean install -DskipTests |
- | >mvn clean install -DskipTests | |
- +-------------------------------------------------------+--------------------------------------------------------+
-
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| Name | Type | Java type | Description |
-+============+=============+================================+=====================================================================================+
-| inFields | Fields | java.util.Map <String,Object> | .. container:: paragraph |
-| | | | |
-| | | | All fields in the state’s incoming event. This is implemented as a standard Java |
-| | | | Java (unmodifiable) Map |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | executor.logger.debug("Incoming fields: " |
-| | | | +executor.inFields.entrySet()); |
-| | | | var item_id = executor.incomingFields["item_ID"]; |
-| | | | if (item_id >=1000) { ... } |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| outFields | Fields | java.util.Map <String,Object> | .. container:: paragraph |
-| | | | |
-| | | | The outgoing task fields. This is implemented as a standard initially empty Java |
-| | | | (modifiable) Map. To create a new schema-compliant instance of a field object |
-| | | | see the utility method subject.getOutFieldSchemaHelper() below |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | executor.outFields["authorised"] = false; |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| logger | Logger | org.slf4j.ext.XLogger | .. container:: paragraph |
-| | | | |
-| | | | A helpful logger |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | executor.logger.info("Executing task: " |
-| | | | +executor.subject.id); |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| TRUE/FALSE | boolean | java.lang.Boolean | .. container:: paragraph |
-| | | | |
-| | | | 2 helpful constants. These are useful to retrieve correct return values for the |
-| | | | task logic |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | var returnValue = executor.isTrue; |
-| | | | var returnValueType = Java.type("java.lang.Boolean"); |
-| | | | var returnValue = new returnValueType(true); |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| subject | Task | TaskFacade | .. container:: paragraph |
-| | | | |
-| | | | This provides some useful information about the task that contains this task |
-| | | | logic. This object has some useful fields and methods : |
-| | | | |
-| | | | .. container:: ulist |
-| | | | |
-| | | | - **AxTask task** to get access to the full task definition of |
-| | | | the host task |
-| | | | |
-| | | | - **String getTaskName()** to get the name of the host task |
-| | | | |
-| | | | - **String getId()** to get the ID of the host task |
-| | | | |
-| | | | - **SchemaHelper getInFieldSchemaHelper( String fieldName )** to |
-| | | | get a ``SchemaHelper`` helper object to manipulate incoming |
-| | | | task fields in a schema-aware manner |
-| | | | |
-| | | | - **SchemaHelper getOutFieldSchemaHelper( String fieldName )** to |
-| | | | get a ``SchemaHelper`` helper object to manipulate outgoing |
-| | | | task fields in a schema-aware manner, e.g. to instantiate new |
-| | | | schema-compliant field objects to populate the |
-| | | | ``executor.outFields`` outgoing fields map |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | executor.logger.info("Task name: " |
-| | | | +executor.subject.getTaskName()); |
-| | | | executor.logger.info("Task id: " |
-| | | | +executor.subject.getId()); |
-| | | | executor.logger.info("Task inputs definitions: " |
-| | | | +"executor.subject.task.getInputFieldSet()); |
-| | | | executor.logger.info("Task outputs definitions: " |
-| | | | +"executor.subject.task.getOutputFieldSet()); |
-| | | | executor.outFields["authorised"] = executor.subject |
-| | | | .getOutFieldSchemaHelper("authorised") |
-| | | | .createNewInstance("false"); |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| parameters | Fields | java.util.Map <String,String> | .. container:: paragraph |
-| | | | |
-| | | | All parameters in the current task. This is implemented as a standard Java Map. |
-| | | | |
-| | | | .. container:: |
-| | | | |
-| | | | .. container:: content |
-| | | | |
-| | | | .. container:: paragraph |
-| | | | |
-| | | | **Example:** |
-| | | | |
-| | | | .. code:: javascript |
-| | | | |
-| | | | executor.parameters.get("ParameterKey1")) |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-| ContextAlbum getContextAlbum(String ctxtAlbumName ) | .. container:: paragraph |
-| | |
-| | A utility method to retrieve a ``ContextAlbum`` for use in the task. |
-| | This is how you access the context used by the task. The returned |
-| | ``ContextAlbum`` implements the ``java.util.Map <String,Object>`` |
-| | interface to get and set context as appropriate. The returned |
-| | ``ContextAlbum`` also has methods to lock context albums, get |
-| | information about the schema of the items to be stored in a context |
-| | album, and get a ``SchemaHelper`` to manipulate context album items. How |
-| | to define and use context in a task is described in the Apex |
-| | Programmer’s Guide and in the My First Apex Policy guide. |
-| | |
-| | .. container:: |
-| | |
-| | .. container:: content |
-| | |
-| | .. container:: paragraph |
-| | |
-| | **Example:** |
-| | |
-| | .. code:: javascript |
-| | |
-| | var bkey = executor.inFields.get("branch_ID"); |
-| | var cnts = executor.getContextMap("BranchCounts"); |
-| | cnts.lockForWriting(bkey); |
-| | cnts.put(bkey, cnts.get(bkey) + 1); |
-| | cnts.unlockForWriting(bkey); |
-+------------+-------------+--------------------------------+-------------------------------------------------------------------------------------+
-
-Logic Cheatsheet
-----------------
-
- .. container:: paragraph
-
- Examples given here use Javascript (if not stated otherwise),
- other execution environments will be similar.
+.. container:: paragraph
+
+ These languages were chosen because the scripts can be compiled into Java bytecode at runtime and then efficiently
+ executed natively in the JVM. Task Logic an also be written directly in Java but needs to be compiled, with the
+ resulting classes added to the classpath. There are also a number of other Task Logic types (e.g. Fuzzy Logic), but
+ these are not supported as yet. This guide will focus on the scripted Task Logic approaches, with MVEL and JavaScript
+ being our favorite languages. In particular this guide will focus on the Apex aspects of the scripts. However, this
+ guide does not attempt to teach you about the scripting languages themselves …​ that is up to you!
+
+.. tip::
+ JVM-based scripting languages For more more information on scripting for the Java platform see:
+ https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/index.html
+
+.. note::
+ What do Tasks do? The function of an Apex Task is to provide the logic that can be executed for an Apex State as one
+ of the steps in an Apex Policy. Each task receives some *incoming fields*, executes some logic (e.g: make a decision
+ based on *shared state* or *context*, *incoming fields*, *external context*, etc.), perhaps set some *shared state*
+ or *context* and then emits *outgoing fields*. The state that uses the task is responsible for extracting the
+ *incoming fields* from the state input event. The state also has an *output mapper* associated with the task, and
+ this *output mapper* is responsible for mapping the *outgoing fields* from the task into an appropriate output event
+ for the state.
+
+.. container:: paragraph
+
+ First lets start with a sample task, drawn from the "My First Apex Policy" example: The task "MorningBoozeCheck"
+ from the "My First Apex Policy" example is available in both MVEL and JavaScript:
+
+.. container:: listingblock
+
+ .. container:: title
+
+ Javascript code for the ``MorningBoozeCheck`` task
+
+ .. container:: content
+
+ .. code:: javascript
+ :number-lines:
+
+ /*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * Modifications Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * 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=========================================================
+ */
+
+ 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 :-)
+ */
+
+ true;
+
+.. container:: listingblock
+
+ .. container:: title
+
+ MVEL code for the ``MorningBoozeCheck`` task
+
+ .. container:: content
+
+ .. code:: javascript
+ :number-lines:
+
+ /*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * Modifications Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * 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:: paragraph
+
+ The role of the task in this simple example is to copy the values in the incoming fields into the outgoing
+ fields, then examine the values in some incoming fields (``item_id`` and ``time``), then set the values in some
+ other outgoing fields (``authorised`` and ``message``).
+
+.. container:: paragraph
+
+ Both MVEL and JavaScript like most JVM-based scripting languages can use standard Java libraries to perform
+ complex tasks. Towards the top of the scripts you will see how to import Java classes and packages to be used
+ directly in the logic. Another thing to notice is that Task Logic should return a ``java.lang.Boolean`` value
+ ``true`` if the logic executed correctly. If the logic fails for some reason then ``false`` can be returned, but
+ this will cause the policy invoking this task will fail and exit.
+
+.. note::
+ How to return a value from task logic
+ Some languages explicitly support returning values from the script (e.g. MVEL and JRuby) using an explicit
+ return statement (e.g. ``return true``), other languages do not (e.g. Jython). For
+ languages that do not support the ``return`` statement, a special field called ``returnValue`` must be
+ created to hold the result of the task logic operation (i.e. assign a ``java.lang.Boolean``
+ value to the ``returnValue`` field before completing the task).
+ Also, in MVEL if there is no explicit return statement then the return value of the last executed statement will
+ return (e.g. the statement a=(1+2) will return the value 3).
+
+ For Javascript, the last statement of a script must be a statement that evaluates to *true* or *false*, indicating
+ whether the script executed correctly or not. In the case where the script always executes to compeletion
+ sucessfully, simply add a last line with the statement *true'*. In cases where success or failure is assessed in the
+ script, create a boolean
+ local variable with a name such as ``returnvalue``. In the execution of the script, set ``returnValue`` to be ``true``
+ or ``false`` as appropriate. The last line of the scritp tehn should simply be ``returnValue;``, which returns the
+ value of ``returnValue``.
+
+.. container:: paragraph
+
+ Besides these imported classes and normal language features Apex provides some natively available parameters
+ and functions that can be used directly. At run-time these parameters are populated by the Apex execution
+ environment and made natively available to logic scripts each time the logic script is invoked. (These can be
+ accessed using the ``executor`` keyword for most languages, or can be accessed directly without the
+ ``executor`` keyword in MVEL):
+
+Table 1. The ``executor`` Fields / Methods
+
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | Name | Type | Java type | Description |
+ +=====================================================+==========================================================================+===============================+==================================================================================+
+ | inFields | Fields | java.util.Map <String,Object> |The incoming task fields, implemented as a standard Java (unmodifiable) Map |
+ | | | | |
+ | | | |**Example:** |
+ | | | | |
+ | | | |.. code:: javascript |
+ | | | | |
+ | | | | executor.logger.debug("Incoming fields: " +executor.inFields.entrySet()); |
+ | | | | var item_id = executor.incomingFields["item_ID"]; |
+ | | | | if (item_id >=1000) { ... } |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | outFields | Fields | java.util.Map <String,Object> |The outgoing task fields. This is implemented as a standard initially empty Java |
+ | | | |(modifiable) Map. To create a new schema-compliant instance of a field object |
+ | | | |see the utility method subject.getOutFieldSchemaHelper() below |
+ | | | | |
+ | | | |**Example:** |
+ | | | | |
+ | | | |.. code:: javascript |
+ | | | | |
+ | | | | executor.outFields["authorised"] = false; |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | logger | Logger | org.slf4j.ext.XLogger |A helpful logger |
+ | | | | |
+ | | | |**Example:** |
+ | | | | |
+ | | | |.. code:: javascript |
+ | | | | |
+ | | | | executor.logger.info("Executing task: " +executor.subject.id); |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | TRUE/FALSE | boolean | java.lang.Boolean |2 helpful constants. These are useful to retrieve correct return values for the |
+ | | | |task logic |
+ | | | | |
+ | | | |**Example:** |
+ | | | | |
+ | | | |.. code:: javascript |
+ | | | | |
+ | | | | var returnValue = executor.isTrue; |
+ | | | | var returnValueType = Java.type("java.lang.Boolean"); |
+ | | | | var returnValue = new returnValueType(true); |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | subject | Task | TaskFacade |This provides some useful information about the task that contains this task |
+ | | | |logic. This object has some useful fields and methods : |
+ | | | | |
+ | | | |.. container:: ulist |
+ | | | | |
+ | | | | - **AxTask task** to get access to the full task definition of the host task |
+ | | | | |
+ | | | | - **String getTaskName()** to get the name of the host task |
+ | | | | |
+ | | | | - **String getId()** to get the ID of the host task |
+ | | | | |
+ | | | | - **SchemaHelper getInFieldSchemaHelper( String fieldName )** to |
+ | | | | get a ``SchemaHelper`` helper object to manipulate incoming |
+ | | | | task fields in a schema-aware manner |
+ | | | | |
+ | | | | - **SchemaHelper getOutFieldSchemaHelper( String fieldName )** to |
+ | | | | get a ``SchemaHelper`` helper object to manipulate outgoing |
+ | | | | task fields in a schema-aware manner, e.g. to instantiate new |
+ | | | | schema-compliant field objects to populate the |
+ | | | | ``executor.outFields`` outgoing fields map |
+ | | | | |
+ | | | |**Example:** |
+ | | | | |
+ | | | |.. code:: javascript |
+ | | | | |
+ | | | | executor.logger.info("Task name: " + executor.subject.getTaskName()); |
+ | | | | executor.logger.info("Task id: " + executor.subject.getId()); |
+ | | | | executor.logger.info("Task inputs definitions: " |
+ | | | | + "executor.subject.task.getInputFieldSet()); |
+ | | | | executor.logger.info("Task outputs definitions: " |
+ | | | | + "executor.subject.task.getOutputFieldSet()); |
+ | | | | executor.outFields["authorised"] = executor.subject |
+ | | | | .getOutFieldSchemaHelper("authorised").createNewInstance("false"); |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | ContextAlbum getContextAlbum(String ctxtAlbumName ) |A utility method to retrieve a ``ContextAlbum`` for use in the task. | | |
+ | |This is how you access the context used by the task. The returned | | |
+ | |``ContextAlbum`` implements the ``java.util.Map <String,Object>`` | | |
+ | |interface to get and set context as appropriate. The returned | | |
+ | |``ContextAlbum`` also has methods to lock context albums, get | | |
+ | |information about the schema of the items to be stored in a context | | |
+ | |album, and get a ``SchemaHelper`` to manipulate context album items. How | | |
+ | |to define and use context in a task is described in the Apex | | |
+ | |Programmer’s Guide and in the My First Apex Policy guide. | | |
+ | | | | |
+ | |**Example:** | | |
+ | | | | |
+ | |.. code:: javascript | | |
+ | | | | |
+ | | var bkey = executor.inFields.get("branch_ID"); | | |
+ | | var cnts = executor.getContextMap("BranchCounts"); | | |
+ | | cnts.lockForWriting(bkey); | | |
+ | | cnts.put(bkey, cnts.get(bkey) + 1); | | |
+ | | cnts.unlockForWriting(bkey); | | |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+
+Writing APEX Task Selection Logic
+=================================
+
+.. container:: paragraph
+
+ The function of Task Selection Logic is to choose which task should be executed for an Apex State as one of
+ the steps in an Apex Policy. Since each state must define a default task there is no need for Task Selection
+ Logic unless the state uses more than one task. This logic can be specified in a number of ways, exploiting
+ Apex’s plug-in architecture to support a range of logic executors. In Apex scripted Task Selection Logic can be
+ written in any of these languages:
+
+.. container:: ulist
+
+ - ```MVEL`` <https://en.wikipedia.org/wiki/MVEL>`__,
+
+ - ```JavaScript`` <https://en.wikipedia.org/wiki/JavaScript>`__,
+
+ - ```JRuby`` <https://en.wikipedia.org/wiki/JRuby>`__ or
+
+ - ```Jython`` <https://en.wikipedia.org/wiki/Jython>`__.
+
+.. container:: paragraph
+
+ These languages were chosen because the scripts can be compiled into Java bytecode at runtime and then
+ efficiently executed natively in the JVM. Task Selection Logic an also be written directly in Java but needs to
+ be compiled, with the resulting classes added to the classpath. There are also a number of other Task Selection
+ Logic types but these are not supported as yet. This guide will focus on the scripted Task Selection Logic
+ approaches, with MVEL and JavaScript being our favorite languages. In particular this guide will focus on the
+ Apex aspects of the scripts. However, this guide does not attempt to teach you about the scripting languages
+ themselves …​ that is up to you!
+
+.. tip::
+ JVM-based scripting languages
+ For more more information on Scripting for the Java platform see:
+ https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/prog_guide/index.html
+
+.. note::
+ What does Task Selection Logic do?
+ When an Apex state references multiple tasks, there must be a way to dynamically decide
+ which task should be chosen and executed. This can depend on the many factors, e.g. the
+ *incoming event for the state*, *shared state* or *context*, *external context*,
+ etc.. This is the function of a state’s Task Selection Logic. Obviously, if there is
+ only one task then Task only one task then Task Selection Logic is not needed.
+ Each state must also select one of the tasks a the *default state*. If the Task
+ Selection Logic is unable to select an appropriate task, then it should select the
+ *default task*. Once the task has been selected the Apex Engine will then execute that task.
+
+.. container:: paragraph
+
+ First lets start with some simple Task Selection Logic, drawn from the "My First Apex Policy" example: The Task
+ Selection Logic from the "My First Apex Policy" example is specified in JavaScript here:
+
+.. container:: listingblock
+
+ .. container:: title
+
+ Javascript code for the "My First Policy" Task Selection Logic
+
+ .. container:: content
+
+ .. code:: javascript
+
+ /*
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2016-2018 Ericsson. All rights reserved.
+ * Modifications Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * 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=========================================================
+ */
+
+ 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"
+ */
+
+ true;
+
+.. container:: paragraph
+
+ The role of the Task Selection Logic in this simple example is to examine the value in one incoming field
+ (``branchid``), then depending on that field’s value set the value for the selected task to the appropriate task
+ (``MorningBoozeCheck``, ``MorningBoozeCheckAlt1``, or the default task).
+
+.. container:: paragraph
+
+ Another thing to notice is that Task Selection Logic should return a ``java.lang.Boolean`` value ``true`` if
+ the logic executed correctly. If the logic fails for some reason then ``false`` can be returned, but this will
+ cause the policy invoking this task will fail and exit.
+
+.. note::
+ How to return a value from Task Selection Logic
+ Some languages explicitly support returning values from the script (e.g. MVEL and
+ JRuby) using an explicit return statement (e.g. ``return true``), other languages do not (e.g.
+ JavaScript and Jython). For languages that do not support the ``return`` statement, a special field called
+ ``returnValue`` must be created to hold the result of the task logic operation (i.e. assign a ``java.lang.Boolean``
+ value to the ``returnValue`` field before completing the task).
+ Also, in MVEL if there is not explicit return statement then the return value of the last executed statement will
+ return (e.g. the statement a=(1+2) will return the value 3).
+
+.. container:: paragraph
+
+ Each of the scripting languages used in Apex can import and use standard Java libraries to perform complex tasks.
+ Besides imported classes and normal language features Apex provides some natively available parameters and functions
+ that can be used directly. At run-time these parameters are populated by the Apex execution environment and made
+ natively available to logic scripts each time the logic script is invoked. (These can be accessed using the
+ ``executor`` keyword for most languages, or can be accessed directly without the ``executor`` keyword in MVEL):
+
+Table 2. The ``executor`` Fields / Methods
+ +-----------------------------------+------------------------------------+
+ | Unix, Cygwin | Windows |
+ +===================================+====================================+
+ |.. container:: content |.. container:: content |
+ | | |
+ | .. code:: bash | .. code:: bash |
+ | :number-lines: | :number-lines: |
+ | | |
+ | >c: | # cd /usr/local/src/apex-pdp |
+ | >cd \dev\apex | # mvn clean install -DskipTests |
+ | >mvn clean install -DskipTests | |
+ +-----------------------------------+------------------------------------+
+
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | Name | Type | Java type | Description |
+ +=====================================================+==========================================================================+===============================+==================================================================================+
+ | inFields | Fields | java.util.Map <String,Object> | All fields in the state’s incoming event. This is implemented as a standard Java |
+ | | | | Java (unmodifiable) Map |
+ | | | | |
+ | | | | **Example:** |
+ | | | | |
+ | | | | .. code:: javascript |
+ | | | | |
+ | | | | executor.logger.debug("Incoming fields: " + executor.inFields.entrySet()); |
+ | | | | var item_id = executor.incomingFields["item_ID"]; |
+ | | | | if (item_id >=1000) { ... } |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | outFields | Fields | java.util.Map <String,Object> | The outgoing task fields. This is implemented as a standard initially empty Java |
+ | | | | (modifiable) Map. To create a new schema-compliant instance of a field object |
+ | | | | see the utility method subject.getOutFieldSchemaHelper() below |
+ | | | | |
+ | | | | **Example:** |
+ | | | | |
+ | | | | .. code:: javascript |
+ | | | | |
+ | | | | executor.outFields["authorised"] = false; |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | logger | Logger | org.slf4j.ext.XLogger | A helpful logger |
+ | | | | |
+ | | | | **Example:** |
+ | | | | |
+ | | | | .. code:: javascript |
+ | | | | |
+ | | | | executor.logger.info("Executing task: " |
+ | | | | +executor.subject.id); |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | TRUE/FALSE | boolean | java.lang.Boolean | 2 helpful constants. These are useful to retrieve correct return values for the |
+ | | | | task logic |
+ | | | | |
+ | | | | **Example:** |
+ | | | | |
+ | | | | .. code:: javascript |
+ | | | | |
+ | | | | var returnValue = executor.isTrue; |
+ | | | | var returnValueType = Java.type("java.lang.Boolean"); |
+ | | | | var returnValue = new returnValueType(true); |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | subject | Task | TaskFacade | This provides some useful information about the task that contains this task |
+ | | | | logic. This object has some useful fields and methods : |
+ | | | | |
+ | | | | .. container:: ulist |
+ | | | | |
+ | | | | - **AxTask task** to get access to the full task definition of the host task |
+ | | | | |
+ | | | | - **String getTaskName()** to get the name of the host task |
+ | | | | |
+ | | | | - **String getId()** to get the ID of the host task |
+ | | | | |
+ | | | | - **SchemaHelper getInFieldSchemaHelper( String fieldName )** to |
+ | | | | get a ``SchemaHelper`` helper object to manipulate incoming |
+ | | | | task fields in a schema-aware manner |
+ | | | | |
+ | | | | - **SchemaHelper getOutFieldSchemaHelper( String fieldName )** to |
+ | | | | get a ``SchemaHelper`` helper object to manipulate outgoing |
+ | | | | task fields in a schema-aware manner, e.g. to instantiate new |
+ | | | | schema-compliant field objects to populate the |
+ | | | | ``executor.outFields`` outgoing fields map |
+ | | | | |
+ | | | | **Example:** |
+ | | | | |
+ | | | | .. code:: javascript |
+ | | | | |
+ | | | | executor.logger.info("Task name: " + executor.subject.getTaskName()); |
+ | | | | executor.logger.info("Task id: " + executor.subject.getId()); |
+ | | | | executor.logger.info("Task inputs definitions: " |
+ | | | | + "executor.subject.task.getInputFieldSet()); |
+ | | | | executor.logger.info("Task outputs definitions: " |
+ | | | | + "executor.subject.task.getOutputFieldSet()); |
+ | | | | executor.outFields["authorised"] = executor.subject |
+ | | | | .getOutFieldSchemaHelper("authorised") |
+ | | | | .createNewInstance("false"); |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | parameters | Fields | java.util.Map <String,String> | All parameters in the current task. This is implemented as a standard Java Map. |
+ | | | | |
+ | | | | **Example:** |
+ | | | | |
+ | | | | .. code:: javascript |
+ | | | | |
+ | | | | executor.parameters.get("ParameterKey1")) |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+ | ContextAlbum getContextAlbum(String ctxtAlbumName ) | A utility method to retrieve a ``ContextAlbum`` for use in the task. | | |
+ | | This is how you access the context used by the task. The returned | | |
+ | | ``ContextAlbum`` implements the ``java.util.Map <String,Object>`` | | |
+ | | interface to get and set context as appropriate. The returned | | |
+ | | ``ContextAlbum`` also has methods to lock context albums, get | | |
+ | | information about the schema of the items to be stored in a context | | |
+ | | album, and get a ``SchemaHelper`` to manipulate context album items. How | | |
+ | | to define and use context in a task is described in the Apex | | |
+ | | Programmer’s Guide and in the My First Apex Policy guide. | | |
+ | | | | |
+ | | **Example:** | | |
+ | | | | |
+ | | .. code:: javascript | | |
+ | | | | |
+ | | var bkey = executor.inFields.get("branch_ID"); | | |
+ | | var cnts = executor.getContextMap("BranchCounts"); | | |
+ | | cnts.lockForWriting(bkey); | | |
+ | | cnts.put(bkey, cnts.get(bkey) + 1); | | |
+ | | cnts.unlockForWriting(bkey); | | |
+ +-----------------------------------------------------+--------------------------------------------------------------------------+-------------------------------+----------------------------------------------------------------------------------+
+
+Logic Cheat Sheet
+=================
+
+.. container:: paragraph
+
+ Examples given here use Javascript (if not stated otherwise), other execution environments will be similar.
Finish Logic with Success or Error
-##################################
+----------------------------------
- .. container:: paragraph
+.. container:: paragraph
- To finish logic, i.e. return to APEX, with success use the
- following line close to the end of the logic.
+ To finish logic, i.e. return to APEX, with success use the following line close to the end of the logic.
- .. container:: listingblock
+.. container:: listingblock
- .. container:: title
+ .. container:: title
- JS Success
+ JS Success
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- true;
+ true;
- .. container:: paragraph
+.. container:: paragraph
- To notify a problem, finish with an error.
+ To notify a problem, finish with an error.
- .. container:: listingblock
+ .. container:: listingblock
- .. container:: title
+ .. container:: title
- JS Fail
+ JS Fail
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- false;
+ false;
Logic Logging
-#############
+-------------
- .. container:: paragraph
+.. container:: paragraph
- Logging can be made easy using a local variable for the logger.
- Line 1 below does that. Then we start with a trace log with the
- task (or task logic) identifier followed by the infields.
+ Logging can be made easy using a local variable for the logger. Line 1 below does that. Then we start
+ with a trace log with the task (or task logic) identifier followed by the infields.
- .. container:: listingblock
+.. container:: listingblock
- .. container:: title
+ .. container:: title
- JS Logging
+ JS Logging
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- var logger = executor.logger;
- logger.trace("start: " + executor.subject.id);
- logger.trace("-- infields: " + executor.inFields);
+ var logger = executor.logger;
+ logger.trace("start: " + executor.subject.id);
+ logger.trace("-- infields: " + executor.inFields);
- .. container:: paragraph
+.. container:: paragraph
- For larger logging blocks you can use the standard logging API
- to detect log levels, for instance:
+ For larger logging blocks you can use the standard logging API to detect log levels, for instance:
- .. container:: listingblock
+ .. container:: listingblock
- .. container:: title
+ .. container:: title
- JS Logging Blocks
+ JS Logging Blocks
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- if(logger.isTraceEnabled()){
- // trace logging block here
- }
+ if(logger.isTraceEnabled()){
+ // trace logging block here
+ }
- .. container:: paragraph
+.. container:: paragraph
- Note: the shown logger here logs to
- ``org.onap.policy.apex.executionlogging``. The behavior of the
- actual logging can be specified in the
- ``$APEX_HOME/etc/logback.xml``.
+ Note: the shown logger here logs to ``org.onap.policy.apex.executionlogging``. The behavior of the actual logging can
+ be specified in the ``$APEX_HOME/etc/logback.xml``.
- .. container:: paragraph
+.. container:: paragraph
- If you want to log into the APEX root logger (which is
- sometimes necessary to report serious logic errors to the top),
- then import the required class and use this logger.
+ If you want to log into the APEX root logger (which is sometimes necessary to report serious logic errors to the top),
+ then import the required class and use this logger.
- .. container:: listingblock
+.. container:: listingblock
- .. container:: title
+ .. container:: title
- JS Root Logger
+ JS Root Logger
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- importClass(org.slf4j.LoggerFactory);
- var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
-
- rootLogger.error("Serious error in logic detected: " + executor.subject.id);
+ var rootLogger = LoggerFactory.getLogger(logger.ROOT_LOGGER_NAME);
+ rootLogger.error("Serious error in logic detected: " + executor.subject.id);
Accessing TaskParameters
-########################
+------------------------
- .. container:: paragraph
+.. container:: paragraph
- TaskParameters available in a Task can be accessed in the logic.
- The parameters in each task are made available at the executor level.
- This example assumes a parameter with key ``ParameterKey1``.
+ TaskParameters available in a Task can be accessed in the logic. The parameters in each task are made
+ available at the executor level. This example assumes a parameter with key ``ParameterKey1``.
- .. container:: listingblock
+ .. container:: listingblock
- .. container:: title
+ .. container:: title
- JS TaskParameter value
+ JS TaskParameter value
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- executor.parameters.get("ParameterKey1"))
+ executor.parameters.get("ParameterKey1"))
- .. container:: paragraph
+.. container:: paragraph
- Alternatively, the task parameters can also be accessed from the task object.
+ Alternatively, the task parameters can also be accessed from the task object.
- .. container:: listingblock
+ .. container:: listingblock
- .. container:: title
+ .. container:: title
- JS TaskParameter value using task object
+ JS TaskParameter value using task object
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- executor.subject.task.getTaskParameters.get("ParameterKey1").getTaskParameterValue()
+ executor.subject.task.getTaskParameters.get("ParameterKey1").getTaskParameterValue()
Local Variable for Infields
-###########################
+---------------------------
- .. container:: paragraph
+.. container:: paragraph
- It is a good idea to use local variables for ``infields``. This
- avoids long code lines and policy evolution. The following
- example assumes infields named ``nodeName`` and ``nodeAlias``.
+ It is a good idea to use local variables for ``infields``. This avoids long code lines and policy
+ evolution. The following example assumes infields named ``nodeName`` and ``nodeAlias``.
- .. container:: listingblock
+ .. container:: listingblock
- .. container:: title
+ .. container:: title
- JS Infields Local Var
+ JS Infields Local Var
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- var ifNodeName = executor.inFields["nodeName"];
- var ifNodeAlias = executor.inFields["nodeAlias"];
+ var ifNodeName = executor.inFields["nodeName"];
+ var ifNodeAlias = executor.inFields["nodeAlias"];
Local Variable for Context Albums
-#################################
+---------------------------------
- .. container:: paragraph
+.. container:: paragraph
- Similar to the ``infields`` it is good practice to use local
- variables for context albums as well. The following example
- assumes that a task can access a context album
- ``albumTopoNodes``. The second line gets a particular node from
- this context album.
+ Similar to the ``infields`` it is good practice to use local variables for context albums as well. The
+ following example assumes that a task can access a context album ``albumTopoNodes``. The second line gets a
+ particular node from this context album.
- .. container:: listingblock
+.. container:: listingblock
- .. container:: title
+ .. container:: title
- JS Infields Local Var
+ JS Infields Local Var
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- var albumTopoNodes = executor.getContextAlbum("albumTopoNodes");
- var ctxtNode = albumTopoNodes.get(ifNodeName);
+ var albumTopoNodes = executor.getContextAlbum("albumTopoNodes");
+ var ctxtNode = albumTopoNodes.get(ifNodeName);
Set Outfields in Logic
-######################
+----------------------
- .. container:: paragraph
+.. container:: paragraph
- The task logic needs to set outfields with content generated.
- The exception are outfields that are a direct copy from an
- infield of the same name, APEX does that autmatically.
+ The task logic needs to set outfields with content generated. The exception are outfields that are a
+ direct copy from an infield of the same name, APEX does that autmatically.
- .. container:: listingblock
+.. container:: listingblock
- .. container:: title
+ .. container:: title
- JS Set Outfields
+ JS Set Outfields
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- executor.outFields["report"] = "node ctxt :: added node " + ifNodeName;
+ executor.outFields["report"] = "node ctxt :: added node " + ifNodeName;
Create a instance of an Outfield using Schemas
-##############################################
+----------------------------------------------
+
+.. container:: paragraph
- .. container:: paragraph
+ If an outfield is not an atomic type (string, integer, etc.) but uses a complex schema (with a Java or
+ Avro backend), APEX can help to create new instances. The ``executor`` provides a field called ``subject``,
+ which provides a schem helper with an API for this. The complete API of the schema helper is documented here:
+ `API Doc: SchemaHelper <https://ericsson.github.io/apex-docs/javadocs/index.html>`__.
- If an outfield is not an atomic type (string, integer, etc.)
- but uses a complex schema (with a Java or Avro backend), APEX
- can help to create new instances. The ``executor`` provides a
- field called ``subject``, which provides a schem helper with an
- API for this. The complete API of the schema helper is
- documented here: `API Doc:
- SchemaHelper <https://ericsson.github.io/apex-docs/javadocs/index.html>`__.
+.. container:: paragraph
- .. container:: paragraph
+ If the backend is Java, then the Java class implementing the schema needs to be imported.
- If the backend is Avro, then an import of the Avro schema
- library is required:
+.. container:: paragraph
- .. container:: listingblock
+ The following example assumes an outfield ``situation``. The ``subject`` method ``getOutFieldSchemaHelper()`` is used
+ to create a new instance.
- .. container:: title
+.. container:: listingblock
- JS Import Avro
+ .. container:: title
- .. container:: content
+ JS Outfield Instance with Schema
- .. code:: javascript
+ .. container:: content
- importClass(org.apache.avro.generic.GenericData.Array);
- importClass(org.apache.avro.generic.GenericRecord);
- importClass(org.apache.avro.Schema);
+ .. code:: javascript
- .. container:: paragraph
+ var situation = executor.subject.getOutFieldSchemaHelper("situation").createNewInstance();
- If the backend is Java, then the Java class implementing the
- schema needs to be imported.
+.. container:: paragraph
- .. container:: paragraph
+ If the schema backend is Java, the new instance will be as implemented in the Java class. If the schema backend is
+ Avro, the new instance will have all fields from the Avro schema specification, but set to ``null``. So any entry here
+ needs to be done separately. For instance, the ``situation`` schema has a field ``problemID`` which we set.
- The following example assumes an outfield ``situation``. The
- ``subject`` method ``getOutFieldSchemaHelper()`` is used to
- create a new instance.
+.. container:: listingblock
- .. container:: listingblock
+ .. container:: title
- .. container:: title
+ JS Outfield Instance with Schema, set
- JS Outfield Instance with Schema
+ .. container:: content
- .. container:: content
+ .. code:: javascript
- .. code:: javascript
+ situation.put("problemID", "my-problem");
- var situation = executor.subject.getOutFieldSchemaHelper("situation").createNewInstance();
+Create a instance of an Context Album entry using Schemas
+---------------------------------------------------------
- .. container:: paragraph
+.. container:: paragraph
- If the schema backend is Java, the new instance will be as
- implemented in the Java class. If the schema backend is Avro,
- the new instance will have all fields from the Avro schema
- specification, but set to ``null``. So any entry here needs to
- be done separately. For instance, the ``situation`` schema has
- a field ``problemID`` which we set.
+ Context album instances can be created using very similar to the outfields. Here, the schema helper
+ comes from the context album directly. The API of the schema helper is the same as for outfields, see
+ `API Doc: SchemaHelper <https://ericsson.github.io/apex-docs/javadocs/index.html>`__.
- .. container:: listingblock
+.. container:: paragraph
- .. container:: title
+ If the backend is Java, then the Java class implementing the schema needs to be imported.
- JS Outfield Instance with Schema, set
+.. container:: paragraph
- .. container:: content
+ The following example creates a new instance of a context album instance named ``albumProblemMap``.
- .. code:: javascript
+.. container:: listingblock
- situation.put("problemID", "my-problem");
+ .. container:: title
-Create a instance of an Context Album entry using Schemas
-#########################################################
+ JS Outfield Instance with Schema
+
+ .. container:: content
- .. container:: paragraph
+ .. code:: javascript
- Context album instances can be created using very similar to
- the outfields. Here, the schema helper comes from the context
- album directly. The API of the schema helper is the same as for
- outfields, see `API Doc:
- SchemaHelper <https://ericsson.github.io/apex-docs/javadocs/index.html>`__.
+ var albumProblemMap = executor.getContextAlbum("albumProblemMap");
+ var linkProblem = albumProblemMap.getSchemaHelper().createNewInstance();
- .. container:: paragraph
+.. container:: paragraph
- If the backend is Avro, then an import of the Avro schema
- library is required:
+ This can of course be also done in a single call without the local variable for the context album.
- .. container:: listingblock
+.. container:: listingblock
- .. container:: title
+ .. container:: title
- JS Import Avro
+ JS Outfield Instance with Schema, one line
- .. container:: content
+ .. container:: content
- .. code:: javascript
+ .. code:: javascript
- importClass(org.apache.avro.generic.GenericData.Array);
- importClass(org.apache.avro.generic.GenericRecord);
- importClass(org.apache.avro.Schema);
+ var linkProblem = executor.getContextAlbum("albumProblemMap").getSchemaHelper().createNewInstance();
- .. container:: paragraph
+.. container:: paragraph
- If the backend is Java, then the Java class implementing the
- schema needs to be imported.
+ If the schema backend is Java, the new instance will be as implemented in the Java class. If the schema backend is
+ Avro, the new instance will have all fields from the Avro schema specification, but set to ``null``. So any entry here
+ needs to be done separately (see above in outfields for an example).
- .. container:: paragraph
+Enumerates
+----------
- The following example creates a new instance of a context album
- instance named ``albumProblemMap``.
+.. container:: paragraph
- .. container:: listingblock
+ When dealing with enumerates (Avro or Java defined), it is sometimes and in some execution
+ environments necessary to convert them to a string. For example, assume an Avro enumerate schema as:
- .. container:: title
+.. container:: listingblock
- JS Outfield Instance with Schema
+ .. container:: title
- .. container:: content
+ Avro Enumerate Schema
- .. code:: javascript
+ .. container:: content
- var albumProblemMap = executor.getContextAlbum("albumProblemMap");
- var linkProblem = albumProblemMap.getSchemaHelper().createNewInstance();
+ .. code:: javascript
- .. container:: paragraph
+ {
+ "type": "enum", "name": "Status", "symbols" : [
+ "UP", "DOWN"
+ ]
+ }
- This can of course be also done in a single call without the
- local variable for the context album.
+.. container:: paragraph
- .. container:: listingblock
+ Using a switch over a field initialized with this enumerate in Javascript will fail. Instead, use the ``toString`` method, for example:
- .. container:: title
+.. container:: listingblock
- JS Outfield Instance with Schema, one line
+ .. container:: title
- .. container:: content
+ JS Outfield Instance with Schema, one line
- .. code:: javascript
+ .. container:: content
- var linkProblem = executor.getContextAlbum("albumProblemMap").getSchemaHelper().createNewInstance();
+ .. code:: javascript
- .. container:: paragraph
+ var switchTest = executor.inFields["status"]; switch(switchTest.toString()){
+ case "UP": ...; break; case "DOWN": ...; break; default: ...;
+ }
- If the schema backend is Java, the new instance will be as
- implemented in the Java class. If the schema backend is Avro,
- the new instance will have all fields from the Avro schema
- specification, but set to ``null``. So any entry here needs to
- be done separately (see above in outfields for an example).
+MVEL Initialize Outfields First!
+--------------------------------
-Enumerates
-##########
+.. container:: paragraph
- .. container:: paragraph
+ In MVEL, we observed a problem when accessing (setting) outfields without a prior access to them. So
+ in any MVEL task logic, before setting any outfield, simply do a get (with any string), to load the outfields
+ into the MVEL cache.
- When dealing with enumerates (Avro or Java defined), it is
- sometimes and in some execution environments necessary to
- convert them to a string. For example, assume an Avro enumerate
- schema as:
+.. container:: listingblock
- .. container:: listingblock
+ .. container:: title
- .. container:: title
+ MVEL Outfield Initialization
- Avro Enumerate Schema
+ .. container:: content
- .. container:: content
+ .. code:: javascript
- .. code:: javascript
+ outFields.get("initialize outfields");
- {
- "type": "enum",
- "name": "Status",
- "symbols" : [
- "UP",
- "DOWN"
- ]
- }
+Using Java in Scripting Logic
+-----------------------------
- .. container:: paragraph
+.. container:: paragraph
- Using a switch over a field initialized with this enumerate in
- Javascript will fail. Instead, use the ``toString`` method, for
- example:
+ Since APEX executes the logic inside a JVM, most scripting languages provide access to all standard
+ Java classes. Simply add an import for the required class and then use it as in actual Java.
- .. container:: listingblock
+.. container:: paragraph
- .. container:: title
+ The following example imports ``java.util.arraylist`` into a Javascript logic, and then creates a new
+ list.
- JS Outfield Instance with Schema, one line
+.. container:: listingblock
- .. container:: content
+ .. container:: title
- .. code:: javascript
+ JS Import ArrayList
- var switchTest = executor.inFields["status"];
- switch(switchTest.toString()){
- case "UP": ...; break;
- case "DOWN": ...; break;
- default: ...;
- }
+ .. container:: content
-MVEL Initialize Outfields First!
-################################
+ .. code:: javascript
+
+ var myList = new ArrayList();
- .. container:: paragraph
+Converting Javascript scripts from Nashorn to Rhino dialects
+------------------------------------------------------------
- In MVEL, we observed a problem when accessing (setting)
- outfields without a prior access to them. So in any MVEL task
- logic, before setting any outfield, simply do a get (with any
- string), to load the outfields into the MVEL cache.
+The Nashorn Javascript engine was removed from Java in the Java 11 release. Java 11 was introduced into
+the Policy Framework in the Frankfurt release, so from Frankfurt on, APEX Javascript scripts use the Rhino
+Javascript engine and scripts must be in the Rhino dialect.
- .. container:: listingblock
+There are some minor but important differences between the dialects that users should be aware of so
+that they can convert their scripts into the Rhino dialect.
- .. container:: title
+Return Values
+^^^^^^^^^^^^^
- MVEL Outfield Initialization
+APEX scripts must always return a value of ``true`` indicating that the script executed correctly or ``false``
+indicating that there was an error in script execution.
- .. container:: content
+*Pre Frankfurt*
- .. code:: javascript
+In Nashorn dialect scripts, the user had to create a special variable called ``returnValue`` and set the value of
+that variable to be the return value for the script.
- outFields.get("initialize outfields");
+*Frankfurt and Later*
-Using Java in Scripting Logic
-#############################
+In Rhino dialect scripts, the return value of the script is the logical result of the last statement. Therefore the
+last line of the script must evaluate to either ``true`` or ``false``.
+
+.. container:: listingblock
+
+ .. container:: title
+
+ JS Rhino script last executed line examples
+
+ .. container:: content
+
+ .. code:: javascript
+
+ true;
+
+ returnValue; // Where returnValue is assigned earlier in the script
+
+ someValue == 1; // Where the value of someValue is assigned earlier in the script
+
+return statement
+^^^^^^^^^^^^^^^^
+
+The ``return`` statement is not supported from the main script called in the Rhino interpreter.
+
+*Pre Frankfurt*
+
+In Nashorn dialect scripts, the user could return a value of ``true`` or ``false`` at any point in their script.
+
+.. container:: listingblock
+
+ .. container:: title
+
+ JS Nashorn main script returning ``true`` and ``false``
+
+ .. container:: content
+
+ .. code:: javascript
+
+ var n;
+
+ // some code assigns n a value
+
+ if (n < 2) {
+ return false;
+ } else {
+ return true;
+ }
+
+*Frankfurt and Later*
+
+In Rhino dialect scripts, the ``return`` statement cannot be used in the main method, but it can still be used in
+functions. If you want to have a ``return`` statement in your code prior to the last statement, encapsulate your code
+in a function.
+
+.. container:: listingblock
+
+ .. container:: title
+
+ JS Rhino script with ``return`` statements in a function
+
+ .. container:: content
+
+ .. code:: javascript
+
+ someFunction();
+
+ function someFunction() {
+ var n;
+
+ // some code assigns n a value
+
+ if (n < 2) {
+ return false;
+ } else {
+ return true;
+ }
+ }
+
+Compatibility Script
+^^^^^^^^^^^^^^^^^^^^
+
+For Nashorn, the user had to call a compatibility script at the beginning of their Javascript script. This is not
+required in Rhino.
+
+*Pre Frankfurt*
+
+In Nashorn dialect scripts, the compatibility script must be loaded.
+
+.. container:: listingblock
+
+ .. container:: title
+
+ Nashorn compatability script loading
+
+ .. container:: content
+
+ .. code:: javascript
+
+ load("nashorn:mozilla_compat.js");
+
+*Frankfurt and Later*
+
+Not required.
+
+Import of Java classes
+^^^^^^^^^^^^^^^^^^^^^^
+
+For Nashorn, the user had explicitly import all the Java packages and classes they wished to use in their Javascript
+script. In Rhino, all Java classes on the classpath are available for use.
+
+*Pre Frankfurt*
+
+In Nashorn dialect scripts, Java classes must be imported.
+
+.. container:: listingblock
+
+ .. container:: title
+
+ Importation of Java packages and classes
+
+ .. container:: content
+
+ .. code:: javascript
+
+ importPackage(java.text);
+ importClass(java.text.SimpleDateFormat);
+
+*Frankfurt and Later*
+
+Not required.
+
+Using Java Classes and Objects as Variables
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Setting a Javascript variable to hold a Java class or a Java object is more straightforward in Rhino than it is in
+Nashorn. The examples below show how to instantiate a Javascript variable as a Java class and how to use that variable
+to create an instance of the Java class in another Javascript variable in both dialects.
+
+
+*Pre Frankfurt*
+
+.. container:: listingblock
- .. container:: paragraph
+ .. container:: title
- Since APEX executes the logic inside a JVM, most scripting
- languages provide access to all standard Java classes. Simply
- add an import for the required class and then use it as in
- actual Java.
+ Create Javascript variables to hold a Java class and instance
- .. container:: paragraph
+ .. container:: content
- The following example imports ``java.util.arraylist`` into a
- Javascript logic, and then creates a new list.
+ .. code:: javascript
- .. container:: listingblock
+ var webClientClass = Java.type("org.onap.policy.apex.examples.bbs.WebClient");
+ var webClientObject = new webClientClass();
- .. container:: title
+*Frankfurt and Later*
- JS Import ArrayList
+.. container:: listingblock
- .. container:: content
+ .. container:: title
- .. code:: javascript
+ Create Javascript variables to hold a Java class and instance
- importClass(java.util.ArrayList);
- var myList = new ArrayList();
+ .. container:: content
+ .. code:: javascript
-.. container::
- :name: footer
+ var webClientClass = org.onap.policy.apex.examples.bbs.WebClient;
+ var webClientObject = new webClientClass();
- .. container::
- :name: footer-text
+Equal Value and Equal Type operator ``===``
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
- 2.3.0-SNAPSHOT
- Last updated 2020-03-16 16:04:24 GMT
+The *Equal Value and Equal Type* operator ``===`` is not supported in Rhino. Developers must use the Equal To
+operator ``==`` instead. To check types, they may need to explicitly find and check the type of the variables
+they are using.
.. |APEX Policy Matrix| image:: images/apex-intro/ApexPolicyMatrix.png
.. |APEX Policy Model for Execution| image:: images/apex-policy-model/UmlPolicyModels.png
diff --git a/docs/apex/apex.rst b/docs/apex/apex.rst
index 8023e6d7..862bcfaf 100644
--- a/docs/apex/apex.rst
+++ b/docs/apex/apex.rst
@@ -3,14 +3,12 @@
.. _apex-doc:
Policy APEX PDP Engine
-------------------------------------------------
+----------------------
.. toctree::
:maxdepth: 1
APEX-Introduction.rst
APEX-User-Manual.rst
APEX-Policy-Guide.rst
- APEX-Developer-Guide.rst
- APEX-Install-Guide.rst
APEX-OnapPf-Guide.rst
APEX-Policy-Examples.rst
diff --git a/docs/api/api.rst b/docs/api/api.rst
index c65e35e8..990ac9e7 100644
--- a/docs/api/api.rst
+++ b/docs/api/api.rst
@@ -288,3 +288,12 @@ Get vFirewall Operational Policy::
Delete vFirewall Operational Policy::
curl --user 'healthcheck:zb!XztG34' -X DELETE "http://{ip}:{port}/policy/api/v1/policytypes/onap.policies.controlloop.operational.common.Drools/versions/1.0.0/policies/operational.modifyconfig/versions/1.0.0" -H "Accept: application/json" -H "Content-Type: application/json"
+
+Get all available policies::
+ curl --user 'healthcheck:zb!XztG34' -X GET "http://{ip}:{port}/policy/api/v1/policies" -H "Accept: application/json" -H "Content-Type: application/json"
+
+Get version 1.0.0 of vFirewall Monitoring Policy::
+ curl --user 'healthcheck:zb!XztG34' -X GET "http://{ip}:{port}/policy/api/v1/policies/onap.vfirewall.tca/versions/1.0.0" -H "Accept: application/json" -H "Content-Type: application/json"
+
+Delete version 1.0.0 of vFirewall Monitoring Policy::
+ curl --user 'healthcheck:zb!XztG34' -X DELETE "http://{ip}:{port}/policy/api/v1/policies/onap.vfirewall.tca/versions/1.0.0" -H "Accept: application/json" -H "Content-Type: application/json"
diff --git a/docs/api/swagger/policy-api.json b/docs/api/swagger/policy-api.json
index 76735751..95c73973 100644
--- a/docs/api/swagger/policy-api.json
+++ b/docs/api/swagger/policy-api.json
@@ -506,8 +506,287 @@
"last-mod-release" : "Dublin"
}
}
- },
+ },
+ "/policy/api/v1/policies/{policyId}/versions/{policyVersion}": {
+ "get": {
+ "tags": [
+ "Policy"
+ ],
+ "summary": "Retrieve specific version of a specified policy",
+ "description": "Returns a particular version of specified policy",
+ "operationId": "getSpecificPolicy",
+ "consumes": [
+ "application/json",
+ "application/yaml"
+ ],
+ "produces": [
+ "application/json",
+ "application/yaml"
+ ],
+ "parameters": [
+ {
+ "name": "policyId",
+ "in": "path",
+ "description": "Name of policy",
+ "required": true,
+ "type": "string"
+ },
+ {
+ "name": "policyVersion",
+ "in": "path",
+ "description": "Version of policy",
+ "required": true,
+ "type": "string"
+ },
+ {
+ "name": "X-ONAP-RequestID",
+ "in": "header",
+ "description": "RequestID for http transaction",
+ "required": false,
+ "type": "string",
+ "format": "uuid"
+ },
+ {
+ "name": "mode",
+ "in": "query",
+ "description": "Fetch mode for policies, BARE for bare policies (default), REFERENCED for fully referenced policies",
+ "required": false,
+ "type": "string",
+ "default": "bare",
+ "enum": [
+ "BARE",
+ "REFERENCED"
+ ]
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "headers": {
+ "X-MinorVersion": {
+ "type": "string",
+ "description": "Used to request or communicate a MINOR version back from the client to the server, and from the server back to the client"
+ },
+ "X-PatchVersion": {
+ "type": "string",
+ "description": "Used only to communicate a PATCH version in a response for troubleshooting purposes only, and will not be provided by the client on request"
+ },
+ "X-LatestVersion": {
+ "type": "string",
+ "description": "Used only to communicate an API's latest version"
+ },
+ "X-ONAP-RequestID": {
+ "type": "string",
+ "format": "uuid",
+ "description": "Used to track REST transactions for logging purpose"
+ }
+ },
+ "schema": {
+ "$ref": "#/definitions/ToscaServiceTemplate"
+ }
+ },
+ "401": {
+ "description": "Authentication Error"
+ },
+ "403": {
+ "description": "Authorization Error"
+ },
+ "404": {
+ "description": "Resource Not Found"
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ },
+ "security": [
+ {
+ "basicAuth": []
+ }
+ ],
+ "x-interface info": {
+ "api-version": "1.0.0",
+ "last-mod-release": "Guilin"
+ }
+ },
+ "delete": {
+ "tags": [
+ "Policy"
+ ],
+ "summary": "Delete a particular version of a policy",
+ "description": "Rule: the version that has been deployed in PDP group(s) cannot be deleted",
+ "operationId": "deleteSpecificPolicy",
+ "consumes": [
+ "application/json",
+ "application/yaml"
+ ],
+ "produces": [
+ "application/json",
+ "application/yaml"
+ ],
+ "parameters": [
+ {
+ "name": "policyId",
+ "in": "path",
+ "description": "ID of policy",
+ "required": true,
+ "type": "string"
+ },
+ {
+ "name": "policyVersion",
+ "in": "path",
+ "description": "Version of policy",
+ "required": true,
+ "type": "string"
+ },
+ {
+ "name": "X-ONAP-RequestID",
+ "in": "header",
+ "description": "RequestID for http transaction",
+ "required": false,
+ "type": "string",
+ "format": "uuid"
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "headers": {
+ "X-MinorVersion": {
+ "type": "string",
+ "description": "Used to request or communicate a MINOR version back from the client to the server, and from the server back to the client"
+ },
+ "X-PatchVersion": {
+ "type": "string",
+ "description": "Used only to communicate a PATCH version in a response for troubleshooting purposes only, and will not be provided by the client on request"
+ },
+ "X-LatestVersion": {
+ "type": "string",
+ "description": "Used only to communicate an API's latest version"
+ },
+ "X-ONAP-RequestID": {
+ "type": "string",
+ "format": "uuid",
+ "description": "Used to track REST transactions for logging purpose"
+ }
+ },
+ "schema": {
+ "$ref": "#/definitions/ToscaServiceTemplate"
+ }
+ },
+ "401": {
+ "description": "Authentication Error"
+ },
+ "403": {
+ "description": "Authorization Error"
+ },
+ "404": {
+ "description": "Resource Not Found"
+ },
+ "409": {
+ "description": "Delete Conflict, Rule Violation"
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ },
+ "security": [
+ {
+ "basicAuth": []
+ }
+ ],
+ "x-interface info": {
+ "api-version": "1.0.0",
+ "last-mod-release": "Guilin"
+ }
+ }
+ },
"/policy/api/v1/policies" : {
+ "get": {
+ "tags": [
+ "Policy"
+ ],
+ "summary": "Retrieve all versions of available policies",
+ "description": "Returns all version of available policies",
+ "operationId": "getPolicies",
+ "consumes": [
+ "application/json",
+ "application/yaml"
+ ],
+ "produces": [
+ "application/json",
+ "application/yaml"
+ ],
+ "parameters": [
+ {
+ "name": "X-ONAP-RequestID",
+ "in": "header",
+ "description": "RequestID for http transaction",
+ "required": false,
+ "type": "string",
+ "format": "uuid"
+ },
+ {
+ "name": "mode",
+ "in": "query",
+ "description": "Fetch mode for policies, BARE for bare policies (default), REFERENCED for fully referenced policies",
+ "required": false,
+ "type": "string",
+ "default": "bare",
+ "enum": [
+ "BARE",
+ "REFERENCED"
+ ]
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "successful operation",
+ "headers": {
+ "X-MinorVersion": {
+ "type": "string",
+ "description": "Used to request or communicate a MINOR version back from the client to the server, and from the server back to the client"
+ },
+ "X-PatchVersion": {
+ "type": "string",
+ "description": "Used only to communicate a PATCH version in a response for troubleshooting purposes only, and will not be provided by the client on request"
+ },
+ "X-LatestVersion": {
+ "type": "string",
+ "description": "Used only to communicate an API's latest version"
+ },
+ "X-ONAP-RequestID": {
+ "type": "string",
+ "format": "uuid",
+ "description": "Used to track REST transactions for logging purpose"
+ }
+ },
+ "schema": {
+ "$ref": "#/definitions/ToscaServiceTemplate"
+ }
+ },
+ "401": {
+ "description": "Authentication Error"
+ },
+ "403": {
+ "description": "Authorization Error"
+ },
+ "404": {
+ "description": "Resource Not Found"
+ },
+ "500": {
+ "description": "Internal Server Error"
+ }
+ },
+ "security": [
+ {
+ "basicAuth": []
+ }
+ ],
+ "x-interface info": {
+ "api-version": "1.0.0",
+ "last-mod-release": "Guilin"
+ }
+ },
"post" : {
"tags" : [ "Policy" ],
"summary" : "Create one or more new policies",
diff --git a/docs/offeredapis.rst b/docs/offeredapis.rst
index 799facfd..ee90751a 100644
--- a/docs/offeredapis.rst
+++ b/docs/offeredapis.rst
@@ -17,10 +17,6 @@ The Policy Framework supports the public APIs listed in the links below:
pap/pap
xacml/decision-api
-.. warning:: The :ref:`Legacy APIs <legacyapis-label>` are scheduled to be deprecated after the Frankfurt release!
-
-- :ref:`Legacy APIs <legacyapis-label>` (To be DEPRECATED)
-
Postman Environment for API Testing
-----------------------------------
@@ -31,6 +27,22 @@ The following environment file from postman can be used for testing API's. All y
Postman Collection for API Testing
----------------------------------
-The following collection can be used in Postman to assist in testing the Policy APIs.
+Postman collection for `Policy Framework Lifecycle API <https://github.com/onap/policy-api/blob/master/postman/lifecycle-api-collection.json>`_
+
+Postman collection for `Policy Framework Administration API <https://github.com/onap/policy-pap/blob/master/postman/pap-api-collection.json>`_
+
+Postman collection for `Policy Framework Decision API <https://github.com/onap/policy-xacml-pdp/blob/master/postman/decision-api-collection.json>`_
+
+API Swagger Generation
+----------------------
+
+The standard for API definition in the RESTful API world is the OpenAPI Specification (OAS). The OAS, which is based on
+the original "Swagger Specification," is being widely used in API developments.
+
+Execute the below curl command for swagger generation by filling in the authorization details, IP and Port information:
+
+.. code-block:: bash
+
+ “curl -k --user ‘{user_id}:{password}’ https://{ip}:{port}/swagger.json”
+
-:download:`link <PolicyAPI.postman_collection.json>`
diff --git a/integration/pom.xml b/integration/pom.xml
index 42909692..9d5f06f3 100644
--- a/integration/pom.xml
+++ b/integration/pom.xml
@@ -40,7 +40,6 @@
<version.dmaap>1.1.11</version.dmaap>
<version.powermock>2.0.4</version.powermock>
<version.eclipselink>2.7.5</version.eclipselink>
- <version.jackson>2.10.4</version.jackson>
<version.drools>7.33.0.Final</version.drools>
<version.jersey>2.30.1</version.jersey>
<version.ccsdk>0.4.4</version.ccsdk>
@@ -60,37 +59,6 @@
<dependencyManagement>
<dependencies>
- <!-- Jackson -->
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-annotations</artifactId>
- <version>${version.jackson}</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-core</artifactId>
- <version>${version.jackson}</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- <version>${version.jackson}</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.dataformat</groupId>
- <artifactId>jackson-dataformat-yaml</artifactId>
- <version>${version.jackson}</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.jaxrs</groupId>
- <artifactId>jackson-jaxrs-base</artifactId>
- <version>${version.jackson}</version>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.jaxrs</groupId>
- <artifactId>jackson-jaxrs-json-provider</artifactId>
- <version>${version.jackson}</version>
- </dependency>
<!-- Jersey -->
<dependency>
@@ -154,12 +122,6 @@
</dependency>
<dependency>
- <groupId>org.glassfish.jersey.media</groupId>
- <artifactId>jersey-media-json-jackson</artifactId>
- <version>${version.jersey}</version>
- </dependency>
-
- <dependency>
<groupId>org.glassfish.jersey.test-framework</groupId>
<artifactId>jersey-test-framework-core</artifactId>
<version>${version.jersey}</version>