You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@unomi.apache.org by sh...@apache.org on 2018/11/15 12:22:04 UTC

svn commit: r1846646 [2/3] - in /incubator/unomi/website/manual: 1_1_x/ 1_2_x/ 1_2_x/connectors/ 1_2_x/samples/ 1_3_x/ 1_3_x/connectors/ 1_3_x/samples/ latest/ latest/connectors/ latest/samples/

Modified: incubator/unomi/website/manual/1_3_x/index.html
URL: http://svn.apache.org/viewvc/incubator/unomi/website/manual/1_3_x/index.html?rev=1846646&r1=1846645&r2=1846646&view=diff
==============================================================================
--- incubator/unomi/website/manual/1_3_x/index.html (original)
+++ incubator/unomi/website/manual/1_3_x/index.html Thu Nov 15 12:22:03 2018
@@ -4,7 +4,7 @@
 <meta charset="UTF-8">
 <!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=edge"><![endif]-->
 <meta name="viewport" content="width=device-width, initial-scale=1.0">
-<meta name="generator" content="Asciidoctor 1.5.6.1">
+<meta name="generator" content="Asciidoctor 1.5.7.1">
 <meta name="author" content="Apache Software Foundation">
 <title>Apache Unomi 1.x - Documentation</title>
 <link rel="stylesheet" href="./apache.css">
@@ -18,92 +18,56 @@
 <div id="toc" class="toc2">
 <div id="toctitle">Table of Contents</div>
 <ul class="sectlevel1">
-<li><a href="#_concepts">1. Concepts</a>
-<ul class="sectlevel2">
-<li><a href="#_items_and_types">1.1. Items and types</a></li>
-<li><a href="#_events">1.2. Events</a></li>
-<li><a href="#_profiles">1.3. Profiles</a></li>
-<li><a href="#_sessions">1.4. Sessions</a></li>
-</ul>
-</li>
-<li><a href="#_extending_unomi_via_plugins">2. Extending Unomi via plugins</a>
-<ul class="sectlevel2">
-<li><a href="#_types_vs_instances">2.1. Types vs. instances</a></li>
-<li><a href="#_plugin_structure">2.2. Plugin structure</a></li>
-<li><a href="#_extension_points">2.3. Extension points</a>
+<li><a href="#_quick_start">1. Quick start</a>
 <ul class="sectlevel3">
-<li><a href="#_actiontype">2.3.1. ActionType</a></li>
-<li><a href="#_conditiontype">2.3.2. ConditionType</a></li>
-<li><a href="#_persona">2.3.3. Persona</a></li>
-<li><a href="#_propertymergestrategytype">2.3.4. PropertyMergeStrategyType</a></li>
-<li><a href="#_propertytype">2.3.5. PropertyType</a></li>
-<li><a href="#_rule">2.3.6. Rule</a></li>
-<li><a href="#_scoring">2.3.7. Scoring</a></li>
-<li><a href="#_segments">2.3.8. Segments</a></li>
-<li><a href="#_tag">2.3.9. Tag</a></li>
-<li><a href="#_valuetype">2.3.10. ValueType</a></li>
-</ul>
-</li>
-<li><a href="#_other_unomi_entities">2.4. Other Unomi entities</a>
-<ul class="sectlevel3">
-<li><a href="#_userlist">2.4.1. UserList</a></li>
-<li><a href="#_goal">2.4.2. Goal</a></li>
-<li><a href="#_campaign">2.4.3. Campaign</a></li>
-</ul>
-</li>
+<li><a href="#_five_minutes_quickstart">1.1. Five Minutes QuickStart</a></li>
 </ul>
 </li>
-<li><a href="#_quick_start">3. Quick start</a>
+<li><a href="#_concepts">2. Concepts</a>
 <ul class="sectlevel2">
-<li><a href="#_building">3.1. Building</a>
-<ul class="sectlevel3">
-<li><a href="#_initial_setup">3.1.1. Initial Setup</a></li>
-<li><a href="#_building_2">3.1.2. Building</a></li>
-<li><a href="#_installing_an_elasticsearch_server">3.1.3. Installing an ElasticSearch server</a></li>
-<li><a href="#_deploying_the_generated_binary_package">3.1.4. Deploying the generated binary package</a></li>
-<li><a href="#_deploying_into_an_existing_karaf_server">3.1.5. Deploying into an existing Karaf server</a></li>
-<li><a href="#_jdk_selection_on_mac_os_x">3.1.6. JDK Selection on Mac OS X</a></li>
-<li><a href="#_running_the_integration_tests">3.1.7. Running the integration tests</a></li>
-<li><a href="#_running_the_performance_tests">3.1.8. Running the performance tests</a></li>
-<li><a href="#_testing_with_an_example_page">3.1.9. Testing with an example page</a></li>
-<li><a href="#_integrating_onto_a_page">3.1.10. Integrating onto a page</a></li>
+<li><a href="#_items_and_types">2.1. Items and types</a></li>
+<li><a href="#_events">2.2. Events</a></li>
+<li><a href="#_profiles">2.3. Profiles</a></li>
+<li><a href="#_sessions">2.4. Sessions</a></li>
 </ul>
 </li>
-<li><a href="#_getting_started_with_unomi">3.2. Getting started with Unomi</a>
+<li><a href="#_setup">3. Setup</a>
+<ul class="sectlevel2">
+<li><a href="#_getting_started_with_unomi">3.1. Getting started with Unomi</a>
 <ul class="sectlevel3">
-<li><a href="#_prerequisites">3.2.1. Prerequisites</a></li>
-<li><a href="#_running_unomi">3.2.2. Running Unomi</a></li>
+<li><a href="#_prerequisites">3.1.1. Prerequisites</a></li>
+<li><a href="#_running_unomi">3.1.2. Running Unomi</a></li>
 </ul>
 </li>
-<li><a href="#_configuration">3.3. Configuration</a>
+<li><a href="#_configuration">3.2. Configuration</a>
 <ul class="sectlevel3">
-<li><a href="#_changing_the_default_configuration">3.3.1. Changing the default configuration</a></li>
-<li><a href="#_secured_events_configuration">3.3.2. Secured events configuration</a></li>
-<li><a href="#_installing_the_maxmind_geoiplite2_ip_lookup_database">3.3.3. Installing the MaxMind GeoIPLite2 IP lookup database</a></li>
-<li><a href="#_installing_geonames_database">3.3.4. Installing Geonames database</a></li>
-<li><a href="#_rest_api_security">3.3.5. REST API Security</a></li>
-<li><a href="#_automatic_profile_merging">3.3.6. Automatic profile merging</a></li>
-<li><a href="#_securing_a_production_environment">3.3.7. Securing a production environment</a></li>
-<li><a href="#_integrating_with_an_apache_http_web_server">3.3.8. Integrating with an Apache HTTP web server</a></li>
-<li><a href="#_changing_the_default_tracking_location">3.3.9. Changing the default tracking location</a></li>
-<li><a href="#_apache_karaf_ssh_console">3.3.10. Apache Karaf SSH Console</a></li>
-<li><a href="#_elasticsearch_x_pack_support">3.3.11. ElasticSearch X-Pack Support</a></li>
+<li><a href="#_changing_the_default_configuration">3.2.1. Changing the default configuration</a></li>
+<li><a href="#_secured_events_configuration">3.2.2. Secured events configuration</a></li>
+<li><a href="#_installing_the_maxmind_geoiplite2_ip_lookup_database">3.2.3. Installing the MaxMind GeoIPLite2 IP lookup database</a></li>
+<li><a href="#_installing_geonames_database">3.2.4. Installing Geonames database</a></li>
+<li><a href="#_rest_api_security">3.2.5. REST API Security</a></li>
+<li><a href="#_automatic_profile_merging">3.2.6. Automatic profile merging</a></li>
+<li><a href="#_securing_a_production_environment">3.2.7. Securing a production environment</a></li>
+<li><a href="#_integrating_with_an_apache_http_web_server">3.2.8. Integrating with an Apache HTTP web server</a></li>
+<li><a href="#_changing_the_default_tracking_location">3.2.9. Changing the default tracking location</a></li>
+<li><a href="#_apache_karaf_ssh_console">3.2.10. Apache Karaf SSH Console</a></li>
+<li><a href="#_elasticsearch_x_pack_support">3.2.11. ElasticSearch X-Pack Support</a></li>
 </ul>
 </li>
-<li><a href="#_important">3.4. Important !</a></li>
-<li><a href="#_installation_steps">3.5. Installation steps</a></li>
+<li><a href="#_important">3.3. Important !</a></li>
+<li><a href="#_installation_steps">3.4. Installation steps</a></li>
 </ul>
 </li>
-<li><a href="#_sample">4. Sample</a>
+<li><a href="#_integration_samples">4. Integration samples</a>
 <ul class="sectlevel2">
 <li><a href="#_samples">4.1. Samples</a></li>
-<li><a href="#_login_samples">4.2. Login samples</a>
+<li><a href="#_login_sample">4.2. Login sample</a>
 <ul class="sectlevel3">
 <li><a href="#_warning">4.2.1. Warning !</a></li>
 <li><a href="#_installing_the_samples">4.2.2. Installing the samples</a></li>
 </ul>
 </li>
-<li><a href="#_twitter_samples">4.3. Twitter samples</a>
+<li><a href="#_twitter_sample">4.3. Twitter sample</a>
 <ul class="sectlevel3">
 <li><a href="#_overview">4.3.1. Overview</a></li>
 <li><a href="#_interacting_with_the_context_server">4.3.2. Interacting with the context server</a></li>
@@ -118,7 +82,7 @@
 </li>
 <li><a href="#_conclusion">4.5. Conclusion</a></li>
 <li><a href="#_annex">4.6. Annex</a></li>
-<li><a href="#_weather_update_samples">4.7. Weather update samples</a></li>
+<li><a href="#_weather_update_sample">4.7. Weather update sample</a></li>
 </ul>
 </li>
 <li><a href="#_connectors">5. Connectors</a>
@@ -128,15 +92,20 @@
 <li><a href="#_call_for_contributors">5.1.1. Call for contributors</a></li>
 </ul>
 </li>
-<li><a href="#_apache_unomi_salesforce_connector">5.2. Apache Unomi Salesforce Connector</a>
+<li><a href="#_salesforce_connector">5.2. Salesforce Connector</a>
 <ul class="sectlevel3">
 <li><a href="#_getting_started">5.2.1. Getting started</a></li>
-<li><a href="#_upgrading_the_salesforce_connectors">5.2.2. Upgrading the Salesforce connectors</a></li>
+<li><a href="#_hot_deploying_updates_to_the_salesforce_connector_for_developers">5.2.2. Hot-deploying updates to the Salesforce connector (for developers)</a></li>
 <li><a href="#_using_the_salesforce_workbench_for_testing_rest_api">5.2.3. Using the Salesforce Workbench for testing REST API</a></li>
 <li><a href="#_setting_up_streaming_push_queries">5.2.4. Setting up Streaming Push queries</a></li>
 <li><a href="#_executing_the_unit_tests">5.2.5. Executing the unit tests</a></li>
 </ul>
 </li>
