Author: shuber
Date: Wed Feb 9 08:27:10 2022
New Revision: 1897886
URL: http://svn.apache.org/viewvc?rev=1897886&view=rev
Log:
Site checkin for project Apache Unomi :: Root Project
Modified:
unomi/website/manual/1_1_x/index.html
unomi/website/manual/1_2_x/index.html
unomi/website/manual/1_3_x/index.html
unomi/website/manual/1_4_x/index.html
unomi/website/manual/1_5_x/index.html
unomi/website/manual/latest/index.html
Modified: unomi/website/manual/1_1_x/index.html
URL:
http://svn.apache.org/viewvc/unomi/website/manual/1_1_x/index.html?rev=1897886&r1=1897885&r2=1897886&view=diff
==============================================================================
--- unomi/website/manual/1_1_x/index.html (original)
+++ unomi/website/manual/1_1_x/index.html Wed Feb 9 08:27:10 2022
@@ -921,7 +921,7 @@ information about the context for the cu
<p>We need to either retrieve (from the initial context we retrieved
previously using <code>cxs.sessionId</code>) or generate a session identifier
for our request since Unomi currently requires one.</p>
</li>
<li>
-<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId='"
class="bare">http://localhost:8181/cxs/context.json?sessionId='</a>; +
sessionId</code>. This URI requests context from Unomi, resulting in an updated
<code>cxs</code> object in the javascript global scope. The context server can
reply to this request either by returning a JSON-only object containing solely
the context information as is the case when the requested URI is
<code>context.json</code>. However, if the client requests
<code>context.js</code> then useful functions to interact with Unomi are added
to the <code>cxs</code> object in addition to the context information as
depicted above.</p>
+<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId=sessionId"
class="bare">http://localhost:8181/cxs/context.json?sessionId=sessionId</a></code>.
This URI requests context from Unomi, resulting in an updated <code>cxs</code>
object in the javascript global scope. The context server can reply to this
request either by returning a JSON-only object containing solely the context
information as is the case when the requested URI is <code>context.json</code>.
However, if the client requests <code>context.js</code> then useful functions
to interact with Unomi are added to the <code>cxs</code> object in addition to
the context information as depicted above.</p>
</li>
<li>
<p>We don’t need to provide any authentication at all to interact with
this part of Unomi since we only have access to read-only data (as well as
providing events as we shall see later on). If we had been using the REST API,
we would have needed to provide authentication information as well.</p>
Modified: unomi/website/manual/1_2_x/index.html
URL:
http://svn.apache.org/viewvc/unomi/website/manual/1_2_x/index.html?rev=1897886&r1=1897885&r2=1897886&view=diff
==============================================================================
--- unomi/website/manual/1_2_x/index.html (original)
+++ unomi/website/manual/1_2_x/index.html Wed Feb 9 08:27:10 2022
@@ -1657,7 +1657,7 @@ information about the context for the cu
<p>We need to either retrieve (from the initial context we retrieved
previously using <code>cxs.sessionId</code>) or generate a session identifier
for our request since Unomi currently requires one.</p>
</li>
<li>
-<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId='"
class="bare">http://localhost:8181/cxs/context.json?sessionId='</a>; +
sessionId</code>. This URI requests context from Unomi, resulting in an updated
<code>cxs</code> object in the javascript global scope. The context server can
reply to this request either by returning a JSON-only object containing solely
the context information as is the case when the requested URI is
<code>context.json</code>. However, if the client requests
<code>context.js</code> then useful functions to interact with Unomi are added
to the <code>cxs</code> object in addition to the context information as
depicted above.</p>
+<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId=sessionId"
class="bare">http://localhost:8181/cxs/context.json?sessionId=sessionId</a></code>.
This URI requests context from Unomi, resulting in an updated <code>cxs</code>
object in the javascript global scope. The context server can reply to this
request either by returning a JSON-only object containing solely the context
information as is the case when the requested URI is <code>context.json</code>.
However, if the client requests <code>context.js</code> then useful functions
to interact with Unomi are added to the <code>cxs</code> object in addition to
the context information as depicted above.</p>
</li>
<li>
<p>We don’t need to provide any authentication at all to interact with
this part of Unomi since we only have access to read-only data (as well as
providing events as we shall see later on). If we had been using the REST API,
we would have needed to provide authentication information as well.</p>
Modified: unomi/website/manual/1_3_x/index.html
URL:
http://svn.apache.org/viewvc/unomi/website/manual/1_3_x/index.html?rev=1897886&r1=1897885&r2=1897886&view=diff
==============================================================================
--- unomi/website/manual/1_3_x/index.html (original)
+++ unomi/website/manual/1_3_x/index.html Wed Feb 9 08:27:10 2022
@@ -1300,7 +1300,7 @@ information about the context for the cu
<p>We need to either retrieve (from the initial context we retrieved
previously using <code>cxs.sessionId</code>) or generate a session identifier
for our request since Unomi currently requires one.</p>
</li>
<li>
-<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId='"
class="bare">http://localhost:8181/cxs/context.json?sessionId='</a>; +
sessionId</code>. This URI requests context from Unomi, resulting in an updated
<code>cxs</code> object in the javascript global scope. The context server can
reply to this request either by returning a JSON-only object containing solely
the context information as is the case when the requested URI is
<code>context.json</code>. However, if the client requests
<code>context.js</code> then useful functions to interact with Unomi are added
to the <code>cxs</code> object in addition to the context information as
depicted above.</p>
+<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId=sessionId"
class="bare">http://localhost:8181/cxs/context.json?sessionId=sessionId</a></code>.
This URI requests context from Unomi, resulting in an updated <code>cxs</code>
object in the javascript global scope. The context server can reply to this
request either by returning a JSON-only object containing solely the context
information as is the case when the requested URI is <code>context.json</code>.
However, if the client requests <code>context.js</code> then useful functions
to interact with Unomi are added to the <code>cxs</code> object in addition to
the context information as depicted above.</p>
</li>
<li>
<p>We don’t need to provide any authentication at all to interact with
this part of Unomi since we only have access to read-only data (as well as
providing events as we shall see later on). If we had been using the REST API,
we would have needed to provide authentication information as well.</p>
Modified: unomi/website/manual/1_4_x/index.html
URL:
http://svn.apache.org/viewvc/unomi/website/manual/1_4_x/index.html?rev=1897886&r1=1897885&r2=1897886&view=diff
==============================================================================
--- unomi/website/manual/1_4_x/index.html (original)
+++ unomi/website/manual/1_4_x/index.html Wed Feb 9 08:27:10 2022
@@ -4033,7 +4033,7 @@ information about the context for the cu
<p>We need to either retrieve (from the initial context we retrieved
previously using <code>cxs.sessionId</code>) or generate a session identifier
for our request since Unomi currently requires one.</p>
</li>
<li>
-<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId='"
class="bare">http://localhost:8181/cxs/context.json?sessionId='</a>; +
sessionId</code>. This URI requests context from Unomi, resulting in an updated
<code>cxs</code> object in the javascript global scope. The context server can
reply to this request either by returning a JSON-only object containing solely
the context information as is the case when the requested URI is
<code>context.json</code>. However, if the client requests
<code>context.js</code> then useful functions to interact with Unomi are added
to the <code>cxs</code> object in addition to the context information as
depicted above.</p>
+<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId=sessionId"
class="bare">http://localhost:8181/cxs/context.json?sessionId=sessionId</a></code>.
This URI requests context from Unomi, resulting in an updated <code>cxs</code>
object in the javascript global scope. The context server can reply to this
request either by returning a JSON-only object containing solely the context
information as is the case when the requested URI is <code>context.json</code>.
However, if the client requests <code>context.js</code> then useful functions
to interact with Unomi are added to the <code>cxs</code> object in addition to
the context information as depicted above.</p>
</li>
<li>
<p>We don’t need to provide any authentication at all to interact with
this part of Unomi since we only have access to read-only data (as well as
providing events as we shall see later on). If we had been using the REST API,
we would have needed to provide authentication information as well.</p>
Modified: unomi/website/manual/1_5_x/index.html
URL:
http://svn.apache.org/viewvc/unomi/website/manual/1_5_x/index.html?rev=1897886&r1=1897885&r2=1897886&view=diff
==============================================================================
--- unomi/website/manual/1_5_x/index.html (original)
+++ unomi/website/manual/1_5_x/index.html Wed Feb 9 08:27:10 2022
@@ -6844,7 +6844,7 @@ information about the context for the cu
<p>We need to either retrieve (from the initial context we retrieved
previously using <code>cxs.sessionId</code>) or generate a session identifier
for our request since Unomi currently requires one.</p>
</li>
<li>
-<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId='"
class="bare">http://localhost:8181/cxs/context.json?sessionId='</a>; +
sessionId</code>. This URI requests context from Unomi, resulting in an updated
<code>cxs</code> object in the javascript global scope. The context server can
reply to this request either by returning a JSON-only object containing solely
the context information as is the case when the requested URI is
<code>context.json</code>. However, if the client requests
<code>context.js</code> then useful functions to interact with Unomi are added
to the <code>cxs</code> object in addition to the context information as
depicted above.</p>
+<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId=sessionId"
class="bare">http://localhost:8181/cxs/context.json?sessionId=sessionId</a></code>.
This URI requests context from Unomi, resulting in an updated <code>cxs</code>
object in the javascript global scope. The context server can reply to this
request either by returning a JSON-only object containing solely the context
information as is the case when the requested URI is <code>context.json</code>.
However, if the client requests <code>context.js</code> then useful functions
to interact with Unomi are added to the <code>cxs</code> object in addition to
the context information as depicted above.</p>
</li>
<li>
<p>We don’t need to provide any authentication at all to interact with
this part of Unomi since we only have access to read-only data (as well as
providing events as we shall see later on). If we had been using the REST API,
we would have needed to provide authentication information as well.</p>
Modified: unomi/website/manual/latest/index.html
URL:
http://svn.apache.org/viewvc/unomi/website/manual/latest/index.html?rev=1897886&r1=1897885&r2=1897886&view=diff
==============================================================================
--- unomi/website/manual/latest/index.html (original)
+++ unomi/website/manual/latest/index.html Wed Feb 9 08:27:10 2022
@@ -77,7 +77,8 @@
<li><a href="#_multi_layer_scripting_filtering_system">3.8.1. Multi-layer
scripting filtering system</a></li>
<li><a href="#_scripts_and_expressions">3.8.2. Scripts and expressions</a></li>
<li><a href="#_scripting_expression_filtering_configuration_parameters">3.8.3.
Scripting expression filtering configuration parameters</a></li>
-<li><a href="#_scripting_roadmap">3.8.4. Scripting roadmap</a></li>
+<li><a href="#_groovy_actions">3.8.4. Groovy Actions</a></li>
+<li><a href="#_scripting_roadmap">3.8.5. Scripting roadmap</a></li>
</ul>
</li>
<li><a href="#_automatic_profile_merging">3.9. Automatic profile
merging</a></li>
@@ -359,8 +360,7 @@
<li><a href="#_deploying_into_an_existing_karaf_server">13.1.5. Deploying into
an existing Karaf server</a></li>
<li><a href="#_jdk_selection_on_mac_os_x">13.1.6. JDK Selection on Mac OS
X</a></li>
<li><a href="#_running_the_integration_tests">13.1.7. Running the integration
tests</a></li>
-<li><a href="#_running_the_performance_tests">13.1.8. Running the performance
tests</a></li>
-<li><a href="#_testing_with_an_example_page">13.1.9. Testing with an example
page</a></li>
+<li><a href="#_testing_with_an_example_page">13.1.8. Testing with an example
page</a></li>
</ul>
</li>
<li><a href="#_ssh_shell_commands">13.2. SSH Shell Commands</a>
@@ -567,7 +567,7 @@ Apache Unomi.</p>
endpoint. However you will need to send a body along with that request.
Here’s an example:</p>
</div>
<div class="paragraph">
-<p>Here is an example that will retrieve all the session and profile
properties.</p>
+<p>Here is an example that will retrieve all the session and profile
properties, as well as the profile’s segments and scores</p>
</div>
<div class="listingblock">
<div class="content">
@@ -582,7 +582,8 @@ endpoint. However you will need to send
},
"requiredProfileProperties":["*"],
"requiredSessionProperties":["*"],
- "requireSegments":true
+ "requireSegments":true,
+ "requireScores":true
}
EOF</code></pre>
</div>
@@ -997,7 +998,8 @@ the profile or session properties. If yo
of the context.js(on) servlet.</p>
</div>
<div class="paragraph">
-<p>Here is an example that will retrieve all the session and profile
properties.</p>
+<p>Here is an example that will retrieve all the session and profile
properties, as well as the profile’s segments and
+scores</p>
</div>
<div class="listingblock">
<div class="content">
@@ -1012,7 +1014,8 @@ of the context.js(on) servlet.</p>
},
"requiredProfileProperties":["*"],
"requiredSessionProperties":["*"],
- "requireSegments":true
+ "requireSegments":true,
+ "requireScores":true
}
EOF</code></pre>
</div>
@@ -2056,15 +2059,221 @@ org.apache.unomi.security.personalizatio
</div>
</div>
<div class="sect3">
-<h4 id="_scripting_roadmap">3.8.4. Scripting roadmap</h4>
+<h4 id="_groovy_actions">3.8.4. Groovy Actions</h4>
<div class="paragraph">
-<p>Scripting will probably undergo major changes in future versions of Apache
Unomi, possibly replacing MVEL with a
-more secure implementation of a scripting language, or possibly even removed
completely (see Groovy actions below).</p>
+<p>Groovy actions offer the ability to define a set of actions and action
types (aka action descriptors) purely from Groovy scripts defined at
runtime.</p>
</div>
<div class="paragraph">
-<p>It is recommended that scripting be avoided as in most cases it could be
replaced by custom action implementations,
-which are also possible using the Groovy Scripting language. The main
difference is in the deployment mechanism,
-Groovy actions or Java actions must be deployed as plugins, which require
system administrator access and permissions.</p>
+<p>Initially submitted to Unomi through a purpose-built REST API endpoint,
Groovy actions are then stored in Elasticsearch. When an event matches a rule
configured to execute an action, the corresponding action is fetched from
Elasticsearch and executed.</p>
+</div>
+<div class="sect4">
+<h5 id="_anatomy_of_a_groovy_action">Anatomy of a Groovy Action</h5>
+<div class="paragraph">
+<p>To be valid, a Groovy action must follow a particular convention which is
divided in two parts:</p>
+</div>
+<div class="ulist">
+<ul>
+<li>
+<p>An annotation used to define the associated action type</p>
+</li>
+<li>
+<p>The function to be executed</p>
+</li>
+</ul>
+</div>
+<div class="paragraph">
+<p>Placed right before the function, the â@Actionâ annotation contains a
set of parameter detailing how the action should be triggered.</p>
+</div>
+<table class="tableblock frame-all grid-all stretch">
+<caption class="title">Table 2. @Action annotation</caption>
+<colgroup>
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+<col style="width: 25%;">
+</colgroup>
+<thead>
+<tr>
+<th class="tableblock halign-left valign-top">Field name</th>
+<th class="tableblock halign-left valign-top">Type</th>
+<th class="tableblock halign-left valign-top">Required</th>
+<th class="tableblock halign-left valign-top">Description</th>
+</tr>
+</thead>
+<tbody>
+<tr>
+<td class="tableblock halign-left valign-top"><p class="tableblock">id</p></td>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">String</p></td>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">YES</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Id of the
action</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">actionExecutor</p></td>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">String</p></td>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">YES</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Action
executor contains the name of the script to call for the action type and must
be prefixed with â<strong>groovy:</strong>â. The prefix indicates to Unomi
which dispatcher to use when processing the action.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">name</p></td>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">String</p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Action
name</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">hidden</p></td>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">Boolean</p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">Define if
the action is hidden or not. It is usually used to hide objects in a
UI.</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">parameters</p></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">List<<a
href="https://github.com/apache/unomi/blob/master/extensions/groovy-actions/services/src/main/java/org/apache/unomi/groovy/actions/annotations/Parameter.java">Parameter</a>></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">The
parameters of the actions, also defined by annotations</p></td>
+</tr>
+<tr>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">systemTags</p></td>
+<td class="tableblock halign-left valign-top"><p
class="tableblock">List<String></p></td>
+<td class="tableblock halign-left valign-top"></td>
+<td class="tableblock halign-left valign-top"><p class="tableblock">A
(reserved) list of tags for the associated object. This is usually populated
through JSON descriptors and is not meant to be modified by end users. These
tags may include values that help classify associated objects.</p></td>
+</tr>
+</tbody>
+</table>
+<div class="paragraph">
+<p>The function contained within the Groovy Action must be called
<code>execute()</code> and its last instruction must be an integer.</p>
+</div>
+<div class="paragraph">
+<p>This integer serves as an indication whether the values of the session and
profile should be persisted. In general, the codes used are defined in the <a
href="https://github.com/apache/unomi/blob/master/api/src/main/java/org/apache/unomi/api/services/EventService.java">EventService
interface</a>.</p>
+</div>
+<div class="paragraph">
+<p>Each groovy actions extends by default a Base script
+<a
href="https://github.com/apache/unomi/blob/master/extensions/groovy-actions/services/src/main/resources/META-INF/base/BaseScript.groovy">defined
here</a></p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_rest_api">REST API</h5>
+<div class="paragraph">
+<p>Actions can be deployed/updated/deleted via the dedicated
<code>/cxs/groovyActions</code> rest endpoint.</p>
+</div>
+<div class="paragraph">
+<p>Deploy/update an Action:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-bash" data-lang="bash">curl -X
POST 'http://localhost:8181/cxs/groovyActions' \
+--user karaf:karaf \
+--form 'file=@"<file location>"'</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>A Groovy Action can be updated by submitting another Action with the same
id.</p>
+</div>
+<div class="paragraph">
+<p>Delete an Action:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-bash" data-lang="bash">curl -X
DELETE 'http://localhost:8181/cxs/groovyActions/<Action id>' \
+--user karaf:karaf</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Note that when a groovy action is deleted by the API, the action type
associated with this action will also be deleted.</p>
+</div>
+</div>
+<div class="sect4">
+<h5 id="_hello_world">Hello World!</h5>
+<div class="paragraph">
+<p>In this short example, weâre going to create a Groovy Action that will be
adding âHello world!â to the logs whenever a new view event is
triggered.</p>
+</div>
+<div class="paragraph">
+<p>The first step consists in creating the groovy script on your filesystem,
start by creating the file <code>hello-world.groovy</code>:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-groovy"
data-lang="groovy">@Action(id = "helloWorldGroovyAction",
+ actionExecutor = "groovy:helloWorldAction")
+ parameters = [@Parameter(id = "location", type = "string", multivalued
= false)])
+def execute() {
+ logger.info("Hello {}", action.getParameterValues().get("location"))
+ EventService.NO_CHANGE
+}</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>As the last instruction of the script is
<code>EventService.NO_CHANGE</code>, data will not be persisted.</p>
+</div>
+<div class="paragraph">
+<p>Once the action has been created you need to submit it to Unomi (from the
same folder as <code>hello-world.groovy</code>).</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-bash" data-lang="bash">curl -X
POST 'http://localhost:8181/cxs/groovyActions' \
+--user karaf:karaf \
+--form '[email protected]'</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Finally, register a rule to trigger execution of the groovy action:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-bash" data-lang="bash">curl -X
POST 'http://localhost:8181/cxs/rules' \
+--user karaf:karaf \
+--header 'Content-Type: application/json' \
+--data-raw '{
+ "metadata": {
+ "id": "scriptGroovyActionRule",
+ "name": "Test Groovy Action Rule",
+ "description": "A sample rule to test Groovy actions"
+ },
+ "condition": {
+ "type": "eventTypeCondition",
+ "parameterValues": {
+ "eventTypeId": "view"
+ }
+ },
+ "actions": [
+ {
+ "parameterValues": {
+ "location": "world!"
+ },
+ "type": "helloWorldAction"
+ }
+ ]
+}'</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>Note that this rule contains a âlocationâ parameter, with the value
âworld!â, which is then used in the log message triggered by the action.</p>
+</div>
+<div class="paragraph">
+<p>You can now use unomi to trigger a âviewâ event and see the
corresponding message in the Unomi logs.</p>
+</div>
+<div class="paragraph">
+<p>Once youâre done with the Hello World! action, it can be deleted using
the following command:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-bash" data-lang="bash">curl -X
DELETE 'http://localhost:8181/cxs/groovyActions/helloWorldGroovyAction' \
+--user karaf:karaf</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>And the corresponding rule can be deleted using the following command:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code class="language-bash" data-lang="bash">curl -X
DELETE 'http://localhost:8181/cxs/rules/scriptGroovyActionRule' \
+--user karaf:karaf</code></pre>
+</div>
+</div>
+</div>
+</div>
+<div class="sect3">
+<h4 id="_scripting_roadmap">3.8.5. Scripting roadmap</h4>
+<div class="paragraph">
+<p>Scripting will probably undergo major changes in future versions of Apache
Unomi, with the likely retirement of MVEL in favor of Groovy Actions detailed
above.</p>
</div>
<div class="paragraph">
<p>These changes will not happen on maintenance versions of Apache Unomi, only
in the next major version. Maintenance
@@ -3735,7 +3944,7 @@ results as the returned JSON is not beau
<p>Important : all URLs are relative to the private Apache Unomi URL, by
default: <a href="https://localhost:9443"
class="bare">https://localhost:9443</a></p>
</div>
<table class="tableblock frame-all grid-all stretch">
-<caption class="title">Table 2. Useful URLs</caption>
+<caption class="title">Table 3. Useful URLs</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
@@ -6886,7 +7095,7 @@ information about the context for the cu
<p>We need to either retrieve (from the initial context we retrieved
previously using <code>cxs.sessionId</code>) or generate a session identifier
for our request since Unomi currently requires one.</p>
</li>
<li>
-<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId='"
class="bare">http://localhost:8181/cxs/context.json?sessionId='</a>; +
sessionId</code>. This URI requests context from Unomi, resulting in an updated
<code>cxs</code> object in the javascript global scope. The context server can
reply to this request either by returning a JSON-only object containing solely
the context information as is the case when the requested URI is
<code>context.json</code>. However, if the client requests
<code>context.js</code> then useful functions to interact with Unomi are added
to the <code>cxs</code> object in addition to the context information as
depicted above.</p>
+<p>We’re calling the <code>ContextServlet</code> using the default
install URI, specifying the session identifier: <code><a
href="http://localhost:8181/cxs/context.json?sessionId=sessionId"
class="bare">http://localhost:8181/cxs/context.json?sessionId=sessionId</a></code>.
This URI requests context from Unomi, resulting in an updated <code>cxs</code>
object in the javascript global scope. The context server can reply to this
request either by returning a JSON-only object containing solely the context
information as is the case when the requested URI is <code>context.json</code>.
However, if the client requests <code>context.js</code> then useful functions
to interact with Unomi are added to the <code>cxs</code> object in addition to
the context information as depicted above.</p>
</li>
<li>
<p>We don’t need to provide any authentication at all to interact with
this part of Unomi since we only have access to read-only data (as well as
providing events as we shall see later on). If we had been using the REST API,
we would have needed to provide authentication information as well.</p>
@@ -7024,7 +7233,7 @@ conditions and we want to know which is
"source": null,
"requireSegments": false,
"requiredProfileProperties": null,
- "requiredSessionProperties": null,
+ "requiredSessionProperties": [ "unomiControlGroups" ],
"events": null,
"filters": null,
"personalizations": [
@@ -7032,7 +7241,13 @@ conditions and we want to know which is
"id": "gender-test",
"strategy": "matching-first",
"strategyOptions": {
- "fallback": "var2"
+ "fallback": "var2",
+ "controlGroup" : {
+ "percentage" : 10.0,
+ "displayName" : "Gender test control group",
+ "path" : "/gender-test",
+ "storeInSession" : true
+ }
},
"contents": [
{
@@ -7070,8 +7285,7 @@ conditions and we want to know which is
<div class="paragraph">
<p>In the above example, we basically setup two variants : <code>var1</code>
and <code>var2</code> and setup the <code>var2</code> to be the fallback variant
in case no variant is matched. We could of course specify more than a variant.
The <code>strategy</code> indicates to the
-personalization service how to calculate the "winning" variant. In this case
the strategy <code>matching-first</code> will return
-the first variant that matches the current profile.</p>
+personalization service how to calculate the "winning" variant. In this case
the strategy <code>matching-first</code> will return variants that match the
current profile. We also use the <code>controlGroups</code> option to specify
that we want to have a control group for this personalization. The
<code>10.0</code> percentage value represents 10% (0.0 to 100.0) of traffic
that will be assigned randomly to the control group. The control group will be
stored in the profile and the session of the visitors if they were assigned to
it. We also specify that we store the control group in the session (by default
it is stored in the profile)</p>
</div>
<div class="paragraph">
<p>Currently the following strategies are available:</p>
@@ -7079,10 +7293,10 @@ the first variant that matches the curre
<div class="ulist">
<ul>
<li>
-<p><code>matching-first</code>: will return the first matching variant.</p>
+<p><code>matching-first</code>: will return the variant IDs that match the
current profile (using the initial content order)</p>
</li>
<li>
-<p><code>random</code>: will return a random variant</p>
+<p><code>random</code>: will return a shuffled list of variant IDs (ignoring
any conditions)</p>
</li>
<li>
<p><code>score-sorted</code>: allows to sort the variants based on scores
associated with the filtering conditions, effectively
@@ -7099,7 +7313,16 @@ sorting them by the highest scoring cond
"profileId": "01060c4c-a055-4c8f-9692-8a699d0c434a",
"sessionId": "demo-session-id",
"profileProperties": null,
- "sessionProperties": null,
+ "sessionProperties": {
+ "unomiControlGroups": [
+ {
+ "id": "previousPerso",
+ "displayName": "Previous perso",
+ "path": "/home/previousPerso.html",
+ "timeStamp": "2021-12-15T13:52:38Z"
+ }
+ ]
+ },
"profileSegments": null,
"filteringResults": null,
"processedEvents": 0,
@@ -7115,6 +7338,9 @@ sorting them by the highest scoring cond
}</code></pre>
</div>
</div>
+<div class="paragraph">
+<p>In the above example we can see the profile and session were assigned to
other control groups but not the current one (the ids are different).</p>
+</div>
</div>
<div class="sect5">
<h6 id="_overrides">Overrides</h6>
@@ -7899,7 +8125,7 @@ the MVN_HOME/bin directory.</p>
</div>
<div class="listingblock">
<div class="content">
-<pre class="highlight"><code> $> mvn -P
\!integration-tests,\!performance-tests clean install</code></pre>
+<pre class="highlight"><code> $> mvn -P \!integration-tests clean
install</code></pre>
</div>
</div>
<div class="paragraph">
@@ -8107,30 +8333,7 @@ to use these tests is to run them from a
</div>
</div>
<div class="sect3">
-<h4 id="_running_the_performance_tests">13.1.8. Running the performance
tests</h4>
-<div class="paragraph">
-<p>Performance tests are based on Gatling. You need to have a running context
server or cluster of servers before
-executing the tests.</p>
-</div>
-<div class="paragraph">
-<p>Test parameteres are editable in the
performance-tests/src/test/scala/unomi/Parameters.scala file. baseUrls should
-contains the URLs of all your cluster nodes</p>
-</div>
-<div class="paragraph">
-<p>Run the test by using the gatling.conf file in
performance-tests/src/test/resources :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code> export
GATLING_CONF=<path>/performance-tests/src/test/resources
- gatling.sh</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>Reports are generated in performance-tests/target/results.</p>
-</div>
-</div>
-<div class="sect3">
-<h4 id="_testing_with_an_example_page">13.1.9. Testing with an example
page</h4>
+<h4 id="_testing_with_an_example_page">13.1.8. Testing with an example
page</h4>
<div class="paragraph">
<p>A default test page is provided at the following URL:</p>
</div>
@@ -8208,7 +8411,7 @@ ARGUMENTS
<p>The commands control the lifecycle of the Apache Unomi server and are used
to migrate, start or stop the server.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
-<caption class="title">Table 3. Table Lifecycle commands</caption>
+<caption class="title">Table 4. Table Lifecycle commands</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">
@@ -8251,7 +8454,7 @@ ARGUMENTS
<p>These commands are available once the application is running. If an
argument is between brackets [] it means it is optional.</p>
</div>
<table class="tableblock frame-all grid-all stretch">
-<caption class="title">Table 4. Table Runtime commands</caption>
+<caption class="title">Table 5. Table Runtime commands</caption>
<colgroup>
<col style="width: 33.3333%;">
<col style="width: 33.3333%;">