| --- |
| title: Tutorial |
| layout: default |
| --- |
| |
| <!-- Marketing messaging and featurettes |
| ================================================== --> |
| <!-- Wrap the rest of the page in another container to center all the content. --> |
| <div class="container"> |
| |
| <!-- Migrating ES --> |
| <div id="ubuntu-tutorial" class="row mb-5 mt-5"> |
| <div class="col"> |
| <h2 class="pb-3 border-bottom">Running and Interfacing with Apache Unomi 1.4 on Ubuntu</h2> |
| <p>This section includes a quick tutorial demonstrating how to install and interface with Unomi running on Ubuntu. The purpose of this tutorial is to demonstrate how to use the features of Apache Unomi.</p> |
| |
| <h3 class="pt-3 pb-2 text-dark">Install Java 8</h3> |
| <p>Unomi 1.4 requires Java 8. Use these command to install this specific version:</p> |
| <pre><code> |
| apt install openjdk-8-jdk |
| </code></pre> |
| <p>Set your <code>JAVA_HOME</code> by editing <code>/etc/environment</code>:</p> |
| <pre><code> |
| vi /etc/environment |
| </code></pre> |
| <p>and add these two lines below what is already there:</p> |
| <pre><code> |
| JAVA_HOME="/usr/lib/jvm/java-8-openjdk-amd64/" |
| PATH=$JAVA_HOME/bin:$PATH |
| </code></pre> |
| <div class="alert alert-warning" role="alert">Your <code>JAVA_HOME</code> may vary. You can review the output of the <code>apt install</code> command to see where Java was installed.</div> |
| <p>Now reload the environment:</p> |
| <pre><code> |
| source /etc/environment |
| </code></pre> |
| |
| <h3 class="pt-3 pb-2 text-dark">Installing ElasticSearch 5.6.3</h3> |
| <p>Unomi 1.4 requires ElasticSearch version 5.6.3. Use these command to install this specific version:</p> |
| <pre><code> |
| apt-get update && apt-get -y install apt-transport-https curl wget |
| wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-5.6.3.deb |
| dpkg -i elasticsearch-5.6.3.deb |
| </code></pre> |
| <p>Now, edit the ElasticSearch configuration:</p> |
| <pre><code> |
| vi /etc/elasticsearch/elasticsearch.yml |
| </code></pre> |
| <p>Uncomment and edit the line with <code>cluster.name</code> to:</p> |
| <pre><code> |
| cluster.name: contextElasticSearch |
| </code></pre> |
| <p>Now start and check the status of ElasticSearch to confirm it is running:</p> |
| <pre><code> |
| service elasticsearch start |
| service elasticsearch status |
| </code></pre> |
| |
| <h3 class="pt-3 pb-2 text-dark">Installing Unomi 1.4</h3> |
| <p>You can install a binary distribution from any of <a href="https://www.apache.org/dyn/closer.lua/incubator/unomi/1.4.0/unomi-1.4.0-bin.tar.gz">these</a> mirrors. Just download and extract the files, then run it using Karaf:</p> |
| <pre><code> |
| wget http://apache.mirrors.pair.com/incubator/unomi/1.4.0/unomi-1.4.0-bin.tar.gz |
| tar -xzf unomi-1.4.0-bin.tar.gz |
| </code></pre> |
| <p>After it is extracted, move it into <code>/opt/unomi</code>:</p> |
| <pre><code> |
| mkdir /opt/unomi |
| mv unomi-1.4.0-incubating/* |
| </code></pre> |
| |
| |
| <h3 class="pt-3 pb-2 text-dark">Start Unomi</h3> |
| <p>Next, start Unomi from the terminal:</p> |
| <pre><code> |
| /opt/unomi/bin/karaf |
| </code></pre> |
| <p>In the Karaf terminal, run <code>unomi:start</code>:</p> |
| <pre><code> |
| karaf@root()> unomi:start |
| </code></pre> |
| |
| <div class="alert alert-info"> |
| <h4 class="pt-3 pb-2 text-dark">Installing Unomi as a Service</h4> |
| <p>You can install Unomi as a service using Karaf's <a href="http://karaf.apache.org/manual/latest/#_service_wrapper">Service Wrapper</a>.</p> |
| <p>From the Karaf command line:</p> |
| <pre><code> |
| karaf@root()> feature:install wrapper |
| karaf@root()> wrapper:install |
| </code></pre> |
| <p>The output from the <code>wrapper:install</code> command will include instructions for finishing the installation and starting/stoping Karaf.</p> |
| </div> |
| |
| <h3 class="pt-3 pb-2 text-dark">Interfacing with Unomi</h3> |
| <p>Below are some Python scripts that demonstrate how to interface with Unomi.</p> |
| <p>You can check some endpoints in a web browser, the default username and password is `karaf` and `karaf`:</p> |
| <pre><code> |
| https://localhost:9443/cxs/cluster |
| http://localhost:8181/context.js?sessionId=1234 |
| </code></pre> |
| |
| |
| <h4 class="pt-3 pb-2 text-dark">Create a New Profile</h4> |
| <p>Run the Python code to create a new profile (use Python 3):</p> |
| <pre><code> |
| from requests import request |
| |
| """ |
| Make a request to Unomi to create a profile with ID = 10 |
| """ |
| r = requests.post('http://localhost:8181/cxs/profiles/', |
| auth=('karaf','karaf'), |
| json ={ |
| "itemId":"10", |
| "itemType":"profile", |
| "version":None, |
| "properties": { |
| "firstName": "John", |
| "lastName": "Smith" |
| }, |
| "systemProperties":{}, |
| "segments":[], |
| "scores":{}, |
| "mergedWith":None, |
| "consents":{} |
| }) |
| print(r) |
| print(r.content) |
| </code></pre> |
| <p>This creates a profile with ID 10. You can view this profile with a <a href="https://unomi.incubator.apache.org/rest-api-doc/#-1185500428">GET /profile endpoint</a> in the browser:</p> |
| <pre><code> |
| http://localhost:8181/cxs/profile/10 |
| </code></pre> |
| |
| <h4 class="pt-3 pb-2 text-dark">Create a New Profile and Session</h4> |
| <p>Run the Python code to create a new profile and session (use Python 3):</p> |
| <pre><code> |
| from requests import post |
| from datetime import datetime |
| |
| profile = { |
| "itemId":"10", |
| "itemType":"profile", |
| "version":None, |
| "properties": { |
| "firstName": "John", |
| "lastName": "Smith" |
| }, |
| "systemProperties":{}, |
| "segments":[], |
| "scores":{}, |
| "mergedWith":None, |
| "consents":{} |
| } |
| |
| session = { |
| "itemId": "101", |
| "itemType":"session", |
| "scope":None, |
| "version":1, |
| "profileId":profile_id, |
| "profile": profile, |
| "properties":{}, |
| "systemProperties":{}, |
| "timeStamp": datetime.now().strftime("%Y-%m-%dT%H:%M:%SZ") |
| } |
| |
| # Create or update profile |
| r = post('http://localhost:8181/cxs/profiles/', |
| auth=('karaf','karaf'), |
| json =profile) |
| print(r) |
| print(r.content) |
| |
| |
| # Create session |
| r = post('http://localhost:8181/cxs/profiles/sessions/101', |
| auth=('karaf', 'karaf'), |
| json=session) |
| |
| print(r) |
| print(r.content) |
| </code></pre> |
| <p>This creates a session with ID 101 and profile with ID 10. You can view this profile with a <a href="https://unomi.apache.org/rest-api-doc/#1764110248">[GET /profile/{profile_id}/sessions endpoint]</a> in the browser:</p> |
| <pre><code> |
| http://localhost:8181/cxs/profiles/10/sessions/ |
| </code></pre> |
| |
| <h4 class="pt-3 pb-2 text-dark">Create a New Rule</h4> |
| <p>Run the Python code to create a new rule (use Python 3):</p> |
| <pre><code> |
| import requests |
| |
| """ |
| Make a request to Unomi to create a rule that marks profiles as "eligible = yes" |
| when annualIncome < 12000 |
| """ |
| r = requests.post('http://localhost:8181/cxs/rules/', |
| auth=('karaf','karaf'), |
| json ={ |
| "metadata": { |
| "id": "eligibilityRule", |
| "name": "Example eligibility rule", |
| "description": "Profile annualIncome < 12000" |
| }, |
| "condition": { |
| "parameterValues": { |
| "subConditions": [ |
| { |
| "parameterValues": { |
| "propertyName": "properties.annualIncome", |
| "comparisonOperator": "greaterThan", |
| "propertyValueInt": 12000 |
| }, |
| "type": "profilePropertyCondition" |
| }, |
| { |
| "type": "profileUpdatedEventCondition", |
| "parameterValues": { |
| } |
| } |
| ], |
| "operator" : "and" |
| }, |
| "type": "booleanCondition" |
| }, |
| "actions": [ |
| { |
| "parameterValues": { |
| "setPropertyName": "properties.eligibility", |
| "setPropertyValue": "yes" |
| }, |
| "type": "setPropertyAction" |
| } |
| ] |
| }) |
| print("Rule Response Code:", r) |
| print("Rule Response Content:", r.content) |
| |
| |
| """ |
| Make a request to Unomi to create a profile with annualIncome < 12000 |
| """ |
| r = requests.post('http://localhost:8181/cxs/profiles/', |
| auth=('karaf','karaf'), |
| json ={ |
| "itemId":"10", |
| "itemType":"profile", |
| "version":None, |
| "properties": { |
| "firstName": "John", |
| "lastName": "Smith", |
| "annualIncome": 10000 |
| }, |
| "systemProperties":{}, |
| "segments":[], |
| "scores":{}, |
| "mergedWith":None, |
| "consents":{} |
| }) |
| print("Profile Response Code:", r) |
| print("Profile Response Content:", r.content) |
| </code></pre> |
| <p>This creates a rule with ID eligibilityRule and a profile with ID 10. You can view this rule with a <a href="https://unomi.apache.org/rest-api-doc/#-1505954579">[GET /rule/{rule_id} endpoint]</a> in the browser:</p> |
| <pre><code> |
| http://localhost:8181/cxs/rules/eligibilityRule/ |
| </code></pre> |
| <p>and you can view the profile which has been marked as eligible = "yes":</p> |
| <pre><code> |
| http://localhost:8181/cxs/profile/10 |
| </code></pre> |
| |
| </div><!-- /.blog-main --> |
| </div> |
| |
| <div id="docker-tutorial" class="row mb-5 mt-5"> |
| <div class="col"> |
| <h2 class="pb-3 border-bottom">Running Unomi 1.3 using Docker</h2> |
| <p>This section includes a quick tutorial demonstrating how to run Unomi using Docker. The purpose of this tutorial is to demonstrate how to run Apache Unomi in a Docker container.</p> |
| <h3 class="pt-3 pb-2 text-dark">Install Docker and Docker Compose</h3> |
| <p>Before you get started, you will need to install Docker and Docker Compose on your machine. Installation instructions can be found <a href="https://docs.docker.com/install/">here</a>. Docker for Mac and Docker Toolbox already include Docker Compose.</p> |
| <h3 class="pt-3 pb-2 text-dark">About the Required Images</h3> |
| <p>Unomi requires ElasticSearch so this setup will use an Elasticsearch image provided by <a href="https://www.elastic.co/">Elasticsearch B.V.</a>. We will use a Unomi Docker image mantained by the community.</p> |
| <ul> |
| <li><a href="https://hub.docker.com/r/mikeghen/unomi/">Unomi 1.3 image</a></li> |
| <li><a href="https://hub.docker.com/_/elasticsearch/">ElasticSearch 5.6.3 image</a></li> |
| </ul> |
| <h3 class="pt-3 pb-2 text-dark">Create a Docker Compose Configuration</h3> |
| <p>Create a new directory and add a <code>docker-compose.yaml</code> file. Then copy the code below into that file.</p> |
| <pre><code> |
| version: '2.2' |
| services: |
| elasticsearch: |
| image: docker.elastic.co/elasticsearch/elasticsearch:5.6.3 |
| volumes: # Persist ES data in seperate "esdata" volume |
| - esdata1:/usr/share/elasticsearch/data |
| environment: |
| - bootstrap.memory_lock=true |
| - "ES_JAVA_OPTS=-Xms512m -Xmx512m" |
| - discovery.type=single-node |
| - xpack.security.enabled=false |
| - cluster.name=contextElasticSearch |
| ports: # Expose Elasticsearch ports |
| - "9300:9300" |
| - "9200:9200" |
| unomi: |
| image: mikeghen/unomi:1.3 |
| container_name: unomi |
| environment: |
| - ELASTICSEARCH_HOST=elasticsearch |
| - ELASTICSEARCH_PORT=9300 |
| ports: |
| - 8181:8181 |
| - 9443:9443 |
| links: |
| - elasticsearch |
| depends_on: |
| - elasticsearch |
| |
| volumes: # Define seperate volume for Elasticsearch data |
| esdata1: |
| driver: local |
| </code></pre> |
| <p>The configuration above creates a single node ElasticSearch container with persistent storage. It also creates a single Unomi container and links it so it can access ElasticSearch.</p> |
| <p>You can find the code for the Unomi image here: <a href="https://github.com/mikeghen/unomi-docker">https://github.com/mikeghen/unomi-docker</a> |
| <h3 class="pt-3 pb-2 text-dark">Create the Environment with Docker Compose</h3> |
| <p>To start everything, run this command from the same directory where the <code>docker-compose.yaml</code> file exists:</p> |
| <pre><code> |
| docker-compose up |
| </code></pre> |
| <div class="alert alert-warning" role="alert">At this point you need to wait several minutes for both ElasticSearch and Unomi to become available</div> |
| <h3 class="pt-3 pb-2 text-dark">Check Unomi Services are Running</h3> |
| <p>You will need to wait a few minutes for ElasticSearch and Unomi to start up. Check that services are running locally by opening this URL in a browser:</p> |
| <pre><code> |
| http://localhost:8181/cxs |
| </code></pre> |
| <p>This will check Unomi. It will come back with "Available RESTful services" and a list of services when Unomi finishes starting up.</p> |
| <p>You can check ElasticSearch is running with this curl command: |
| <pre><code> |
| curl http://localhost:9200/_cat/health?format=json |
| </code></pre> |
| <p>This will come back with a "yellow" status which is just because we're only running 1 ElasticSearch node.</p> |
| </div> |
| </div> |
| |
| </div><!-- /.container --> |