+<li><a href="#_mailchimp_connector">5.3. MailChimp Connector</a>
+<ul class="sectlevel3">
+<li><a href="#_getting_started_2">5.3.1. Getting started</a></li>
+</ul>
+</li>
 </ul>
 </li>
 <li><a href="#_cluster_setup">6. Cluster setup</a>
@@ -149,31 +118,71 @@
 </li>
 </ul>
 </li>
-<li><a href="#_custom_extensions">7. Custom extensions</a>
+<li><a href="#_consent_api">7. Consent API</a>
 <ul class="sectlevel2">
-<li><a href="#_custom_extensions_2">7.1. Custom extensions</a>
+<li><a href="#_consent_api_2">7.1. Consent API</a>
 <ul class="sectlevel3">
-<li><a href="#_creating_an_extension">7.1.1. Creating an extension</a></li>
-<li><a href="#_deployment_and_custom_definition">7.1.2. Deployment and custom definition</a></li>
-<li><a href="#_predefined_segments">7.1.3. Predefined segments</a></li>
-<li><a href="#_predefined_rules">7.1.4. Predefined rules</a></li>
-<li><a href="#_predefined_properties">7.1.5. Predefined properties</a></li>
-<li><a href="#_predefined_child_conditions">7.1.6. Predefined child conditions</a></li>
-<li><a href="#_predefined_personas">7.1.7. Predefined personas</a></li>
-<li><a href="#_custom_actions">7.1.8. Custom actions</a></li>
-<li><a href="#_custom_conditions">7.1.9. Custom conditions</a></li>
+<li><a href="#_profiles_with_consents">7.1.1. Profiles with consents</a></li>
+<li><a href="#_consent_type_definitions">7.1.2. Consent type definitions</a></li>
+<li><a href="#_creating_update_a_visitor_consent">7.1.3. Creating / update a visitor consent</a></li>
+<li><a href="#_how_it_works_internally">7.1.4. How it works (internally)</a></li>
 </ul>
 </li>
+<li><a href="#_building">7.2. Building</a>
+<ul class="sectlevel3">
+<li><a href="#_initial_setup">7.2.1. Initial Setup</a></li>
+<li><a href="#_building_2">7.2.2. Building</a></li>
+<li><a href="#_installing_an_elasticsearch_server">7.2.3. Installing an ElasticSearch server</a></li>
+<li><a href="#_deploying_the_generated_binary_package">7.2.4. Deploying the generated binary package</a></li>
+<li><a href="#_deploying_into_an_existing_karaf_server">7.2.5. Deploying into an existing Karaf server</a></li>
+<li><a href="#_jdk_selection_on_mac_os_x">7.2.6. JDK Selection on Mac OS X</a></li>
+<li><a href="#_running_the_integration_tests">7.2.7. Running the integration tests</a></li>
+<li><a href="#_running_the_performance_tests">7.2.8. Running the performance tests</a></li>
+<li><a href="#_testing_with_an_example_page">7.2.9. Testing with an example page</a></li>
+<li><a href="#_integrating_onto_a_page">7.2.10. Integrating onto a page</a></li>
 </ul>
 </li>
-<li><a href="#_consent_api">8. Consent API</a>
-<ul class="sectlevel2">
-<li><a href="#_consent_api_2">8.1. Consent API</a>
+<li><a href="#_ssh_shell_commands">7.3. SSH Shell Commands</a>
 <ul class="sectlevel3">
-<li><a href="#_profiles_with_consents">8.1.1. Profiles with consents</a></li>
-<li><a href="#_consent_type_definitions">8.1.2. Consent type definitions</a></li>
-<li><a href="#_creating_update_a_visitor_consent">8.1.3. Creating / update a visitor consent</a></li>
-<li><a href="#_how_it_works_internally">8.1.4. How it works (internally)</a></li>
+<li><a href="#_using_the_shell">7.3.1. Using the shell</a></li>
+<li><a href="#_lifecycle_commands">7.3.2. Lifecycle commands</a></li>
+<li><a href="#_runtime_commands">7.3.3. Runtime commands</a></li>
+</ul>
+</li>
+<li><a href="#_types_vs_instances">7.4. Types vs. instances</a></li>
+<li><a href="#_plugin_structure">7.5. Plugin structure</a></li>
+<li><a href="#_extension_points">7.6. Extension points</a>
+<ul class="sectlevel3">
+<li><a href="#_actiontype">7.6.1. ActionType</a></li>
+<li><a href="#_conditiontype">7.6.2. ConditionType</a></li>
+<li><a href="#_persona">7.6.3. Persona</a></li>
+<li><a href="#_propertymergestrategytype">7.6.4. PropertyMergeStrategyType</a></li>
+<li><a href="#_propertytype">7.6.5. PropertyType</a></li>
+<li><a href="#_rule">7.6.6. Rule</a></li>
+<li><a href="#_scoring">7.6.7. Scoring</a></li>
+<li><a href="#_segments">7.6.8. Segments</a></li>
+<li><a href="#_tag">7.6.9. Tag</a></li>
+<li><a href="#_valuetype">7.6.10. ValueType</a></li>
+</ul>
+</li>
+<li><a href="#_other_unomi_entities">7.7. Other Unomi entities</a>
+<ul class="sectlevel3">
+<li><a href="#_userlist">7.7.1. UserList</a></li>
+<li><a href="#_goal">7.7.2. Goal</a></li>
+<li><a href="#_campaign">7.7.3. Campaign</a></li>
+</ul>
+</li>
+<li><a href="#_custom_extensions">7.8. Custom extensions</a>
+<ul class="sectlevel3">
+<li><a href="#_creating_an_extension">7.8.1. Creating an extension</a></li>
+<li><a href="#_deployment_and_custom_definition">7.8.2. Deployment and custom definition</a></li>
+<li><a href="#_predefined_segments">7.8.3. Predefined segments</a></li>
+<li><a href="#_predefined_rules">7.8.4. Predefined rules</a></li>
+<li><a href="#_predefined_properties">7.8.5. Predefined properties</a></li>
+<li><a href="#_predefined_child_conditions">7.8.6. Predefined child conditions</a></li>
+<li><a href="#_predefined_personas">7.8.7. Predefined personas</a></li>
+<li><a href="#_custom_actions">7.8.8. Custom actions</a></li>
+<li><a href="#_custom_conditions">7.8.9. Custom conditions</a></li>
 </ul>
 </li>
 </ul>
@@ -192,13 +201,56 @@
 </div>
 </div>
 <div class="sect1">
-<h2 id="_concepts">1. Concepts</h2>
+<h2 id="_quick_start">1. Quick start</h2>
+<div class="sectionbody">
+<div class="sect3">
+<h4 id="_five_minutes_quickstart">1.1. Five Minutes QuickStart</h4>
+<div class="paragraph">
+<p>1) Install JDK 8 (<a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html" class="bare">http://www.oracle.com/technetwork/java/javase/downloads/index.html</a>) and make sure you set the
+JAVA_HOME variable <a href="https://docs.oracle.com/cd/E19182-01/820-7851/inst_cli_jdk_javahome_t/" class="bare">https://docs.oracle.com/cd/E19182-01/820-7851/inst_cli_jdk_javahome_t/</a></p>
+</div>
+<div class="paragraph">
+<p>2) Download ElasticSearch here : <a href="https://www.elastic.co/downloads/past-releases/elasticsearch-5-6-3" class="bare">https://www.elastic.co/downloads/past-releases/elasticsearch-5-6-3</a> (please &lt;strong&gt;make sure&lt;/strong&gt; you use the proper version : 5.6.3)</p>
+</div>
+<div class="paragraph">
+<p>3) Uncompress it and change the <code>config/elasticsearch.yml</code> to include the following config : &lt;code&gt;cluster.name: contextElasticSearch&lt;/code&gt;</p>
+</div>
+<div class="paragraph">
+<p>4) Launch ElasticSearch using : <code>bin/elasticsearch</code></p>
+</div>
+<div class="paragraph">
+<p>5) Download Apache Unomi here : <a href="http://unomi.incubator.apache.org/download.html" class="bare">http://unomi.incubator.apache.org/download.html</a></p>
+</div>
+<div class="paragraph">
+<p>6) Start it using : <code>./bin/karaf</code></p>
+</div>
+<div class="paragraph">
+<p>7) Start the Apache Unomi packages using <code>unomi:start</code> in the Apache Karaf Shell</p>
+</div>
+<div class="paragraph">
+<p>8) Wait for startup to complete</p>
+</div>
+<div class="paragraph">
+<p>9) Try accessing <a href="https://localhost:9443/cxs/cluster" class="bare">https://localhost:9443/cxs/cluster</a> with username/password: <code>karaf/karaf</code> . You might get a certificate warning in your browser, just accept it despite the warning it is safe.</p>
+</div>
+<div class="paragraph">
+<p>10) Request your first context by simply accessing : <a href="http://localhost:8181/context.js?sessionId=1234" class="bare">http://localhost:8181/context.js?sessionId=1234</a></p>
+</div>
+<div class="paragraph">
+<p>11) If something goes wrong, you should check the logs in <code>./data/log/karaf.log</code>. If you get errors on ElasticSearch,
+make sure you are using the proper version.</p>
+</div>
+</div>
+</div>
+</div>
+<div class="sect1">
+<h2 id="_concepts">2. Concepts</h2>
 <div class="sectionbody">
 <div class="paragraph">
 <p>Apache Unomi gathers information about users actions, information that is processed and stored by Unomi services. The collected information can then be used to personalize content, derive insights on user behavior, categorize the user profiles into segments along user-definable dimensions or acted upon by algorithms.</p>
 </div>
 <div class="sect2">
-<h3 id="_items_and_types">1.1. Items and types</h3>
+<h3 id="_items_and_types">2.1. Items and types</h3>
 <div class="paragraph">
 <p>Unomi structures the information it collects using the concept of <code>Item</code> which provides the base information (an identifier and a type) the context server needs to process and store the data. Items are persisted according to their type (structure) and identifier (identity). This base structure can be extended, if needed, using properties in the form of key-value pairs.</p>
 </div>
@@ -254,7 +306,7 @@
 </div>
 </div>
 <div class="sect2">
-<h3 id="_events">1.2. Events</h3>
+<h3 id="_events">2.2. Events</h3>
 <div class="paragraph">
 <p>Users' actions are conveyed from clients to the context server using events. Of course, the required information depends on what is collected and users' interactions with the observed systems but events minimally provide a type, a scope and source and target items. Additionally, events are timestamped. Conceptually, an event can be seen as a sentence, the event&#8217;s type being the verb, the source the subject and the target the object.</p>
 </div>
@@ -313,7 +365,7 @@
 </div>
 </div>
 <div class="sect2">
-<h3 id="_profiles">1.3. Profiles</h3>
+<h3 id="_profiles">2.3. Profiles</h3>
 <div class="paragraph">
 <p>By processing events, Unomi progressively builds a picture of who the user is and how they behave. This knowledge is embedded in <code>Profile</code> object. A profile is an <code>Item</code> with any number of properties and optional segments and scores. Unomi provides default properties to cover common data (name, last name, age, email, etc.) as well as default segments to categorize users. Unomi users are, however, free and even encouraged to create additional properties and segments to better suit their needs.</p>
 </div>
@@ -325,7 +377,7 @@
 </div>
 </div>
 <div class="sect2">
-<h3 id="_sessions">1.4. Sessions</h3>
+<h3 id="_sessions">2.4. Sessions</h3>
 <div class="paragraph">
 <p>A session represents a time-bounded interaction between a user (via their associated profile) and a Unomi-enabled application. A session represents the sequence of actions the user performed during its duration. For this reason, events are associated with the session during which they occurred. In the context of web applications, sessions are usually linked to HTTP sessions.</p>
 </div>
@@ -333,2157 +385,2572 @@
 </div>
 </div>
 <div class="sect1">
-<h2 id="_extending_unomi_via_plugins">2. Extending Unomi via plugins</h2>
+<h2 id="_setup">3. Setup</h2>
 <div class="sectionbody">
-<div class="paragraph">
-<p>Unomi is architected so that users can provided extensions in the form of plugins.</p>
-</div>
 <div class="sect2">
-<h3 id="_types_vs_instances">2.1. Types vs. instances</h3>
+<h3 id="_getting_started_with_unomi">3.1. Getting started with Unomi</h3>
 <div class="paragraph">
-<p>Several extension points in Unomi rely on the concept of type: the extension defines a prototype for what the actual items will be once parameterized with values known only at runtime. This is similar to the concept of classes in object-oriented programming: types define classes, providing the expected structure and which fields are expected to be provided at runtime, that are then instantiated when needed with actual values.</p>
-</div>
+<p>We will first get you up and running with an example. We will then lift the corner of the cover somewhat and explain in greater details what just happened.</p>
 </div>
-<div class="sect2">
-<h3 id="_plugin_structure">2.2. Plugin structure</h3>
+<div class="sect3">
+<h4 id="_prerequisites">3.1.1. Prerequisites</h4>
 <div class="paragraph">
-<p>Being built on top of Apache Karaf, Unomi leverages OSGi to support plugins. A Unomi plugin is, thus, an OSGi bundle specifying some specific metadata to tell Unomi the kind of entities it provides. A plugin can provide the following entities to extend Unomi, each with its associated definition (as a JSON file), located in a specific spot within the <code>META-INF/cxs/</code> directory of the bundle JAR file:</p>
+<p>This document assumes that you are already familiar with Unomi&#8217;s <a href="#_concepts">concepts</a>. On the technical side, we also assume working knowledge of <a href="https://git-scm.com/">git</a> to be able to retrieve the code for Unomi and the example. Additionnally, you will require a working Java 7 or above install. Refer to <a href="http://www.oracle.com/technetwork/java/javase/">http://www.oracle.com/technetwork/java/javase/</a> for details on how to download and install Java SE 7 or greater.</p>
 </div>
-<table class="tableblock frame-all grid-all spread">
-<colgroup>
-<col style="width: 50%;">
-<col style="width: 50%;">
-</colgroup>
-<thead>
-<tr>
-<th class="tableblock halign-left valign-top">Entity</th>
-<th class="tableblock halign-left valign-top">Location in <code>cxs</code> directory</th>
-</tr>
-</thead>
-<tbody>
-<tr>
-<td class="tableblock halign-left valign-top"><p class="tableblock">ActionType</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">actions</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p class="tableblock">ConditionType</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">conditions</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p class="tableblock">Persona</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">personas</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p class="tableblock">PropertyMergeStrategyType</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">mergers</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p class="tableblock">PropertyType</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">properties then profiles or sessions subdirectory then <code>&lt;category name&gt;</code> directory</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p class="tableblock">Rule</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">rules</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p class="tableblock">Scoring</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">scorings</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p class="tableblock">Segment</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">segments</p></td>
-</tr>
-<tr>
-<td class="tableblock halign-left valign-top"><p class="tableblock">ValueType</p></td>
-<td class="tableblock halign-left valign-top"><p class="tableblock">values</p></td>
-</tr>
-</tbody>
-</table>
-<div class="paragraph">
-<p><a href="http://aries.apache.org/modules/blueprint.html">Blueprint</a> is used to declare what the plugin provides and inject any required dependency. The Blueprint file is located, as usual, at <code>OSGI-INF/blueprint/blueprint.xml</code> in the bundle JAR file.</p>
 </div>
+<div class="sect3">
+<h4 id="_running_unomi">3.1.2. Running Unomi</h4>
+<div class="sect4">
+<h5 id="_start_unomi">Start Unomi</h5>
 <div class="paragraph">
-<p>The plugin otherwise follows a regular maven project layout and should depend on the Unomi API maven artifact:</p>
+<p>Start Unomi according to the <a href="#_5-min-quickstart">5 minute quick start</a> or by compiling using the building <a href="building-and-deploying.html#Deploying_the_generated_package">instructions</a>. Once you have Karaf running,
+ you should wait until you see the following messages on the Karaf console:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code class="language-xml" data-lang="xml">&lt;dependency&gt;
-    &lt;groupId&gt;org.apache.unomi&lt;/groupId&gt;
-    &lt;artifactId&gt;unomi-api&lt;/artifactId&gt;
-    &lt;version&gt;...&lt;/version&gt;
-&lt;/dependency&gt;</code></pre>
-</div>
+<pre class="highlight"><code>Initializing user list service endpoint...
+Initializing geonames service endpoint...
+Initializing segment service endpoint...
+Initializing scoring service endpoint...
+Initializing campaigns service endpoint...
+Initializing rule service endpoint...
+Initializing profile service endpoint...
+Initializing cluster service endpoint...</code></pre>
 </div>
-<div class="paragraph">
-<p>Some plugins consists only of JSON definitions that are used to instantiate the appropriate structures at runtime while some more involved plugins provide code that extends Unomi in deeper ways.</p>
 </div>
 <div class="paragraph">
-<p>In both cases, plugins can provide more that one type of extension. For example, a plugin could provide both `ActionType`s and `ConditionType`s.</p>
+<p>This indicates that all the Unomi services are started and ready to react to requests. You can then open a browser and go to <code><a href="http://localhost:8181/cxs" class="bare">http://localhost:8181/cxs</a></code> to see the list of
+available RESTful services or retrieve an initial context at <code><a href="http://localhost:8181/context.json" class="bare">http://localhost:8181/context.json</a></code> (which isn&#8217;t very useful at this point).</p>
 </div>
 </div>
-<div class="sect2">
-<h3 id="_extension_points">2.3. Extension points</h3>
-<div class="sect3">
-<h4 id="_actiontype">2.3.1. ActionType</h4>
+<div class="sect4">
+<h5 id="_request_examples">Request examples</h5>
+<div class="sect5">
+<h6 id="_retrieving_your_first_context">Retrieving your first context</h6>
 <div class="paragraph">
-<p><code>ActionType`s define new actions that can be used as consequences of Rules being triggered. When a rule triggers, it creates new actions based on the event data and the rule internal processes, providing values for parameters defined in the associated `ActionType</code>. Example actions include: “Set user property x to value y” or “Send a message to service x”.</p>
-</div>
+<p>You can retrieve a context using curl like this :</p>
 </div>
-<div class="sect3">
-<h4 id="_conditiontype">2.3.2. ConditionType</h4>
-<div class="paragraph">
-<p>`ConditionType`s define new conditions that can be applied to items (for example to decide whether a rule needs to be triggered or if a profile is considered as taking part in a campaign) or to perform queries against the stored Unomi data. They may be implemented in Java when attempting to define a particularly complex test or one that can better be optimized by coding it. They may also be defined as combination of other conditions. A simple condition could be: “User is male”, while a more generic condition with parameters may test whether a given property has a specific value: “User property x has value y”.</p>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl http://localhost:8181/context.js?sessionId=1234</code></pre>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_persona">2.3.3. Persona</h4>
 <div class="paragraph">
-<p>A persona is a "virtual" profile used to represent categories of profiles, and may also be used to test how a personalized experience would look like using this virtual profile. A persona can define predefined properties and sessions. Persona definition make it possible to “emulate” a certain type of profile, e.g : US visitor, non-US visitor, etc.</p>
+<p>This will retrieve a JavaScript script that contains a <code>cxs</code> object that contains the context with the current user
+profile, segments, scores as well as functions that makes it easier to perform further requests (such as collecting
+events using the cxs.collectEvents() function).</p>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_propertymergestrategytype">2.3.4. PropertyMergeStrategyType</h4>
+<div class="sect5">
+<h6 id="_retrieving_a_context_as_a_json_object">Retrieving a context as a JSON object.</h6>
 <div class="paragraph">
-<p>A strategy to resolve how to merge properties when merging profile together.</p>
+<p>If you prefer to retrieve a pure JSON object, you can simply use a request formed like this:</p>
 </div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl http://localhost:8181/context.json?sessionId=1234</code></pre>
 </div>
-<div class="sect3">
-<h4 id="_propertytype">2.3.5. PropertyType</h4>
-<div class="paragraph">
-<p>Definition for a profile or session property, specifying how possible values are constrained, if the value is multi-valued (a vector of values as opposed to a scalar value). `PropertyType`s can also be categorized using systemTags or file system structure, using sub-directories to organize definition files.</p>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_rule">2.3.6. Rule</h4>
+<div class="sect5">
+<h6 id="_accessing_profile_properties_in_a_context">Accessing profile properties in a context</h6>
 <div class="paragraph">
-<p>`Rule`s are conditional sets of actions to be executed in response to incoming events. Triggering of rules is guarded by a condition: the rule is only triggered if the associated condition is satisfied. That condition can test the event itself, but also the profile or the session. Once a rule triggers, a list of actions can be performed as consequences. Also, when rules trigger, a specific event is raised so that other parts of Unomi can react accordingly.</p>
-</div>
+<p>By default, in order to optimize the amount of data sent over the network, Apache Unomi will not send the content of
+the profile or session properties. If you need this data, you must send a JSON object to configure the resulting output
+of the context.js(on) servlet.</p>
 </div>
-<div class="sect3">
-<h4 id="_scoring">2.3.7. Scoring</h4>
 <div class="paragraph">
-<p>`Scoring`s are set of conditions associated with a value to assign to profiles when matching so that the associated users can be scored along that dimension. Each scoring element is evaluated and matching profiles' scores are incremented with the associated value.</p>
-</div>
+<p>Here is an example that will retrieve all the session and profile properties.</p>
 </div>
-<div class="sect3">
-<h4 id="_segments">2.3.8. Segments</h4>
-<div class="paragraph">
-<p>`Segment`s represent dynamically evaluated groups of similar profiles in order to categorize the associated users. To be considered part of a given segment, users must satisfies the segment’s condition. If they match, users are automatically added to the segment. Similarly, if at any given point during, they cease to satisfy the segment’s condition, they are automatically removed from it.</p>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -H "Content-Type: application/json" -X POST -d '{"source":{"itemId":"homepage","itemType":"page","scope":"example"},"requiredProfileProperties":["*"],"requiredSessionProperties":["*"],"requireSegments":true}' http://localhost:8181/context.json?sessionId=1234</code></pre>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_tag">2.3.9. Tag</h4>
 <div class="paragraph">
-<p>`Tag`s are simple labels that are used to classify all other objects inside Unomi.</p>
+<p>The <code>requiredProfileProperties</code> and <code>requiredSessionProperties</code> are properties that take an array of property names
+that should be retrieved. In this case we use the wildcard character '*' to say we want to retrieve all the available
+properties. The structure of the JSON object that you should send is a JSON-serialized version of the <a href="http://unomi.incubator.apache.org/unomi-api/apidocs/org/apache/unomi/api/ContextRequest.html">ContextRequest</a>
+Java class.</p>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_valuetype">2.3.10. ValueType</h4>
+<div class="sect5">
+<h6 id="_sending_events_using_the_context_servlet">Sending events using the context servlet</h6>
 <div class="paragraph">
-<p>Definition for values that can be assigned to properties ("primitive" types).</p>
+<p>At the same time as you are retrieving the context, you can also directly send events in the ContextRequest object as
+illustrated in the following example:</p>
 </div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -H "Content-Type: application/json" -X POST -d '{"source":{"itemId":"homepage","itemType":"page","scope":"example"},"events":[{"eventType":"view","scope": "example","source":{"itemType": "site","scope":"example","itemId": "mysite"},"target":{"itemType":"page","scope":"example","itemId":"homepage","properties":{"pageInfo":{"referringURL":""}}}}]}' http://localhost:8181/context.json?sessionId=1234</code></pre>
 </div>
 </div>
-<div class="sect2">
-<h3 id="_other_unomi_entities">2.4. Other Unomi entities</h3>
-<div class="sect3">
-<h4 id="_userlist">2.4.1. UserList</h4>
 <div class="paragraph">
-<p>User list are simple static lists of users. The associated profile stores the lists it belongs to in a specific property.</p>
+<p>Upon received events, Apache Unomi will execute all the rules that match the current context, and return an updated context.
+This way of sending events is usually used upon first loading of a page. If you want to send events after the page has
+finished loading you could either do a second call and get an updating context, or if you don&#8217;t need the context and want
+to send events in a network optimal way you can use the eventcollector servlet (see below).</p>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_goal">2.4.2. Goal</h4>
+<div class="sect5">
+<h6 id="_sending_events_using_the_eventcollector_servlet">Sending events using the eventcollector servlet</h6>
 <div class="paragraph">
-<p>Goals represent tracked activities / actions that can be accomplished by site (or more precisely scope) visitors. These are tracked in general because they relate to specific business objectives or are relevant to measure site/scope performance.</p>
+<p>If you only need to send events without retrieving a context, you should use the eventcollector servlet that is optimized
+respond quickly and minimize network traffic. Here is an example of using this servlet:</p>
 </div>
-<div class="paragraph">
-<p>Goals can be defined at the scope level or in the context of a particular <code>Campaign</code>. Either types of goals behave exactly the same way with the exception of two notable differences:
- - duration: scope-level goals are considered until removed while campaign-level goals are only considered for the campaign duration
- - audience filtering: any visitor is considered for scope-level goals while campaign-level goals only consider visitors who match the campaign&#8217;s conditions</p>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>curl -H "Content-Type: application/json" -X POST -d '{"events":[{"eventType":"view","scope": "example","source":{"itemType": "site","scope":"example","itemId": "mysite"},"target":{"itemType":"page","scope":"example","itemId":"homepage","properties":{"pageInfo":{"referringURL":""}}}}]}' http://localhost:8181/eventcollector?sessionId=1234</code></pre>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_campaign">2.4.3. Campaign</h4>
 <div class="paragraph">
-<p>A goal-oriented, time-limited marketing operation that needs to be evaluated for return on investment performance by tracking the ratio of visits to conversions.</p>
+<p>Note that the eventcollector executes the rules but does not return a context. If is generally used after a page is loaded
+to send additional events.</p>
+</div>
 </div>
 </div>
+<div class="sect4">
+<h5 id="_where_to_go_from_here">Where to go from here</h5>
+<div class="ulist">
+<ul>
+<li>
+<p>Read the <a href="#_twitter_sample">Twitter sample</a> documentation that contains a detailed example of how to integrate with Apache Unomi.</p>
+</li>
+</ul>
+</div>
 </div>
 </div>
 </div>
-<div class="sect1">
-<h2 id="_quick_start">3. Quick start</h2>
-<div class="sectionbody">
 <div class="sect2">
-<h3 id="_building">3.1. Building</h3>
+<h3 id="_configuration">3.2. Configuration</h3>
 <div class="sect3">
-<h4 id="_initial_setup">3.1.1. Initial Setup</h4>
+<h4 id="_changing_the_default_configuration">3.2.1. Changing the default configuration</h4>
 <div class="paragraph">
-<p>1) Install J2SE 8.0 SDK (or later), which can be downloaded from
- <a href="http://www.oracle.com/technetwork/java/javase/downloads/index.html">http://www.oracle.com/technetwork/java/javase/downloads/index.html</a></p>
+<p>If you want to change the default configuration, you can perform any modification you want in the $MY_KARAF_HOME/etc directory.</p>
 </div>
 <div class="paragraph">
-<p>2) Make sure that your JAVA_HOME environment variable is set to the newly installed
- JDK location, and that your PATH includes %JAVA_HOME%\bin (windows) or
- $JAVA_HOME$/bin (unix).</p>
+<p>If you want to change the HTTP ports that the server is listening on, you will need to add/change the following lines in the $MY_KARAF_HOME/etc/custom.properties file:</p>
 </div>
-<div class="paragraph">
-<p>3) Install Maven 3.0.3 (or later), which can be downloaded from
- <a href="http://maven.apache.org/download.html">http://maven.apache.org/download.html</a>. Make sure that your PATH includes
- the MVN_HOME/bin directory.</p>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>org.osgi.service.http.port.secure=9443
+org.osgi.service.http.port=8181</code></pre>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_building_2">3.1.2. Building</h4>
 <div class="paragraph">
-<p>1) Change to the top level directory of Apache Unomi source distribution.
-2) Run</p>
+<p>If you change these ports, also make sure you adjust the following file in the cluster configuration.</p>
+</div>
+<div class="paragraph">
+<p>The context server configuration is kept in the $MY_KARAF_HOME/etc/org.apache.unomi.cluster.cfg . It defines the
+addresses where it can be found :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>     $&gt; mvn clean install</code></pre>
+<pre class="highlight"><code>contextserver.publicAddress=https://localhost:9443
+contextserver.internalAddress=http://127.0.0.1:8181</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>This will compile Apache Unomi and run all of the tests in the
- Apache Unomi source distribution. Alternatively, you can run</p>
+<p>If you need to specify an Elasticsearch cluster name, or a host and port that are different than the default,
+it is recommended to do this BEFORE you start the server for the first time, or you will loose all the data
+you have stored previously.</p>
+</div>
+<div class="paragraph">
+<p>To change these settings, you will need to modify a file called</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>     $&gt; mvn -P \!integration-tests,\!performance-tests clean install</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>This will compile Apache Unomi without running the tests and takes less
- time to build.</p>
-</div>
-<div class="paragraph">
-<p>3) The distributions will be available under "package/target" directory.</p>
+<pre class="highlight"><code>$MY_KARAF_HOME/etc/org.apache.unomi.persistence.elasticsearch.cfg</code></pre>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_installing_an_elasticsearch_server">3.1.3. Installing an ElasticSearch server</h4>
 <div class="paragraph">
-<p>Starting with version 1.2, Apache Unomi no longer embeds an ElasticSearch server as this is no longer supported by
-the developers of ElasticSearch. Therefore you will need to install a standalone ElasticSearch using the following steps:</p>
+<p>with the following contents:</p>
 </div>
-<div class="paragraph">
-<p>.</p>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>cluster.name=contextElasticSearch
+# The elasticSearchAddresses may be a comma seperated list of host names and ports such as
+# hostA:9300,hostB:9300
+# Note: the port number must be repeated for each host.
+elasticSearchAddresses=localhost:9300
+index.name=context</code></pre>
 </div>
-<div class="paragraph">
-<p>Download an ElasticSearch version. Here&#8217;s the version you will need depending
-on your version of Apache Unomi.</p>
 </div>
-<div class="paragraph">
-<p>Apache Unomi &lt;= 1.2 : <a href="https://www.elastic.co/downloads/past-releases/elasticsearch-5-1-2">https://www.elastic.co/downloads/past-releases/elasticsearch-5-1-2</a>
-Apache Unomi &gt;= 1.3 : <a href="https://www.elastic.co/downloads/past-releases/elasticsearch-5-6-3">https://www.elastic.co/downloads/past-releases/elasticsearch-5-6-3</a></p>
 </div>
+<div class="sect3">
+<h4 id="_secured_events_configuration">3.2.2. Secured events configuration</h4>
 <div class="paragraph">
-<p>.</p>
+<p>Unomi secures some events by default. You can find the default configuration in the following file (created after the
+first server startup):</p>
 </div>
-<div class="paragraph">
-<p>Uncompress the downloaded package into a directory</p>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>$MY_KARAF_HOME/etc/org.apache.unomi.thirdparty.cfg</code></pre>
 </div>
-<div class="paragraph">
-<p>.</p>
 </div>
 <div class="paragraph">
-<p>In the config/elasticsearch.yml file, uncomment and modify the following line :</p>
+<p>Ususally, login events, which operate on profiles and do merge on protected properties, must be secured. For each
+trusted third party server, you need to add these 3 lines :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>cluster.name: contextElasticSearch</code></pre>
+<pre class="highlight"><code>thirdparty.provider1.key=secret-key
+thirdparty.provider1.ipAddresses=127.0.0.1,::1
+thirdparty.provider1.allowedEvents=login,updateProperties</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>.</p>
+<p>The events set in allowedEvents will be secured and will only be accepted if the call comes from the specified IP
+address, and if the secret-key is passed in the X-Unomi-Peer header.</p>
 </div>
+</div>
+<div class="sect3">
+<h4 id="_installing_the_maxmind_geoiplite2_ip_lookup_database">3.2.3. Installing the MaxMind GeoIPLite2 IP lookup database</h4>
 <div class="paragraph">
-<p>Launch the server using</p>
+<p>The Context Server requires an IP database in order to resolve IP addresses to user location.
+The GeoLite2 database can be downloaded from MaxMind here :
+<a href="http://dev.maxmind.com/geoip/geoip2/geolite2/">http://dev.maxmind.com/geoip/geoip2/geolite2/</a></p>
 </div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>bin/elasticsearch (Mac, Linux)
-bin\elasticsearch.bat (Windows)</code></pre>
+<div class="paragraph">
+<p>Simply download the GeoLite2-City.mmdb file into the "etc" directory.</p>
 </div>
 </div>
+<div class="sect3">
+<h4 id="_installing_geonames_database">3.2.4. Installing Geonames database</h4>
 <div class="paragraph">
-<p>.</p>
+<p>Context server includes a geocoding service based on the geonames database ( <a href="http://www.geonames.org/">http://www.geonames.org/</a> ). It can be
+used to create conditions on countries or cities.</p>
 </div>
 <div class="paragraph">
-<p>Check that the ElasticSearch is up and running by accessing the following URL :</p>
+<p>In order to use it, you need to install the Geonames database into . Get the "allCountries.zip" database from here :
+<a href="http://download.geonames.org/export/dump/">http://download.geonames.org/export/dump/</a></p>
 </div>
 <div class="paragraph">
-<p><a href="http://localhost:9200">http://localhost:9200</a></p>
+<p>Download it and put it in the "etc" directory, without unzipping it.
+Edit $MY_KARAF_HOME/etc/org.apache.unomi.geonames.cfg and set request.geonamesDatabase.forceImport to true, import should start right away.
+Otherwise, import should start at the next startup. Import runs in background, but can take about 15 minutes.
+At the end, you should have about 4 million entries in the geonames index.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_deploying_the_generated_binary_package">3.1.4. Deploying the generated binary package</h4>
+<h4 id="_rest_api_security">3.2.5. REST API Security</h4>
 <div class="paragraph">
-<p>The "package" sub-project generates a pre-configured Apache Karaf installation that is the simplest way to get started.
-Simply uncompress the package/target/unomi-VERSION.tar.gz (for Linux or Mac OS X) or
- package/target/unomi-VERSION.zip (for Windows) archive into the directory of your choice.</p>
+<p>The Context Server REST API is protected using JAAS authentication and using Basic or Digest HTTP auth.
+By default, the login/password for the REST API full administrative access is "karaf/karaf".</p>
 </div>
 <div class="paragraph">
-<p>You can then start the server simply by using the command on UNIX/Linux/MacOS X :</p>
+<p>The generated package is also configured with a default SSL certificate. You can change it by following these steps :</p>
 </div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>./bin/karaf</code></pre>
+<div class="paragraph">
+<p>Replace the existing keystore in $MY_KARAF_HOME/etc/keystore by your own certificate :</p>
 </div>
+<div class="paragraph">
+<p><a href="http://wiki.eclipse.org/Jetty/Howto/Configure_SSL">http://wiki.eclipse.org/Jetty/Howto/Configure_SSL</a></p>
 </div>
 <div class="paragraph">
-<p>or on Windows shell :</p>
+<p>Update the keystore and certificate password in $MY_KARAF_HOME/etc/custom.properties file :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>bin\karaf.bat</code></pre>
+<pre class="highlight"><code>    org.osgi.service.http.secure.enabled = true
+    org.ops4j.pax.web.ssl.keystore=${karaf.etc}/keystore
+    org.ops4j.pax.web.ssl.password=changeme
+    org.ops4j.pax.web.ssl.keypassword=changeme
+    org.osgi.service.http.port.secure=9443</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>You will then need to launch (only on the first Karaf start) the Apache Unomi packages using the following Apache Karaf
-shell command:</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>unomi:start</code></pre>
+<p>You should now have SSL setup on Karaf with your certificate, and you can test it by trying to access it on port 9443.</p>
 </div>
+<div class="olist arabic">
+<ol class="arabic">
+<li>
+<p>Changing the default Karaf password can be done by modifying the etc/users.properties file</p>
+</li>
+</ol>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_deploying_into_an_existing_karaf_server">3.1.5. Deploying into an existing Karaf server</h4>
-<div class="paragraph">
-<p>This is only needed if you didn&#8217;t use the generated package. Also, this is the preferred way to install a development
-environment if you intend to re-deploy the context server KAR iteratively.</p>
-</div>
+<h4 id="_automatic_profile_merging">3.2.6. Automatic profile merging</h4>
 <div class="paragraph">
-<p>Additional requirements:
-* Apache Karaf 3.x, <a href="http://karaf.apache.org">http://karaf.apache.org</a></p>
+<p>The context server is capable of merging profiles based on a common property value. In order to use this, you must
+add the MergeProfileOnPropertyAction to a rule (such as a login rule for example), and configure it with the name
+ of the property that will be used to identify the profiles to be merged. An example could be the "email" property,
+ meaning that if two (or more) profiles are found to have the same value for the "email" property they will be merged
+ by this action.</p>
 </div>
 <div class="paragraph">
-<p>.</p>
+<p>Upon merge, the old profiles are marked with a "mergedWith" property that will be used on next profile access to delete
+the original profile and replace it with the merged profile (aka "master" profile). Once this is done, all cookie tracking
+will use the merged profile.</p>
 </div>
 <div class="paragraph">
-<p>Before deploying, make sure that you have Apache Karaf properly installed. You will also have to increase the
-default maximum memory size and perm gen size by adjusting the following environment values in the bin/setenv(.bat)
-files (at the end of the file):</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>   MY_DIRNAME=`dirname $0`
-   MY_KARAF_HOME=`cd "$MY_DIRNAME/.."; pwd`
-   export JAVA_MAX_MEM=3G
-   export JAVA_MAX_PERM_MEM=384M</code></pre>
+<p>To test, simply configure the action in the "login" or "facebookLogin" rules and set it up on the "email" property.
+Upon sending one of the events, all matching profiles will be merged.</p>
 </div>
 </div>
+<div class="sect3">
+<h4 id="_securing_a_production_environment">3.2.7. Securing a production environment</h4>
 <div class="paragraph">
-<p>.</p>
+<p>Before going live with a project, you should <em>absolutely</em> read the following section that will help you setup a proper
+secure environment for running your context server.</p>
 </div>
 <div class="paragraph">
-<p>Install the WAR support, CXF and Karaf Cellar into Karaf by doing the following in the Karaf command line:</p>
+<p>Step 1: Install and configure a firewall</p>
 </div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>   feature:repo-add cxf 3.0.2
-   feature:repo-add cellar 3.0.3
-   feature:repo-add mvn:org.apache.unomi/unomi-kar/VERSION/xml/features
-   feature:install unomi-kar</code></pre>
+<div class="paragraph">
+<p>You should setup a firewall around your cluster of context servers and/or Elasticsearch nodes. If you have an
+application-level firewall you should only allow the following connections open to the whole world :</p>
 </div>
+<div class="ulist">
+<ul>
+<li>
+<p><a href="http://localhost:8181/context.js">http://localhost:8181/context.js</a></p>
+</li>
+<li>
+<p><a href="http://localhost:8181/eventcollector">http://localhost:8181/eventcollector</a></p>
+</li>
+</ul>
 </div>
 <div class="paragraph">
-<p>.</p>
+<p>All other ports should not be accessible to the world.</p>
 </div>
 <div class="paragraph">
-<p>Create a new $MY_KARAF_HOME/etc/org.apache.cxf.osgi.cfg file and put the following property inside :</p>
+<p>For your Context Server client applications (such as the Jahia CMS), you will need to make the following ports
+accessible :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>   org.apache.cxf.servlet.context=/cxs</code></pre>
+<pre class="highlight"><code>8181 (Context Server HTTP port)
+9443 (Context Server HTTPS port)</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>.</p>
+<p>The context server actually requires HTTP Basic Auth for access to the Context Server administration REST API, so it is
+highly recommended that you design your client applications to use the HTTPS port for accessing the REST API.</p>
 </div>
 <div class="paragraph">
-<p>If all went smoothly, you should be able to access the context script here : <a href="http://localhost:8181/cxs/cluster">http://localhost:8181/cxs/cluster</a> .
- You should be able to login with karaf / karaf and see basic server information. If not something went wrong during the install.</p>
+<p>The user accounts to access the REST API are actually routed through Karaf&#8217;s JAAS support, which you may find the
+documentation for here :</p>
 </div>
+<div class="ulist">
+<ul>
+<li>
+<p><a href="http://karaf.apache.org/manual/latest/users-guide/security.html">http://karaf.apache.org/manual/latest/users-guide/security.html</a></p>
+</li>
+</ul>
 </div>
-<div class="sect3">
-<h4 id="_jdk_selection_on_mac_os_x">3.1.6. JDK Selection on Mac OS X</h4>
 <div class="paragraph">
-<p>You might need to select the JDK to run the tests in the itests subproject. In order to do so you can list the
-installed JDKs with the following command :</p>
+<p>The default username/password is</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>/usr/libexec/java_home -V</code></pre>
+<pre class="highlight"><code>karaf/karaf</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>which will output something like this :</p>
+<p>You should really change this default username/password as soon as possible. To do so, simply modify the following
+file :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>Matching Java Virtual Machines (7):
-    1.7.0_51, x86_64:   "Java SE 7"   /Library/Java/JavaVirtualMachines/jdk1.7.0_51.jdk/Contents/Home
-    1.7.0_45, x86_64:   "Java SE 7"   /Library/Java/JavaVirtualMachines/jdk1.7.0_45.jdk/Contents/Home
-    1.7.0_25, x86_64:   "Java SE 7"   /Library/Java/JavaVirtualMachines/jdk1.7.0_25.jdk/Contents/Home
-    1.6.0_65-b14-462, x86_64:   "Java SE 6"   /Library/Java/JavaVirtualMachines/1.6.0_65-b14-462.jdk/Contents/Home
-    1.6.0_65-b14-462, i386: "Java SE 6" /Library/Java/JavaVirtualMachines/1.6.0_65-b14-462.jdk/Contents/Home
-    1.6.0_65-b14-462, x86_64:   "Java SE 6"   /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home
-    1.6.0_65-b14-462, i386: "Java SE 6" /System/Library/Java/JavaVirtualMachines/1.6.0.jdk/Contents/Home</code></pre>
+<pre class="highlight"><code>$MY_KARAF_HOME/etc/users.properties</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>You can then select the one you want using :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>export JAVA_HOME=`/usr/libexec/java_home -v 1.7.0_51`</code></pre>
+<p>For your context servers, and for any standalone Elasticsearch nodes you will need to open the following ports for proper
+node-to-node communication : 9200 (Elasticsearch REST API), 9300 (Elasticsearch TCP transport)</p>
 </div>
+<div class="paragraph">
+<p>Of course any ports listed here are the default ports configured in each server, you may adjust them if needed.</p>
 </div>
 <div class="paragraph">
-<p>and then check that it was correctly referenced using:</p>
+<p>Step 2 : Follow industry recommended best practices for securing Elasticsearch</p>
 </div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>java -version</code></pre>
+<div class="paragraph">
+<p>You may find more valuable recommendations here :</p>
 </div>
+<div class="ulist">
+<ul>
+<li>
+<p><a href="https://www.elastic.co/blog/found-elasticsearch-security">https://www.elastic.co/blog/found-elasticsearch-security</a></p>
+</li>
+<li>
+<p><a href="https://www.elastic.co/blog/scripting-security">https://www.elastic.co/blog/scripting-security</a></p>
+</li>
+</ul>
 </div>
 <div class="paragraph">
-<p>which should give you a result such as this:</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>java version "1.7.0_51"
-Java(TM) SE Runtime Environment (build 1.7.0_51-b13)
-Java HotSpot(TM) 64-Bit Server VM (build 24.51-b03, mixed mode)</code></pre>
+<p>Step 4 : Setup a proxy in front of the context server</p>
 </div>
+<div class="paragraph">
+<p>As an alternative to an application-level firewall, you could also route all traffic to the context server through
+a proxy, and use it to filter any communication.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_running_the_integration_tests">3.1.7. Running the integration tests</h4>
+<h4 id="_integrating_with_an_apache_http_web_server">3.2.8. Integrating with an Apache HTTP web server</h4>
 <div class="paragraph">
-<p>The integration tests are not executed by default to make build time minimal, but it is recommended to run the
-integration tests at least once before using the server to make sure that everything is ok in the build. Another way
-to use these tests is to run them from a continuous integration server such as Jenkins, Apache Gump, Atlassian Bamboo or
- others.</p>
+<p>If you want to setup an Apache HTTP web server in from of Apache Unomi, here is an example configuration using
+mod_proxy.</p>
 </div>
 <div class="paragraph">
-<p>Note : the integration tests require a JDK 7 or more recent !</p>
+<p>In your Unomi package directory, in /etc/org.apache.unomi.cluster.cfg for unomi.apache.org</p>
 </div>
 <div class="paragraph">
-<p>To run the tests simply activate the following profile :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>mvn -P integration-tests clean install</code></pre>
-</div>
-</div>
+<p>contextserver.publicAddress=https://unomi.apache.org/
+ contextserver.internalAddress=http://192.168.1.1:8181</p>
 </div>
-<div class="sect3">
-<h4 id="_running_the_performance_tests">3.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>
+<p>and you will also need to change the contextserver.domain in the /etc/org.apache.unomi.web.cfg file</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>
+<p>contextserver.domain=apache.org</p>
 </div>
 <div class="paragraph">
-<p>Run the test by using the gatling.conf file in performance-tests/src/test/resources :</p>
+<p>Main virtual host config:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>    export GATLING_CONF=&lt;path&gt;/performance-tests/src/test/resources
-    gatling.sh</code></pre>
+<pre class="highlight"><code>&lt;VirtualHost *:80&gt;
+        Include /var/www/vhosts/unomi.apache.org/conf/common.conf
+&lt;/VirtualHost&gt;
+
+&lt;IfModule mod_ssl.c&gt;
+    &lt;VirtualHost *:443&gt;
+        Include /var/www/vhosts/unomi.apache.org/conf/common.conf
+
+        SSLEngine on
+
+        SSLCertificateFile    /var/www/vhosts/unomi.apache.org/conf/ssl/24d5b9691e96eafa.crt
+        SSLCertificateKeyFile /var/www/vhosts/unomi.apache.org/conf/ssl/apache.org.key
+        SSLCertificateChainFile /var/www/vhosts/unomi.apache.org/conf/ssl/gd_bundle-g2-g1.crt
+
+        &lt;FilesMatch "\.(cgi|shtml|phtml|php)$"&gt;
+                SSLOptions +StdEnvVars
+        &lt;/FilesMatch&gt;
+        &lt;Directory /usr/lib/cgi-bin&gt;
+                SSLOptions +StdEnvVars
+        &lt;/Directory&gt;
+        BrowserMatch "MSIE [2-6]" \
+                nokeepalive ssl-unclean-shutdown \
+                downgrade-1.0 force-response-1.0
+        BrowserMatch "MSIE [17-9]" ssl-unclean-shutdown
+
+    &lt;/VirtualHost&gt;
+&lt;/IfModule&gt;</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>Reports are generated in performance-tests/target/results.</p>
+<p>common.conf:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>ServerName unomi.apache.org
+ServerAdmin webmaster@apache.org
+
+DocumentRoot /var/www/vhosts/unomi.apache.org/html
+CustomLog /var/log/apache2/access-unomi.apache.org.log combined
+&lt;Directory /&gt;
+        Options FollowSymLinks
+        AllowOverride None
+&lt;/Directory&gt;
+&lt;Directory /var/www/vhosts/unomi.apache.org/html&gt;
+        Options FollowSymLinks MultiViews
+        AllowOverride None
+        Order allow,deny
+        allow from all
+&lt;/Directory&gt;
+&lt;Location /cxs&gt;
+    Order deny,allow
+    deny from all
+    allow from 88.198.26.2
+    allow from www.apache.org
+&lt;/Location&gt;
+
+RewriteEngine On
+RewriteCond %{REQUEST_METHOD} ^(TRACE|TRACK)
+RewriteRule .* - [F]
+ProxyPreserveHost On
+ProxyPass /server-status !
+ProxyPass /robots.txt !
+
+RewriteCond %{HTTP_USER_AGENT} Googlebot [OR]
+RewriteCond %{HTTP_USER_AGENT} msnbot [OR]
+RewriteCond %{HTTP_USER_AGENT} Slurp
+RewriteRule ^.* - [F,L]
+
+ProxyPass / http://localhost:8181/ connectiontimeout=20 timeout=300 ttl=120
+ProxyPassReverse / http://localhost:8181/</code></pre>
+</div>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_testing_with_an_example_page">3.1.9. Testing with an example page</h4>
+<h4 id="_changing_the_default_tracking_location">3.2.9. Changing the default tracking location</h4>
 <div class="paragraph">
-<p>A default test page is provided at the following URL:</p>
+<p>When performing localhost requests to Apache Unomi, a default location will be used to insert values into the session
+to make the location-based personalization still work. You can find the default location settings in the file :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>   http://localhost:8181/index.html</code></pre>
+<pre class="highlight"><code>org.apache.unomi.plugins.request.cfg</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>This test page will trigger the loading of the /context.js script, which will try to retrieving the user context
-or create a new one if it doesn&#8217;t exist yet. It also contains an experimental integration with Facebook Login, but it
-doesn&#8217;t yet save the context back to the context server.</p>
+<p>that contains the following default settings:</p>
+</div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code># The following settings represent the default position that is used for localhost requests
+defaultSessionCountryCode=CH
+defaultSessionCountryName=Switzerland
+defaultSessionCity=Geneva
+defaultSessionAdminSubDiv1=2660645
+defaultSessionAdminSubDiv2=6458783
+defaultSessionIsp=Cablecom
+defaultLatitude=46.1884341
+defaultLongitude=6.1282508</code></pre>
+</div>
+</div>
+<div class="paragraph">
+<p>You might want to change these for testing or for demonstration purposes.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_integrating_onto_a_page">3.1.10. Integrating onto a page</h4>
+<h4 id="_apache_karaf_ssh_console">3.2.10. Apache Karaf SSH Console</h4>
 <div class="paragraph">
-<p>Simply reference the context script in your HTML as in the following example:</p>
+<p>The Apache Karaf SSH console is available inside Apache Unomi, but the port has been changed from the default value of
+8101 to 8102 to avoid conflicts with other Karaf-based products. So to connect to the SSH console you should use:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code class="language-javascript" data-lang="javascript">&lt;script type="text/javascript"&gt;
-    (function(){ var u=(("https:" ==== document.location.protocol) ? "https://localhost:8181/" : "http://localhost:8181/");
-    var d=document, g=d.createElement('script'), s=d.getElementsByTagName('script')[0]; g.type='text/javascript'; g.defer=true; g.async=true; g.src=u+'context.js';
-    s.parentNode.insertBefore(g,s); })();
-&lt;/script&gt;</code></pre>
+<pre class="highlight"><code>ssh -p 8102 karaf@localhost</code></pre>
 </div>
 </div>
+<div class="paragraph">
+<p>or the user/password you have setup to protect the system if you have changed it.</p>
 </div>
 </div>
-<div class="sect2">
-<h3 id="_getting_started_with_unomi">3.2. Getting started with Unomi</h3>
+<div class="sect3">
+<h4 id="_elasticsearch_x_pack_support">3.2.11. ElasticSearch X-Pack Support</h4>
 <div class="paragraph">
-<p>We will first get you up and running with an example. We will then lift the corner of the cover somewhat and explain in greater details what just happened.</p>
+<p>It is now possible to use X-Pack to connect to ElasticSearch. However, for licensing reasons this is not provided out
+of the box. Here is the procedure to install X-Pack with Apache Unomi:</p>
 </div>
-<div class="sect3">
-<h4 id="_prerequisites">3.2.1. Prerequisites</h4>
+</div>
+</div>
+<div class="sect2">
+<h3 id="_important">3.3. Important !</h3>
 <div class="paragraph">
-<p>This document assumes that you are already familiar with Unomi&#8217;s <a href="concepts.html">concepts</a>. On the technical side, we also assume working knowledge of <a href="https://git-scm.com/">git</a> to be able to retrieve the code for Unomi and the example. Additionnally, you will require a working Java 7 or above install. Refer to <a href="http://www.oracle.com/technetwork/java/javase/">http://www.oracle.com/technetwork/java/javase/</a> for details on how to download and install Java SE 7 or greater.</p>
+<p>Do not start Unomi directly with unomi:start, perform the following steps below first !</p>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_running_unomi">3.2.2. Running Unomi</h4>
-<div class="sect4">
-<h5 id="_building_unomi">Building Unomi</h5>
+<div class="sect2">
+<h3 id="_installation_steps">3.4. Installation steps</h3>
 <div class="olist arabic">
 <ol class="arabic">
 <li>
-<p>Get the code: <code>git clone <a href="https://git-wip-us.apache.org/repos/asf/incubator-unomi.git" class="bare">https://git-wip-us.apache.org/repos/asf/incubator-unomi.git</a></code></p>
+<p>Create a directory for all the JARs that you will download, we will call it XPACK_JARS_DIRECTORY</p>
+</li>
+<li>
+<p>Download <a href="https://artifacts.elastic.co/maven/org/elasticsearch/client/x-pack-transport/5.6.3/x-pack-transport-5.6.3.jar">https://artifacts.elastic.co/maven/org/elasticsearch/client/x-pack-transport/5.6.3/x-pack-transport-5.6.3.jar</a> to XPACK_JARS_DIRECTORY</p>
+</li>
+<li>
+<p>Download <a href="https://artifacts.elastic.co/maven/org/elasticsearch/plugin/x-pack-api/5.6.3/x-pack-api-5.6.3.jar">https://artifacts.elastic.co/maven/org/elasticsearch/plugin/x-pack-api/5.6.3/x-pack-api-5.6.3.jar</a> to XPACK_JARS_DIRECTORY</p>
+</li>
+<li>
+<p>Download <a href="http://central.maven.org/maven2/com/unboundid/unboundid-ldapsdk/3.2.0/unboundid-ldapsdk-3.2.0.jar">http://central.maven.org/maven2/com/unboundid/unboundid-ldapsdk/3.2.0/unboundid-ldapsdk-3.2.0.jar</a> to XPACK_JARS_DIRECTORY</p>
 </li>
 <li>
-<p>Build and install according to the <a href="building-and-deploying.html">instructions</a> and install Unomi.</p>
+<p>Download <a href="http://central.maven.org/maven2/org/bouncycastle/bcpkix-jdk15on/1.55/bcpkix-jdk15on-1.55.jar">http://central.maven.org/maven2/org/bouncycastle/bcpkix-jdk15on/1.55/bcpkix-jdk15on-1.55.jar</a> to XPACK_JARS_DIRECTORY</p>
+</li>
+<li>
+<p>Download <a href="http://central.maven.org/maven2/org/bouncycastle/bcprov-jdk15on/1.55/bcprov-jdk15on-1.55.jar">http://central.maven.org/maven2/org/bouncycastle/bcprov-jdk15on/1.55/bcprov-jdk15on-1.55.jar</a> to XPACK_JARS_DIRECTORY</p>
+</li>
+<li>
+<p>Download <a href="http://central.maven.org/maven2/com/sun/mail/javax.mail/1.5.3/javax.mail-1.5.3.jar">http://central.maven.org/maven2/com/sun/mail/javax.mail/1.5.3/javax.mail-1.5.3.jar</a> to XPACK_JARS_DIRECTORY
+.</p>
 </li>
 </ol>
 </div>
-</div>
-<div class="sect4">
-<h5 id="_start_unomi">Start Unomi</h5>
 <div class="paragraph">
-<p>Start Unomi according to the <a href="building-and-deploying.html#Deploying_the_generated_package">instructions</a>. Once you have Karaf running,
- you should wait until you see the following messages on the Karaf console:</p>
+<p>Edit etc/org.apache.unomi.persistence.elasticsearch.cfg to add the following settings:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>Initializing user list service endpoint...
-Initializing geonames service endpoint...
-Initializing segment service endpoint...
-Initializing scoring service endpoint...
-Initializing campaigns service endpoint...
-Initializing rule service endpoint...
-Initializing profile service endpoint...
-Initializing cluster service endpoint...</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>This indicates that all the Unomi services are started and ready to react to requests. You can then open a browser and go to <code><a href="http://localhost:8181/cxs" class="bare">http://localhost:8181/cxs</a></code> to see the list of
-available RESTful services or retrieve an initial context at <code><a href="http://localhost:8181/context.json" class="bare">http://localhost:8181/context.json</a></code> (which isn&#8217;t very useful at this point).</p>
+<pre class="highlight"><code>transportClientClassName=org.elasticsearch.xpack.client.PreBuiltXPackTransportClient
+transportClientJarDirectory=XPACK_JARS_DIRECTORY
+transportClientProperties=xpack.security.user=elastic:changeme</code></pre>
 </div>
 </div>
-<div class="sect4">
-<h5 id="_request_examples">Request examples</h5>
-<div class="sect5">
-<h6 id="_retrieving_your_first_context">Retrieving your first context</h6>
 <div class="paragraph">
-<p>You can retrieve a context using curl like this :</p>
+<p>You can setup more properties (for example for SSL/TLS support) by seperating the properties with commas,
+as in the following example:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>curl http://localhost:8181/context.js?sessionId=1234</code></pre>
+<pre class="highlight"><code>transportClientProperties=xpack.security.user=elastic:changeme,xpack.ssl.key=/home/user/elasticsearch-5.6.3/config/x-pack/localhost/localhost.key,xpack.ssl.certificate=/home/user/elasticsearch-5.6.3/config/x-pack/localhost/localhost.crt,xpack.ssl.certificate_authorities=/home/user/elasticsearch-5.6.3/config/x-pack/ca/ca.crt,xpack.security.transport.ssl.enabled=true</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>This will retrieve a JavaScript script that contains a <code>cxs</code> object that contains the context with the current user
-profile, segments, scores as well as functions that makes it easier to perform further requests (such as collecting
-events using the cxs.collectEvents() function).</p>
-</div>
+<p>.</p>
 </div>
-<div class="sect5">
-<h6 id="_retrieving_a_context_as_a_json_object">Retrieving a context as a JSON object.</h6>
 <div class="paragraph">
-<p>If you prefer to retrieve a pure JSON object, you can simply use a request formed like this:</p>
+<p>Launch Karaf and launch unomi using the command from the shell :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>curl http://localhost:8181/context.json?sessionId=1234</code></pre>
-</div>
-</div>
+<pre class="highlight"><code>unomi:start</code></pre>
 </div>
-<div class="sect5">
-<h6 id="_accessing_profile_properties_in_a_context">Accessing profile properties in a context</h6>
-<div class="paragraph">
-<p>By default, in order to optimize the amount of data sent over the network, Apache Unomi will not send the content of
-the profile or session properties. If you need this data, you must send a JSON object to configure the resulting output
-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>Alternatively you could edit the configuration directly from the Karaf shell using the following commands:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>curl -H "Content-Type: application/json" -X POST -d '{"source":{"itemId":"homepage","itemType":"page","scope":"example"},"requiredProfileProperties":["*"],"requiredSessionProperties":["*"],"requireSegments":true}' http://localhost:8181/context.json?sessionId=1234</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>The <code>requiredProfileProperties</code> and <code>requiredSessionProperties</code> are properties that take an array of property names
-that should be retrieved. In this case we use the wildcard character '*' to say we want to retrieve all the available
-properties. The structure of the JSON object that you should send is a JSON-serialized version of the <a href="http://unomi.incubator.apache.org/unomi-api/apidocs/org/apache/unomi/api/ContextRequest.html">ContextRequest</a>
-Java class.</p>
+<pre class="highlight"><code>config:edit org.apache.unomi.persistence.elasticsearch
+config:property-set transportClientClassName org.elasticsearch.xpack.client.PreBuiltXPackTransportClient
+config:property-set transportClientJarDirectory XPACK_JARS_DIRECTORY
+config:property-set transportClientProperties xpack.security.user=elastic:changeme
+config:update
+unomi:start</code></pre>
 </div>
 </div>
-<div class="sect5">
-<h6 id="_sending_events_using_the_context_servlet">Sending events using the context servlet</h6>
 <div class="paragraph">
-<p>At the same time as you are retrieving the context, you can also directly send events in the ContextRequest object as
-illustrated in the following example:</p>
+<p>You can setup more properties (for example for SSL/TLS support) by seperating the properties with commas,
+as in the following example:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>curl -H "Content-Type: application/json" -X POST -d '{"source":{"itemId":"homepage","itemType":"page","scope":"example"},"events":[{"eventType":"view","scope": "example","source":{"itemType": "site","scope":"example","itemId": "mysite"},"target":{"itemType":"page","scope":"example","itemId":"homepage","properties":{"pageInfo":{"referringURL":""}}}}]}' http://localhost:8181/context.json?sessionId=1234</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>Upon received events, Apache Unomi will execute all the rules that match the current context, and return an updated context.
-This way of sending events is usually used upon first loading of a page. If you want to send events after the page has
-finished loading you could either do a second call and get an updating context, or if you don&#8217;t need the context and want
-to send events in a network optimal way you can use the eventcollector servlet (see below).</p>
+<pre class="highlight"><code>config:property-set transportClientProperties xpack.security.user=elastic:changeme,xpack.ssl.key=/home/user/elasticsearch-5.6.3/config/x-pack/localhost/localhost.key,xpack.ssl.certificate=/home/user/elasticsearch-5.6.3/config/x-pack/localhost/localhost.crt,xpack.ssl.certificate_authorities=/home/user/elasticsearch-5.6.3/config/x-pack/ca/ca.crt,xpack.security.transport.ssl.enabled=true</code></pre>
 </div>
 </div>
-<div class="sect5">
-<h6 id="_sending_events_using_the_eventcollector_servlet">Sending events using the eventcollector servlet</h6>
-<div class="paragraph">
-<p>If you only need to send events without retrieving a context, you should use the eventcollector servlet that is optimized
-respond quickly and minimize network traffic. Here is an example of using this servlet:</p>
 </div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>curl -H "Content-Type: application/json" -X POST -d '{"events":[{"eventType":"view","scope": "example","source":{"itemType": "site","scope":"example","itemId": "mysite"},"target":{"itemType":"page","scope":"example","itemId":"homepage","properties":{"pageInfo":{"referringURL":""}}}}]}' http://localhost:8181/eventcollector?sessionId=1234</code></pre>
 </div>
 </div>
+<div class="sect1">
+<h2 id="_integration_samples">4. Integration samples</h2>
+<div class="sectionbody">
+<div class="sect2">
+<h3 id="_samples">4.1. Samples</h3>
 <div class="paragraph">
-<p>Note that the eventcollector executes the rules but does not return a context. If is generally used after a page is loaded
-to send additional events.</p>
-</div>
-</div>
+<p>Apache Unomi provides the following samples:</p>
 </div>
-<div class="sect4">
-<h5 id="_where_to_go_from_here">Where to go from here</h5>
 <div class="ulist">
 <ul>
 <li>
-<p>Read the <a href="twitter-samples.html">Twitter samples</a> documentation that contains a detailed example of how to integrate with Apache Unomi.</p>
+<p><a href="#_twitter_sample">Twitter integration</a></p>
+</li>
+<li>
+<p><a href="#_login_sample">Login integration</a></p>
 </li>
 </ul>
 </div>
 </div>
-</div>
-</div>
 <div class="sect2">
-<h3 id="_configuration">3.3. Configuration</h3>
-<div class="sect3">
-<h4 id="_changing_the_default_configuration">3.3.1. Changing the default configuration</h4>
+<h3 id="_login_sample">4.2. Login sample</h3>
 <div class="paragraph">
-<p>If you want to change the default configuration, you can perform any modification you want in the $MY_KARAF_HOME/etc directory.</p>
+<p>This samples is an example of what is involved in integrated a login with Apache Unomi.</p>
 </div>
+<div class="sect3">
+<h4 id="_warning">4.2.1. Warning !</h4>
 <div class="paragraph">
-<p>The context server configuration is kept in the $MY_KARAF_HOME/etc/org.apache.unomi.cluster.cfg . It defines the
-addresses where it can be found :</p>
-</div>
-<div class="listingblock">
-<div class="content">
-<pre class="highlight"><code>contextserver.publicAddress=https://localhost:9443
-contextserver.internalAddress=http://127.0.0.1:8181</code></pre>
-</div>
+<p>The example code uses client-side Javascript code to send the login event. This is only
+done this way for the sake of samples simplicity but if should NEVER BE DONE THIS WAY in real cases.</p>
 </div>
 <div class="paragraph">
-<p>If you need to specify an Elasticsearch cluster name, or a host and port that are different than the default,
-it is recommended to do this BEFORE you start the server for the first time, or you will loose all the data
-you have stored previously.</p>
+<p>The login event should always be sent from the server performing the actual login since it must
+only be sent if the user has authenticated properly, and only the authentication server can validate this.</p>
+</div>
 </div>
+<div class="sect3">
+<h4 id="_installing_the_samples">4.2.2. Installing the samples</h4>
 <div class="paragraph">
-<p>To change these settings, you will need to modify a file called</p>
+<p>Login into the Unomi Karaf SSH shell using something like this :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>$MY_KARAF_HOME/etc/org.apache.unomi.persistence.elasticsearch.cfg</code></pre>
+<pre class="highlight"><code>ssh -p 8102 karaf@localhost (default password is karaf)</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>with the following contents:</p>
+<p>Install the login samples using the following command:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>cluster.name=contextElasticSearch
-# The elasticSearchAddresses may be a comma seperated list of host names and ports such as
-# hostA:9300,hostB:9300
-# Note: the port number must be repeated for each host.
-elasticSearchAddresses=localhost:9300
-index.name=context</code></pre>
+<pre class="highlight"><code>bundle:install mvn:org.apache.unomi/login-integration-samples/${project.version}</code></pre>
 </div>
 </div>
+<div class="paragraph">
+<p>when the bundle is successfully install you will get an bundle ID back we will call it BUNDLE_ID.</p>
 </div>
-<div class="sect3">
-<h4 id="_secured_events_configuration">3.3.2. Secured events configuration</h4>
 <div class="paragraph">
-<p>Unomi secures some events by default. You can find the default configuration in the following file (created after the
-first server startup):</p>
+<p>You can then do:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>$MY_KARAF_HOME/etc/org.apache.unomi.thirdparty.cfg</code></pre>
+<pre class="highlight"><code>bundle:start BUNDLE_ID</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>Ususally, login events, which operate on profiles and do merge on protected properties, must be secured. For each
-trusted third party server, you need to add these 3 lines :</p>
+<p>If all went well you can access the login samples HTML page here :</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>thirdparty.provider1.key=secret-key
-thirdparty.provider1.ipAddresses=127.0.0.1,::1
-thirdparty.provider1.allowedEvents=login,updateProperties</code></pre>
+<pre class="highlight"><code>http://localhost:8181/login/index.html</code></pre>
 </div>
 </div>
 <div class="paragraph">
-<p>The events set in allowedEvents will be secured and will only be accepted if the call comes from the specified IP
-address, and if the secret-key is passed in the X-Unomi-Peer header.</p>
+<p>You can fill in the form to test it. Note that the hardcoded password is:</p>
 </div>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>test1234</code></pre>
 </div>
-<div class="sect3">
-<h4 id="_installing_the_maxmind_geoiplite2_ip_lookup_database">3.3.3. Installing the MaxMind GeoIPLite2 IP lookup database</h4>
-<div class="paragraph">
-<p>The Context Server requires an IP database in order to resolve IP addresses to user location.
-The GeoLite2 database can be downloaded from MaxMind here :
-<a href="http://dev.maxmind.com/geoip/geoip2/geolite2/">http://dev.maxmind.com/geoip/geoip2/geolite2/</a></p>
 </div>
-<div class="paragraph">
-<p>Simply download the GeoLite2-City.mmdb file into the "etc" directory.</p>
 </div>
 </div>
+<div class="sect2">
+<h3 id="_twitter_sample">4.3. Twitter sample</h3>
 <div class="sect3">
-<h4 id="_installing_geonames_database">3.3.4. Installing Geonames database</h4>
-<div class="paragraph">
-<p>Context server includes a geocoding service based on the geonames database ( <a href="http://www.geonames.org/">http://www.geonames.org/</a> ). It can be
-used to create conditions on countries or cities.</p>
-</div>
-<div class="paragraph">
-<p>In order to use it, you need to install the Geonames database into . Get the "allCountries.zip" database from here :
-<a href="http://download.geonames.org/export/dump/">http://download.geonames.org/export/dump/</a></p>
-</div>
+<h4 id="_overview">4.3.1. Overview</h4>
 <div class="paragraph">
-<p>Download it and put it in the "etc" directory, without unzipping it.
-Edit $MY_KARAF_HOME/etc/org.apache.unomi.geonames.cfg and set request.geonamesDatabase.forceImport to true, import should start right away.
-Otherwise, import should start at the next startup. Import runs in background, but can take about 15 minutes.
-At the end, you should have about 4 million entries in the geonames index.</p>
-</div>
+<p>We will examine how a simple HTML page can interact with Unomi to enrich a user&#8217;s profile. The use case we will follow
+is a rather simple one: we use a Twitter button to record the number of times the visitor tweeted (as a <code>tweetNb</code> profile
+integer property) as well as the URLs they tweeted from (as a <code>tweetedFrom</code> multi-valued string profile property).
+A javascript script will use the Twitter API to react to clicks on this button
+and update the user profile using a <code>ContextServlet</code> request triggering a custom event. This event will, in turn,
+trigger a Unomi action on the server implemented using a Unomi plugin, a standard extension point for the server.</p>
 </div>
-<div class="sect3">
-<h4 id="_rest_api_security">3.3.5. REST API Security</h4>
+<div class="sect4">
+<h5 id="_building_the_tweet_button_samples">Building the tweet button samples</h5>
 <div class="paragraph">
-<p>The Context Server REST API is protected using JAAS authentication and using Basic or Digest HTTP auth.
-By default, the login/password for the REST API full administrative access is "karaf/karaf".</p>
+<p>In your local copy of the Unomi repository and run:</p>
 </div>
-<div class="paragraph">
-<p>The generated package is also configured with a default SSL certificate. You can change it by following these steps :</p>
+<div class="listingblock">
+<div class="content">
+<pre class="highlight"><code>cd samples/tweet-button-plugin
+mvn clean install</code></pre>
 </div>
-<div class="paragraph">
-<p>.</p>
 </div>
 <div class="paragraph">
-<p>Replace the existing keystore in $MY_KARAF_HOME/etc/keystore by your own certificate :</p>
+<p>This will compile and create the OSGi bundle that can be deployed on Unomi to extend it.</p>
 </div>
-<div class="paragraph">
-<p><a href="http://wiki.eclipse.org/Jetty/Howto/Configure_SSL">http://wiki.eclipse.org/Jetty/Howto/Configure_SSL</a></p>
 </div>
+<div class="sect4">
+<h5 id="_deploying_the_tweet_button_samples">Deploying the tweet button samples</h5>
 <div class="paragraph">
-<p>.</p>
+<p>In standard Karaf fashion, you will need to copy the samples bundle to your Karaf <code>deploy</code> directory.</p>
 </div>
 <div class="paragraph">
-<p>Update the keystore and certificate password in $MY_KARAF_HOME/etc/custom.properties file :</p>
+<p>If you are using the packaged version of Unomi (as opposed to deploying it to your own Karaf version), you can simply run, assuming your current directory is <code>samples/tweet-button-plugin</code> and that you uncompressed the archive in the directory it was created:</p>
 </div>
 <div class="listingblock">
 <div class="content">
-<pre class="highlight"><code>    org.osgi.service.http.secure.enabled = true
-    org.ops4j.pax.web.ssl.keystore=${karaf.etc}/keystore
-    org.ops4j.pax.web.ssl.password=changeme
-    org.ops4j.pax.web.ssl.keypassword=changeme
-    org.osgi.service.http.port.secure=9443</code></pre>
-</div>
-</div>
-<div class="paragraph">
-<p>You should now have SSL setup on Karaf with your certificate, and you can test it by trying to access it on port 9443.</p>
+<pre class="highlight"><code>cp target/tweet-button-plugin-1.0.0-incubating-SNAPSHOT.jar ../../package/target/unomi-1.0.0-incubating-SNAPSHOT/deploy</code></pre>
 </div>
-<div class="olist arabic">
-<ol class="arabic">
-<li>
-<p>Changing the default Karaf password can be done by modifying the etc/users.properties file</p>
-</li>
-</ol>
 </div>
 </div>
-<div class="sect3">
-<h4 id="_automatic_profile_merging">3.3.6. Automatic profile merging</h4>
+<div class="sect4">
+<h5 id="_testing_the_samples">Testing the samples</h5>
 <div class="paragraph">
-<p>The context server is capable of merging profiles based on a common property value. In order to use this, you must
-add the MergeProfileOnPropertyAction to a rule (such as a login rule for example), and configure it with the name
- of the property that will be used to identify the profiles to be merged. An example could be the "email" property,
- meaning that if two (or more) profiles are found to have the same value for the "email" property they will be merged
- by this action.</p>
+<p>You can now go to <a href="http://localhost:8181/index.html">http://localhost:8181/index.html</a> to test the samples code. The page is very simple, you will see a Twitter button, which, once clicked, will open a new window to tweet about the current page. The original page should be updated with the new values of the properties coming from Unomi. Additionnally, the raw JSON response is displayed.</p>
 </div>
 <div class="paragraph">
-<p>Upon merge, the old profiles are marked with a "mergedWith" property that will be used on next profile access to delete
-the original profile and replace it with the merged profile (aka "master" profile). Once this is done, all cookie tracking
-will use the merged profile.</p>
+<p>We will now explain in greater details some concepts and see how the example works.</p>
 </div>
-<div class="paragraph">
-<p>To test, simply configure the action in the "login" or "facebookLogin" rules and set it up on the "email" property.
-Upon sending one of the events, all matching profiles will be merged.</p>
 </div>
 </div>
 <div class="sect3">
-<h4 id="_securing_a_production_environment">3.3.7. Securing a production environment</h4>
-<div class="paragraph">
-<p>Before going live with a project, you should <em>absolutely</em> read the following section that will help you setup a proper
-secure environment for running your context server.</p>
-</div>
-<div class="paragraph">
-<p>Step 1: Install and configure a firewall</p>
-</div>
-<div class="paragraph">
-<p>You should setup a firewall around your cluster of context servers and/or Elasticsearch nodes. If you have an
-application-level firewall you should only allow the following connections open to the whole world :</p>
-</div>
-<div class="ulist">
-<ul>
-<li>
-<p><a href="http://localhost:8181/context.js">http://localhost:8181/context.js</a></p>
-</li>
-<li>
-<p><a href="http://localhost:8181/eventcollector">http://localhost:8181/eventcollector</a></p>
-</li>
-</ul>
-</div>
+<h4 id="_interacting_with_the_context_server">4.3.2. Interacting with the context server</h4>
 <div class="paragraph">
-<p>All other ports should not be accessible to the world.</p>
+<p>There are essentially two modalities to interact with the context server, reflecting different types of Unomi users: context server clients and context server integrators.</p>
 </div>
 <div class="paragraph">

[... 2843 lines stripped ...]