You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@unomi.apache.org by sh...@apache.org on 2017/01/19 17:08:38 UTC

incubator-unomi git commit: UNOMI-73 Add a log when Unomi is properly initialized. This commit contains global log improvements to services startup and shutdown, in order to diagnose problems when bundles are started or shutdown. It also adds a global Bu

Repository: incubator-unomi
Updated Branches:
  refs/heads/master 46f035819 -> a4a0bdfed


UNOMI-73 Add a log when Unomi is properly initialized.
This commit contains global log improvements to services startup and shutdown, in order to diagnose problems when bundles are started or shutdown. It also adds a global BundleWatcher that will check when the proper conditions are met for the Apache Unomi to be properly started.
In this commit we also get rid of the no longer needed CDI integration.
We also fix some problems with the properties, having to move a few from the org.apache.unomi.web.cfg file to the org.apache.unomi.cluster.cfg file.

Signed-off-by: Serge Huber <sh...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/incubator-unomi/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-unomi/commit/a4a0bdfe
Tree: http://git-wip-us.apache.org/repos/asf/incubator-unomi/tree/a4a0bdfe
Diff: http://git-wip-us.apache.org/repos/asf/incubator-unomi/diff/a4a0bdfe

Branch: refs/heads/master
Commit: a4a0bdfedc414596fdecb3dd2f3ba265fd205443
Parents: 46f0358
Author: Serge Huber <sh...@apache.org>
Authored: Thu Jan 19 18:07:36 2017 +0100
Committer: Serge Huber <sh...@apache.org>
Committed: Thu Jan 19 18:07:36 2017 +0100

----------------------------------------------------------------------
 .../unomi/geonames/rest/GeonamesEndPoint.java   |   6 +-
 .../lists/rest/UserListServiceEndPoint.java     |   7 +-
 .../java/org/apache/unomi/itests/BaseIT.java    |   2 -
 kar/src/main/feature/feature.xml                |   5 +-
 lifecycle-watcher/pom.xml                       |  41 ++++
 .../apache/unomi/lifecycle/BundleWatcher.java   | 190 +++++++++++++++++++
 .../resources/OSGI-INF/blueprint/blueprint.xml  |  39 ++++
 lifecycle-watcher/src/main/resources/logo.txt   |  26 +++
 package/pom.xml                                 |   2 -
 .../unomi/performancetests/BasicTest.java       |   2 -
 .../ElasticSearchPersistenceServiceImpl.java    |  61 +++---
 .../resources/OSGI-INF/blueprint/blueprint.xml  |  21 +-
 .../core/src/main/resources/log4j2.xml          |   2 +-
 ...g.apache.unomi.persistence.elasticsearch.cfg |   4 +
 pom.xml                                         |   1 +
 .../unomi/rest/CampaignsServiceEndPoint.java    |   6 +-
 .../unomi/rest/ClusterServiceEndPoint.java      |   2 +-
 .../unomi/rest/ProfileServiceEndPoint.java      |   2 +-
 .../apache/unomi/rest/RulesServiceEndPoint.java |   6 +-
 .../unomi/rest/ScoringServiceEndPoint.java      |   6 +-
 .../unomi/rest/SegmentServiceEndPoint.java      |   6 +-
 .../services/services/ClusterServiceImpl.java   |  17 +-
 .../services/DefinitionsServiceImpl.java        |   4 +-
 .../services/services/EventServiceImpl.java     |   8 +
 .../services/services/GoalsServiceImpl.java     |   3 +-
 .../services/services/ProfileServiceImpl.java   |   2 +
 .../services/services/QueryServiceImpl.java     |   2 +
 .../services/services/RulesServiceImpl.java     |   2 +
 .../services/services/SegmentServiceImpl.java   |   2 +
 .../resources/OSGI-INF/blueprint/blueprint.xml  |  18 +-
 .../main/resources/org.apache.unomi.cluster.cfg |   6 +-
 src/site/markdown/building-and-deploying.md     |   2 +-
 src/site/markdown/configuration.md              |  19 +-
 wab/pom.xml                                     |  22 ---
 .../org/apache/unomi/web/ContextServlet.java    |   7 +
 .../unomi/web/EventsCollectorServlet.java       |  13 ++
 wab/src/main/resources/org.apache.unomi.web.cfg |   7 +-
 wab/src/main/webapp/WEB-INF/beans.xml           |   0
 38 files changed, 443 insertions(+), 128 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/extensions/geonames/rest/src/main/java/org/apache/unomi/geonames/rest/GeonamesEndPoint.java
----------------------------------------------------------------------
diff --git a/extensions/geonames/rest/src/main/java/org/apache/unomi/geonames/rest/GeonamesEndPoint.java b/extensions/geonames/rest/src/main/java/org/apache/unomi/geonames/rest/GeonamesEndPoint.java
index 3821760..206018c 100644
--- a/extensions/geonames/rest/src/main/java/org/apache/unomi/geonames/rest/GeonamesEndPoint.java
+++ b/extensions/geonames/rest/src/main/java/org/apache/unomi/geonames/rest/GeonamesEndPoint.java
@@ -22,6 +22,8 @@ import org.apache.cxf.rs.security.cors.CrossOriginResourceSharing;
 import org.apache.unomi.api.PartialList;
 import org.apache.unomi.geonames.services.GeonameEntry;
 import org.apache.unomi.geonames.services.GeonamesService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.jws.WebMethod;
 import javax.jws.WebService;
@@ -40,10 +42,12 @@ import java.util.Locale;
 )
 public class GeonamesEndPoint {
 
+    private static final Logger logger = LoggerFactory.getLogger(GeonamesEndPoint.class.getName());
+
     private GeonamesService geonamesService;
 
     public GeonamesEndPoint() {
-        System.out.println("Initializing geonames service endpoint...");
+        logger.info("Initializing geonames service endpoint...");
     }
 
     @WebMethod(exclude = true)

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/extensions/lists-extension/rest/src/main/java/org/apache/unomi/lists/rest/UserListServiceEndPoint.java
----------------------------------------------------------------------
diff --git a/extensions/lists-extension/rest/src/main/java/org/apache/unomi/lists/rest/UserListServiceEndPoint.java b/extensions/lists-extension/rest/src/main/java/org/apache/unomi/lists/rest/UserListServiceEndPoint.java
index a4eb8c9..492bc45 100644
--- a/extensions/lists-extension/rest/src/main/java/org/apache/unomi/lists/rest/UserListServiceEndPoint.java
+++ b/extensions/lists-extension/rest/src/main/java/org/apache/unomi/lists/rest/UserListServiceEndPoint.java
@@ -23,6 +23,8 @@ import org.apache.unomi.api.PartialList;
 import org.apache.unomi.api.query.Query;
 import org.apache.unomi.lists.UserList;
 import org.apache.unomi.services.UserListService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.jws.WebMethod;
 import javax.jws.WebService;
@@ -40,10 +42,13 @@ import javax.ws.rs.core.MediaType;
         allowCredentials = true
 )
 public class UserListServiceEndPoint {
+
+    private static final Logger logger = LoggerFactory.getLogger(UserListServiceEndPoint.class.getName());
+
     private UserListService userListService;
 
     public UserListServiceEndPoint() {
-        System.out.println("Initializing user list service endpoint...");
+        logger.info("Initializing user list service endpoint...");
     }
 
     @WebMethod(exclude = true)

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
index 334e7c6..6a10a4d 100644
--- a/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
+++ b/itests/src/test/java/org/apache/unomi/itests/BaseIT.java
@@ -92,8 +92,6 @@ public abstract class BaseIT {
                 systemProperty("org.ops4j.pax.exam.rbc.rmi.port").value("1199"),
                 features(karafPaxWebRepo, "war"),
                 features(karafCxfRepo, "cxf"),
-                features(karafStandardRepo, "openwebbeans"),
-                features(karafStandardRepo, "pax-cdi-web-openwebbeans"),
                 features(karafCellarRepo, "cellar"),
                 features(contextServerRepo, "unomi-kar"),
                 // we need to wrap the HttpComponents libraries ourselves since the OSGi bundles provided by the project are incorrect

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/kar/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/kar/src/main/feature/feature.xml b/kar/src/main/feature/feature.xml
index fa3ef1f..e3351b7 100644
--- a/kar/src/main/feature/feature.xml
+++ b/kar/src/main/feature/feature.xml
@@ -18,11 +18,9 @@
 
 <features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="unomi-kar">
     <feature description="unomi-kar" version="${project.version}" name="unomi-kar"
-             start-level="75">
+             start-level="70">
         <feature>war</feature>
         <feature>cxf</feature>
-        <feature>openwebbeans</feature>
-        <feature>pax-cdi-web-openwebbeans</feature>
         <feature>cellar</feature>
         <configfile finalname="/etc/org.apache.unomi.web.cfg">mvn:org.apache.unomi/unomi-wab/${project.version}/cfg/unomicfg</configfile>
         <configfile finalname="/etc/org.apache.unomi.persistence.elasticsearch.cfg">mvn:org.apache.unomi/unomi-persistence-elasticsearch-core/${project.version}/cfg/elasticsearchcfg</configfile>
@@ -33,6 +31,7 @@
         <configfile finalname="/etc/hazelcast.xml">mvn:org.apache.unomi/unomi-services/${project.version}/xml/hazelcastconfig</configfile>
         <configfile finalname="/etc/org.apache.unomi.privacy.cfg">mvn:org.apache.unomi/cxs-privacy-extension-services/${project.version}/cfg/privacycfg</configfile>
         <configfile finalname="/etc/org.apache.unomi.geonames.cfg">mvn:org.apache.unomi/cxs-geonames-services/${project.version}/cfg/geonamescfg</configfile>
+        <bundle start-level="70">mvn:org.apache.unomi/unomi-lifecycle-watcher/${project.version}</bundle>
         <bundle start-level="75">mvn:commons-io/commons-io/2.4</bundle>
         <bundle start-level="75">mvn:com.fasterxml.jackson.core/jackson-core/${version.jackson.core}</bundle>
         <bundle start-level="75">mvn:com.fasterxml.jackson.core/jackson-databind/${version.jackson.core}</bundle>

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/lifecycle-watcher/pom.xml
----------------------------------------------------------------------
diff --git a/lifecycle-watcher/pom.xml b/lifecycle-watcher/pom.xml
new file mode 100644
index 0000000..b8e7353
--- /dev/null
+++ b/lifecycle-watcher/pom.xml
@@ -0,0 +1,41 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <parent>
+        <artifactId>unomi-root</artifactId>
+        <groupId>org.apache.unomi</groupId>
+        <version>1.2.0-incubating-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>unomi-lifecycle-watcher</artifactId>
+    <name>Apache Unomi :: Main Lifecycle Watcher</name>
+    <description>A global lifecycle watcher for the Apache Unomi Context server</description>
+    <packaging>bundle</packaging>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java
----------------------------------------------------------------------
diff --git a/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java
new file mode 100644
index 0000000..d688ff8
--- /dev/null
+++ b/lifecycle-watcher/src/main/java/org/apache/unomi/lifecycle/BundleWatcher.java
@@ -0,0 +1,190 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.unomi.lifecycle;
+
+import org.osgi.framework.*;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.*;
+
+/**
+ * This class listens to the global Apache Unomi bundle lifecycle, to provide statistics and state of the overall
+ * system. It notably displays messages for successfull or unsuccessfull startups as well as startup times.
+ */
+public class BundleWatcher implements SynchronousBundleListener, ServiceListener {
+
+    private static final Logger logger = LoggerFactory.getLogger(BundleWatcher.class.getName());
+
+    private long startupTime;
+    private Map<String,Long> bundleStartupTimes = new LinkedHashMap<>();
+    private long unomiStartedBundleCount = 0;
+    private long requiredStartedBundleCount;
+
+    private String requiredServices;
+    private Set<Filter> requiredServicesFilters = new LinkedHashSet<>();
+    private long matchedRequiredServicesCount = 0;
+
+    private BundleContext bundleContext;
+    private boolean startupMessageAlreadyDisplayed = false;
+    private List<String> logoLines = new ArrayList<>();
+
+    public void setRequiredStartedBundleCount(long requiredStartedBundleCount) {
+        this.requiredStartedBundleCount = requiredStartedBundleCount;
+    }
+
+    public void setRequiredServices(String requiredServices) {
+        this.requiredServices = requiredServices;
+        String[] requiredServiceArray = requiredServices.split(",");
+        requiredServicesFilters.clear();
+        for (String requiredService : requiredServiceArray) {
+            try {
+                requiredServicesFilters.add(bundleContext.createFilter(requiredService.trim()));
+            } catch (InvalidSyntaxException e) {
+                logger.error("Error creating require service filter {}", requiredService.trim(), e);
+            }
+        }
+    }
+
+    public void setBundleContext(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    public void init() {
+        bundleContext.addBundleListener(this);
+        bundleContext.addServiceListener(this);
+        URL logoURL = bundleContext.getBundle().getResource("logo.txt");
+        if (logoURL != null) {
+            BufferedReader bufferedReader = null;
+            try {
+                bufferedReader = new BufferedReader(new InputStreamReader(logoURL.openStream()));
+                String line;
+                while ((line = bufferedReader.readLine()) != null) {
+                    if (!line.trim().startsWith("#")) {
+                        logoLines.add(line);
+                    }
+                }
+            } catch (IOException e) {
+                logger.error("Error loading logo lines", e);
+            } finally {
+                if (bufferedReader != null) {
+                    try {
+                        bufferedReader.close();
+                    } catch (IOException e) {
+                    }
+                }
+            }
+        }
+        startupTime = System.currentTimeMillis();
+        logger.info("Bundle watcher initialized.");
+    }
+
+    public void destroy() {
+        bundleContext.removeServiceListener(this);
+        bundleContext.removeBundleListener(this);
+        logger.info("Bundle watcher shutdown.");
+    }
+
+    @Override
+    public void bundleChanged(BundleEvent event) {
+        switch (event.getType()) {
+            case BundleEvent.STARTING:
+                break;
+            case BundleEvent.STARTED:
+                if (event.getBundle().getSymbolicName().startsWith("org.apache.unomi")) {
+                    unomiStartedBundleCount++;
+                    checkStartupComplete();
+                }
+                break;
+            case BundleEvent.STOPPING:
+                break;
+            case BundleEvent.STOPPED:
+                if (event.getBundle().getSymbolicName().startsWith("org.apache.unomi")) {
+                    unomiStartedBundleCount--;
+                }
+                break;
+        }
+    }
+
+    @Override
+    public void serviceChanged(ServiceEvent event) {
+        ServiceReference serviceReference = event.getServiceReference();
+        if (serviceReference == null) {
+            return;
+        }
+        switch (event.getType()) {
+            case ServiceEvent.REGISTERED:
+                addStartedService(serviceReference);
+                checkStartupComplete();
+                break;
+            case ServiceEvent.MODIFIED:
+                break;
+            case ServiceEvent.UNREGISTERING:
+                removeStartedService(serviceReference);
+                break;
+        }
+    }
+
+    private void addStartedService(ServiceReference serviceReference) {
+        for (Filter requiredService : requiredServicesFilters) {
+            if (requiredService.match(serviceReference)) {
+                matchedRequiredServicesCount++;
+            }
+        }
+    }
+
+    private void removeStartedService(ServiceReference serviceReference) {
+        for (Filter requiredService : requiredServicesFilters) {
+            if (requiredService.match(serviceReference)) {
+                matchedRequiredServicesCount--;
+                logger.info("Apache Unomi no longer available, as required service {} is shutdown !", serviceReference);
+                startupMessageAlreadyDisplayed = false;
+            }
+        }
+    }
+
+    private void checkStartupComplete() {
+        if (!isStartupComplete()) {
+            return;
+        }
+        if (!startupMessageAlreadyDisplayed) {
+            long totalStartupTime = System.currentTimeMillis() - startupTime;
+            if (logoLines.size() > 0) {
+                for (String logoLine : logoLines) {
+                    System.out.println(logoLine);
+                }
+            }
+            System.out.println("Successfully started " + unomiStartedBundleCount + " bundles and " + matchedRequiredServicesCount + " required services in " + totalStartupTime + " ms");
+            logger.info("Apache Unomi successfully started {} bundles and {} required services in {} ms", unomiStartedBundleCount, matchedRequiredServicesCount, totalStartupTime);
+            startupMessageAlreadyDisplayed = true;
+        }
+    }
+
+    private boolean isStartupComplete() {
+        if (unomiStartedBundleCount < requiredStartedBundleCount) {
+            return false;
+        }
+        if (matchedRequiredServicesCount < requiredServicesFilters.size()) {
+            return false;
+        }
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml
new file mode 100644
index 0000000..01112a3
--- /dev/null
+++ b/lifecycle-watcher/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<blueprint xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
+           xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 http://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd
+           http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd">
+
+    <cm:property-placeholder persistent-id="org.apache.unomi.lifecycle"
+                             update-strategy="reload" placeholder-prefix="${lifecycle.">
+        <cm:default-properties>
+            <cm:property name="requiredStartedBundleCount" value="16" />
+            <cm:property name="requiredServices" value="(urlPatterns=/eventcollector),(urlPatterns=/context.json)" />
+        </cm:default-properties>
+    </cm:property-placeholder>
+
+    <bean id="bundleWatcher" init-method="init" destroy-method="destroy" class="org.apache.unomi.lifecycle.BundleWatcher">
+        <property name="bundleContext" ref="blueprintBundleContext"/>
+        <property name="requiredServices" value="${lifecycle.requiredServices}" />
+        <property name="requiredStartedBundleCount" value="${lifecycle.requiredStartedBundleCount}" />
+    </bean>
+
+</blueprint>

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/lifecycle-watcher/src/main/resources/logo.txt
----------------------------------------------------------------------
diff --git a/lifecycle-watcher/src/main/resources/logo.txt b/lifecycle-watcher/src/main/resources/logo.txt
new file mode 100644
index 0000000..0db2b87
--- /dev/null
+++ b/lifecycle-watcher/src/main/resources/logo.txt
@@ -0,0 +1,26 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+
+        ____ ___     A P A C H E     .__
+       |    |   \____   ____   _____ |__|
+       |    |   /    \ /  _ \ /     \|  |
+       |    |  /   |  (  <_> )  Y Y  \  |
+       |______/|___|  /\____/|__|_|  /__|
+                    \/             \/
+
+--------------------------------------------------------------------------
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/package/pom.xml
----------------------------------------------------------------------
diff --git a/package/pom.xml b/package/pom.xml
index b2e2c91..0b29901 100644
--- a/package/pom.xml
+++ b/package/pom.xml
@@ -284,8 +284,6 @@
                                 <feature>kar</feature>
                                 <feature>war</feature>
                                 <feature>cxf</feature>
-                                <feature>openwebbeans</feature>
-                                <feature>pax-cdi-web-openwebbeans</feature>
                                 <feature>cellar</feature>
                                 <feature>unomi-kar</feature>
                             </bootFeatures>

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/performance-tests/src/test/java/org/apache/unomi/performancetests/BasicTest.java
----------------------------------------------------------------------
diff --git a/performance-tests/src/test/java/org/apache/unomi/performancetests/BasicTest.java b/performance-tests/src/test/java/org/apache/unomi/performancetests/BasicTest.java
index 82a5b4f..4ed0ea6 100644
--- a/performance-tests/src/test/java/org/apache/unomi/performancetests/BasicTest.java
+++ b/performance-tests/src/test/java/org/apache/unomi/performancetests/BasicTest.java
@@ -131,8 +131,6 @@ public class BasicTest {
                 keepRuntimeFolder(),
                 KarafDistributionOption.features(karafPaxWebRepo, "war"),
                 KarafDistributionOption.features(karafCxfRepo, "cxf"),
-                KarafDistributionOption.features(karafStandardRepo, "openwebbeans"),
-                KarafDistributionOption.features(karafStandardRepo, "pax-cdi-web-openwebbeans"),
                 KarafDistributionOption.features(contextServerRepo, "unomi-kar"),
                 // we need to wrap the HttpComponents libraries ourselves since the OSGi bundles provided by the project are incorrect
                 wrappedBundle(mavenBundle("org.apache.httpcomponents",

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java
----------------------------------------------------------------------
diff --git a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java
index 7abcbd5..04f0602 100644
--- a/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java
+++ b/persistence-elasticsearch/core/src/main/java/org/apache/unomi/persistence/elasticsearch/ElasticSearchPersistenceServiceImpl.java
@@ -42,8 +42,8 @@ import org.elasticsearch.action.search.SearchRequestBuilder;
 import org.elasticsearch.action.search.SearchResponse;
 import org.elasticsearch.action.support.WriteRequest;
 import org.elasticsearch.action.update.UpdateRequest;
-import org.elasticsearch.client.Client;
 import org.elasticsearch.client.Requests;
+import org.elasticsearch.client.transport.TransportClient;
 import org.elasticsearch.cluster.metadata.MappingMetaData;
 import org.elasticsearch.common.collect.ImmutableOpenMap;
 import org.elasticsearch.common.settings.Settings;
@@ -113,8 +113,10 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
     public static final String BULK_PROCESSOR_FLUSH_INTERVAL = "bulkProcessor.flushInterval";
     public static final String BULK_PROCESSOR_BACKOFF_POLICY = "bulkProcessor.backoffPolicy";
 
-    private Client client;
+    private TransportClient client;
     private BulkProcessor bulkProcessor;
+    private String elasticSearchAddresses;
+    private List<String> elasticSearchAddressList = new ArrayList<>();
     private String clusterName;
     private String indexName;
     private String monthlyIndexNumberOfShards;
@@ -131,10 +133,6 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
     private Map<String, String> routingByType;
     private Set<String> existingIndexNames = new TreeSet<String>();
 
-    private String address;
-    private String port;
-    private String secureAddress;
-    private String securePort;
     private Integer defaultQueryLimit = 10;
 
     private Timer timer;
@@ -159,6 +157,15 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
         this.clusterName = clusterName;
     }
 
+    public void setElasticSearchAddresses(String elasticSearchAddresses) {
+        this.elasticSearchAddresses = elasticSearchAddresses;
+        String[] elasticSearchAddressesArray = elasticSearchAddresses.split(",");
+        elasticSearchAddressList.clear();
+        for (String elasticSearchAddress : elasticSearchAddressesArray) {
+            elasticSearchAddressList.add(elasticSearchAddress.trim());
+        }
+    }
+
     public void setIndexName(String indexName) {
         this.indexName = indexName;
     }
@@ -179,22 +186,6 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
         this.numberOfReplicas = numberOfReplicas;
     }
 
-    public void setAddress(String address) {
-        this.address = address;
-    }
-
-    public void setPort(String port) {
-        this.port = port;
-    }
-
-    public void setSecureAddress(String secureAddress) {
-        this.secureAddress = secureAddress;
-    }
-
-    public void setSecurePort(String securePort) {
-        this.securePort = securePort;
-    }
-
     public void setDefaultQueryLimit(Integer defaultQueryLimit) {
         this.defaultQueryLimit = defaultQueryLimit;
     }
@@ -260,11 +251,6 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
             public Object execute(Object... args) throws Exception {
                 logger.info("Connecting to ElasticSearch persistence backend using cluster name " + clusterName + " and index name " + indexName + "...");
 
-                address = System.getProperty(CONTEXTSERVER_ADDRESS, address);
-                port = System.getProperty(CONTEXTSERVER_PORT, port);
-                secureAddress = System.getProperty(CONTEXTSERVER_SECURE_ADDRESS, secureAddress);
-                securePort = System.getProperty(CONTEXTSERVER_SECURE_PORT, securePort);
-
                 bulkProcessorName = System.getProperty(BULK_PROCESSOR_NAME, bulkProcessorName);
                 bulkProcessorConcurrentRequests = System.getProperty(BULK_PROCESSOR_CONCURRENT_REQUESTS, bulkProcessorConcurrentRequests);
                 bulkProcessorBulkActions = System.getProperty(BULK_PROCESSOR_BULK_ACTIONS, bulkProcessorBulkActions);
@@ -272,14 +258,19 @@ public class ElasticSearchPersistenceServiceImpl implements PersistenceService,
                 bulkProcessorFlushInterval = System.getProperty(BULK_PROCESSOR_FLUSH_INTERVAL, bulkProcessorFlushInterval);
                 bulkProcessorBackoffPolicy = System.getProperty(BULK_PROCESSOR_BACKOFF_POLICY, bulkProcessorBackoffPolicy);
 
-                try {
-                    Settings transportSettings = Settings.builder()
-                            .put(CLUSTER_NAME, clusterName).build();
-                    client = new PreBuiltTransportClient(transportSettings)
-                            .addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(address), 9300));
-                } catch (UnknownHostException e) {
-                    String message = "Error resolving address " + address + " ElasticSearch transport client not connected";
-                    throw new Exception(message, e);
+                Settings transportSettings = Settings.builder()
+                        .put(CLUSTER_NAME, clusterName).build();
+                client = new PreBuiltTransportClient(transportSettings);
+                for (String elasticSearchAddress : elasticSearchAddressList) {
+                    String[] elasticSearchAddressParts = elasticSearchAddress.split(":");
+                    String elasticSearchHostName = elasticSearchAddressParts[0];
+                    int elasticSearchPort = Integer.parseInt(elasticSearchAddressParts[1]);
+                    try {
+                        client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(elasticSearchHostName), elasticSearchPort));
+                    } catch (UnknownHostException e) {
+                        String message = "Error resolving address " + elasticSearchAddress + " ElasticSearch transport client not connected";
+                        throw new Exception(message, e);
+                    }
                 }
 
                 // let's now check the versions of all the nodes in the cluster, to make sure they are as expected.

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index 1135ef5..3ca23a9 100644
--- a/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/persistence-elasticsearch/core/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -31,6 +31,7 @@
                              update-strategy="reload" placeholder-prefix="${es.">
         <cm:default-properties>
             <cm:property name="cluster.name" value="contextElasticSearch"/>
+            <cm:property name="elasticSearchAddresses" value="localhost:9300"/>
             <cm:property name="index.name" value="context"/>
             <cm:property name="numberOfShards" value="5"/>
             <cm:property name="numberOfReplicas" value="0"/>
@@ -51,21 +52,6 @@
         </cm:default-properties>
     </cm:property-placeholder>
 
-    <cm:property-placeholder persistent-id="org.apache.unomi.web"
-                             update-strategy="reload" placeholder-prefix="${web.">
-        <cm:default-properties>
-            <cm:property name="contextserver.address" value="localhost"/>
-            <cm:property name="contextserver.port" value="8181"/>
-            <cm:property name="contextserver.secureAddress" value="localhost"/>
-            <cm:property name="contextserver.securePort" value="9443"/>
-        </cm:default-properties>
-    </cm:property-placeholder>
-
-    <reference id="karafCellarClusterManager" interface="org.apache.karaf.cellar.core.ClusterManager" />
-    <reference id="karafCellarEventProducer" interface="org.apache.karaf.cellar.core.event.EventProducer" />
-    <reference id="karafCellarGroupManager" interface="org.apache.karaf.cellar.core.GroupManager" />
-    <reference id="osgiConfigurationAdmin" interface="org.osgi.service.cm.ConfigurationAdmin"/>
-
     <service id="elasticSearchPersistenceService" ref="elasticSearchPersistenceServiceImpl">
         <interfaces>
             <value>org.apache.unomi.persistence.spi.PersistenceService</value>
@@ -93,10 +79,7 @@
         <property name="monthlyIndexNumberOfReplicas" value="${es.monthlyIndex.numberOfReplicas}"/>
         <property name="numberOfShards" value="${es.numberOfShards}"/>
         <property name="numberOfReplicas" value="${es.numberOfReplicas}"/>
-        <property name="address" value="${web.contextserver.address}"/>
-        <property name="port" value="${web.contextserver.port}"/>
-        <property name="secureAddress" value="${web.contextserver.secureAddress}"/>
-        <property name="securePort" value="${web.contextserver.securePort}"/>
+        <property name="elasticSearchAddresses" value="${es.elasticSearchAddresses}"/>
         <property name="defaultQueryLimit" value="${es.defaultQueryLimit}"/>
         <property name="itemsMonthlyIndexed">
             <list>

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/persistence-elasticsearch/core/src/main/resources/log4j2.xml
----------------------------------------------------------------------
diff --git a/persistence-elasticsearch/core/src/main/resources/log4j2.xml b/persistence-elasticsearch/core/src/main/resources/log4j2.xml
index ccafeef..dfb279b 100644
--- a/persistence-elasticsearch/core/src/main/resources/log4j2.xml
+++ b/persistence-elasticsearch/core/src/main/resources/log4j2.xml
@@ -22,7 +22,7 @@
         </Console>
     </Appenders>
     <Loggers>
-        <Root level="info">
+        <Root level="warn">
             <AppenderRef ref="Console"/>
         </Root>
     </Loggers>

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/persistence-elasticsearch/core/src/main/resources/org.apache.unomi.persistence.elasticsearch.cfg
----------------------------------------------------------------------
diff --git a/persistence-elasticsearch/core/src/main/resources/org.apache.unomi.persistence.elasticsearch.cfg b/persistence-elasticsearch/core/src/main/resources/org.apache.unomi.persistence.elasticsearch.cfg
index e0c382c..4e52a1c 100644
--- a/persistence-elasticsearch/core/src/main/resources/org.apache.unomi.persistence.elasticsearch.cfg
+++ b/persistence-elasticsearch/core/src/main/resources/org.apache.unomi.persistence.elasticsearch.cfg
@@ -16,6 +16,10 @@
 #
 
 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
 monthlyIndex.numberOfShards=3
 monthlyIndex.numberOfReplicas=0

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index e47920a..0cd2993 100644
--- a/pom.xml
+++ b/pom.xml
@@ -834,6 +834,7 @@
     <modules>
         <module>api</module>
         <module>persistence-spi</module>
+        <module>lifecycle-watcher</module>
         <module>persistence-elasticsearch</module>
         <module>services</module>
         <module>rest</module>

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/rest/src/main/java/org/apache/unomi/rest/CampaignsServiceEndPoint.java
----------------------------------------------------------------------
diff --git a/rest/src/main/java/org/apache/unomi/rest/CampaignsServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/CampaignsServiceEndPoint.java
index 2cca082..28d275a 100644
--- a/rest/src/main/java/org/apache/unomi/rest/CampaignsServiceEndPoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/CampaignsServiceEndPoint.java
@@ -26,6 +26,8 @@ import org.apache.unomi.api.campaigns.events.CampaignEvent;
 import org.apache.unomi.api.query.Query;
 import org.apache.unomi.api.rules.Rule;
 import org.apache.unomi.api.services.GoalsService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.jws.WebMethod;
 import javax.jws.WebService;
@@ -45,10 +47,12 @@ import java.util.Set;
 )
 public class CampaignsServiceEndPoint {
 
+    private static final Logger logger = LoggerFactory.getLogger(CampaignsServiceEndPoint.class.getName());
+
     private GoalsService goalsService;
 
     public CampaignsServiceEndPoint() {
-        System.out.println("Initializing campaigns service endpoint...");
+        logger.info("Initializing campaigns service endpoint...");
     }
 
     @WebMethod(exclude=true)

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/rest/src/main/java/org/apache/unomi/rest/ClusterServiceEndPoint.java
----------------------------------------------------------------------
diff --git a/rest/src/main/java/org/apache/unomi/rest/ClusterServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/ClusterServiceEndPoint.java
index 62da187..21134e2 100644
--- a/rest/src/main/java/org/apache/unomi/rest/ClusterServiceEndPoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/ClusterServiceEndPoint.java
@@ -51,7 +51,7 @@ public class ClusterServiceEndPoint {
     private ClusterService clusterService;
 
     public ClusterServiceEndPoint() {
-        System.out.println("Initializing cluster service endpoint...");
+        logger.info("Initializing cluster service endpoint...");
     }
 
     @WebMethod(exclude = true)

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/rest/src/main/java/org/apache/unomi/rest/ProfileServiceEndPoint.java
----------------------------------------------------------------------
diff --git a/rest/src/main/java/org/apache/unomi/rest/ProfileServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/ProfileServiceEndPoint.java
index ace49c0..260e7a1 100644
--- a/rest/src/main/java/org/apache/unomi/rest/ProfileServiceEndPoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/ProfileServiceEndPoint.java
@@ -61,7 +61,7 @@ public class ProfileServiceEndPoint {
     private LocalizationHelper localizationHelper;
 
     public ProfileServiceEndPoint() {
-        System.out.println("Initializing profile service endpoint...");
+        logger.info("Initializing profile service endpoint...");
     }
 
     @WebMethod(exclude = true)

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/rest/src/main/java/org/apache/unomi/rest/RulesServiceEndPoint.java
----------------------------------------------------------------------
diff --git a/rest/src/main/java/org/apache/unomi/rest/RulesServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/RulesServiceEndPoint.java
index a51b0e8..8559ed4 100644
--- a/rest/src/main/java/org/apache/unomi/rest/RulesServiceEndPoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/RulesServiceEndPoint.java
@@ -23,6 +23,8 @@ import org.apache.unomi.api.PartialList;
 import org.apache.unomi.api.query.Query;
 import org.apache.unomi.api.rules.Rule;
 import org.apache.unomi.api.services.RulesService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.jws.WebMethod;
 import javax.jws.WebService;
@@ -42,10 +44,12 @@ import java.util.Set;
 )
 public class RulesServiceEndPoint {
 
+    private static final Logger logger = LoggerFactory.getLogger(RulesServiceEndPoint.class.getName());
+
     private RulesService rulesService;
 
     public RulesServiceEndPoint() {
-        System.out.println("Initializing rule service endpoint...");
+        logger.info("Initializing rule service endpoint...");
     }
 
     @WebMethod(exclude=true)

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/rest/src/main/java/org/apache/unomi/rest/ScoringServiceEndPoint.java
----------------------------------------------------------------------
diff --git a/rest/src/main/java/org/apache/unomi/rest/ScoringServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/ScoringServiceEndPoint.java
index e8307bd..bc60f9d 100644
--- a/rest/src/main/java/org/apache/unomi/rest/ScoringServiceEndPoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/ScoringServiceEndPoint.java
@@ -25,6 +25,8 @@ import org.apache.unomi.api.query.Query;
 import org.apache.unomi.api.segments.DependentMetadata;
 import org.apache.unomi.api.segments.Scoring;
 import org.apache.unomi.api.services.SegmentService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.jws.WebMethod;
 import javax.jws.WebService;
@@ -44,10 +46,12 @@ import java.util.List;
 )
 public class ScoringServiceEndPoint {
 
+    private static final Logger logger = LoggerFactory.getLogger(ScoringServiceEndPoint.class.getName());
+
     private SegmentService segmentService;
 
     public ScoringServiceEndPoint() {
-        System.out.println("Initializing scoring service endpoint...");
+        logger.info("Initializing scoring service endpoint...");
     }
 
     @WebMethod(exclude = true)

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/rest/src/main/java/org/apache/unomi/rest/SegmentServiceEndPoint.java
----------------------------------------------------------------------
diff --git a/rest/src/main/java/org/apache/unomi/rest/SegmentServiceEndPoint.java b/rest/src/main/java/org/apache/unomi/rest/SegmentServiceEndPoint.java
index 7c1e573..169a946 100644
--- a/rest/src/main/java/org/apache/unomi/rest/SegmentServiceEndPoint.java
+++ b/rest/src/main/java/org/apache/unomi/rest/SegmentServiceEndPoint.java
@@ -25,6 +25,8 @@ import org.apache.unomi.api.query.Query;
 import org.apache.unomi.api.segments.DependentMetadata;
 import org.apache.unomi.api.segments.Segment;
 import org.apache.unomi.api.services.SegmentService;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.jws.WebMethod;
 import javax.jws.WebService;
@@ -44,10 +46,12 @@ import java.util.List;
 )
 public class SegmentServiceEndPoint {
 
+    private static final Logger logger = LoggerFactory.getLogger(SegmentServiceEndPoint.class.getName());
+
     private SegmentService segmentService;
 
     public SegmentServiceEndPoint() {
-        System.out.println("Initializing segment service endpoint...");
+        logger.info("Initializing segment service endpoint...");
     }
 
     @WebMethod(exclude=true)

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/services/src/main/java/org/apache/unomi/services/services/ClusterServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/src/main/java/org/apache/unomi/services/services/ClusterServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/ClusterServiceImpl.java
index a002b55..50de1b5 100644
--- a/services/src/main/java/org/apache/unomi/services/services/ClusterServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/services/ClusterServiceImpl.java
@@ -127,19 +127,18 @@ public class ClusterServiceImpl implements ClusterService {
     }
 
     public void init() {
-        logger.debug("init cluster service");
         if (karafCellarEventProducer != null && karafCellarClusterManager != null) {
 
-            address = System.getProperty(CONTEXTSERVER_ADDRESS, address);
-            port = System.getProperty(CONTEXTSERVER_PORT, port);
-            secureAddress = System.getProperty(CONTEXTSERVER_SECURE_ADDRESS, secureAddress);
-            securePort = System.getProperty(CONTEXTSERVER_SECURE_PORT, securePort);
-
             boolean setupConfigOk = true;
             Group group = karafCellarGroupManager.findGroupByName(karafCellarGroupName);
             if (setupConfigOk && group == null) {
-                logger.error("Cluster group " + karafCellarGroupName + " doesn't exist");
-                setupConfigOk = false;
+                logger.error("Cluster group " + karafCellarGroupName + " doesn't exist, creating it...");
+                group = karafCellarGroupManager.createGroup(karafCellarGroupName);
+                if (group != null) {
+                    setupConfigOk = true;
+                } else {
+                    setupConfigOk = false;
+                }
             }
 
             // check if the producer is ON
@@ -177,6 +176,7 @@ public class ClusterServiceImpl implements ClusterService {
                 karafCellarEventProducer.produce(clusterConfigurationEvent);
             }
         }
+        logger.info("Cluster service initialized.");
     }
 
     public void destroy() {
@@ -189,6 +189,7 @@ public class ClusterServiceImpl implements ClusterService {
                 logger.error("Error closing JMX connector for url {}", url, e);
             }
         }
+        logger.info("Cluster service shutdown.");
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/services/src/main/java/org/apache/unomi/services/services/DefinitionsServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/src/main/java/org/apache/unomi/services/services/DefinitionsServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/DefinitionsServiceImpl.java
index b1a38a2..0562a5e 100644
--- a/services/src/main/java/org/apache/unomi/services/services/DefinitionsServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/services/DefinitionsServiceImpl.java
@@ -55,7 +55,7 @@ public class DefinitionsServiceImpl implements DefinitionsService, SynchronousBu
 
     private BundleContext bundleContext;
     public DefinitionsServiceImpl() {
-        logger.info("Instantiating definitions service...");
+
     }
 
     public void setBundleContext(BundleContext bundleContext) {
@@ -79,6 +79,7 @@ public class DefinitionsServiceImpl implements DefinitionsService, SynchronousBu
         }
 
         bundleContext.addBundleListener(this);
+        logger.info("Definitions service initialized.");
     }
 
     private void processBundleStartup(BundleContext bundleContext) {
@@ -118,6 +119,7 @@ public class DefinitionsServiceImpl implements DefinitionsService, SynchronousBu
 
     public void preDestroy() {
         bundleContext.removeBundleListener(this);
+        logger.info("Definitions service shutdown.");
     }
 
     private void loadPredefinedTags(BundleContext bundleContext) {

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/services/src/main/java/org/apache/unomi/services/services/EventServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/src/main/java/org/apache/unomi/services/services/EventServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/EventServiceImpl.java
index 2a39eb1..77464db 100644
--- a/services/src/main/java/org/apache/unomi/services/services/EventServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/services/EventServiceImpl.java
@@ -55,6 +55,14 @@ public class EventServiceImpl implements EventService {
 
     private Map<String, ThirdPartyServer> thirdPartyServers = new HashMap<>();
 
+    public void init() {
+        logger.info("Event service initialized.");
+    }
+
+    public void destroy() {
+        logger.info("Event service shutdown.");
+    }
+
     public void setThirdPartyConfiguration(Map<String,String> thirdPartyConfiguration) {
         this.thirdPartyServers = new HashMap<>();
         for (Map.Entry<String, String> entry : thirdPartyConfiguration.entrySet()) {

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/services/src/main/java/org/apache/unomi/services/services/GoalsServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/src/main/java/org/apache/unomi/services/services/GoalsServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/GoalsServiceImpl.java
index a5af23f..ac6a9d2 100644
--- a/services/src/main/java/org/apache/unomi/services/services/GoalsServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/services/GoalsServiceImpl.java
@@ -23,7 +23,6 @@ import org.apache.unomi.api.campaigns.Campaign;
 import org.apache.unomi.api.campaigns.CampaignDetail;
 import org.apache.unomi.api.campaigns.events.CampaignEvent;
 import org.apache.unomi.api.conditions.Condition;
-import org.apache.unomi.api.conditions.ConditionType;
 import org.apache.unomi.api.goals.Goal;
 import org.apache.unomi.api.goals.GoalReport;
 import org.apache.unomi.api.query.AggregateQuery;
@@ -88,10 +87,12 @@ public class GoalsServiceImpl implements GoalsService, SynchronousBundleListener
             }
         }
         bundleContext.addBundleListener(this);
+        logger.info("Goal service initialized.");
     }
 
     public void preDestroy() {
         bundleContext.removeBundleListener(this);
+        logger.info("Goal service shutdown.");
     }
 
     private void processBundleStartup(BundleContext bundleContext) {

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java
index e68eb9a..efe1d86 100644
--- a/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/services/ProfileServiceImpl.java
@@ -98,12 +98,14 @@ public class ProfileServiceImpl implements ProfileService, SynchronousBundleList
         bundleContext.addBundleListener(this);
         initializePurge();
         schedulePropertyTypeLoad();
+        logger.info("Profile service initialized.");
     }
 
     public void preDestroy() {
         bundleContext.removeBundleListener(this);
         cancelPurge();
         cancelPropertyTypeLoad();
+        logger.info("Profile service shutdown.");
     }
 
     private void processBundleStartup(BundleContext bundleContext) {

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/services/src/main/java/org/apache/unomi/services/services/QueryServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/src/main/java/org/apache/unomi/services/services/QueryServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/QueryServiceImpl.java
index 33e4f47..bb9de1d 100644
--- a/services/src/main/java/org/apache/unomi/services/services/QueryServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/services/QueryServiceImpl.java
@@ -44,9 +44,11 @@ public class QueryServiceImpl implements QueryService {
     }
 
     public void postConstruct() {
+        logger.info("Query service initialized.");
     }
 
     public void preDestroy() {
+        logger.info("Query service shutdown.");
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/services/src/main/java/org/apache/unomi/services/services/RulesServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/src/main/java/org/apache/unomi/services/services/RulesServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/RulesServiceImpl.java
index e4deeb1..2df2fff 100644
--- a/services/src/main/java/org/apache/unomi/services/services/RulesServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/services/RulesServiceImpl.java
@@ -103,11 +103,13 @@ public class RulesServiceImpl implements RulesService, EventListenerService, Syn
         bundleContext.addBundleListener(this);
 
         initializeTimer();
+        logger.info("Rule service initialized.");
     }
 
     public void preDestroy() {
         bundleContext.removeBundleListener(this);
         cancelTimers();
+        logger.info("Rule service shutdown.");
     }
 
     private void cancelTimers() {

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/services/src/main/java/org/apache/unomi/services/services/SegmentServiceImpl.java
----------------------------------------------------------------------
diff --git a/services/src/main/java/org/apache/unomi/services/services/SegmentServiceImpl.java b/services/src/main/java/org/apache/unomi/services/services/SegmentServiceImpl.java
index 08f2f25..770936d 100644
--- a/services/src/main/java/org/apache/unomi/services/services/SegmentServiceImpl.java
+++ b/services/src/main/java/org/apache/unomi/services/services/SegmentServiceImpl.java
@@ -137,11 +137,13 @@ public class SegmentServiceImpl implements SegmentService, SynchronousBundleList
         }
         bundleContext.addBundleListener(this);
         initializeTimer();
+        logger.info("Segment service initialized.");
     }
 
     public void preDestroy() {
         bundleContext.removeBundleListener(this);
         cancelTimers();
+        logger.info("Segment service shutdown.");
     }
 
     private void cancelTimers() {

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
----------------------------------------------------------------------
diff --git a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
index cb334ab..23af746 100644
--- a/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
+++ b/services/src/main/resources/OSGI-INF/blueprint/blueprint.xml
@@ -40,12 +40,6 @@
             <cm:property name="jmxUsername" value="karaf" />
             <cm:property name="jmxPassword" value="karaf" />
             <cm:property name="jmxPort" value="1099" />
-        </cm:default-properties>
-    </cm:property-placeholder>
-
-    <cm:property-placeholder persistent-id="org.apache.unomi.web"
-                             update-strategy="reload" placeholder-prefix="${web.">
-        <cm:default-properties>
             <cm:property name="contextserver.address" value="localhost"/>
             <cm:property name="contextserver.port" value="8181"/>
             <cm:property name="contextserver.secureAddress" value="localhost"/>
@@ -53,7 +47,6 @@
         </cm:default-properties>
     </cm:property-placeholder>
 
-
     <reference id="persistenceService"
                interface="org.apache.unomi.persistence.spi.PersistenceService"/>
     <reference id="httpService" interface="org.osgi.service.http.HttpService"/>
@@ -71,7 +64,8 @@
     </bean>
     <service id="definitionsService" ref="definitionsServiceImpl" auto-export="interfaces"/>
 
-    <bean id="eventServiceImpl" class="org.apache.unomi.services.services.EventServiceImpl">
+    <bean id="eventServiceImpl" class="org.apache.unomi.services.services.EventServiceImpl"
+        init-method="init" destroy-method="destroy">
         <property name="persistenceService" ref="persistenceService"/>
         <property name="definitionsService" ref="definitionsServiceImpl"/>
         <property name="bundleContext" ref="blueprintBundleContext"/>
@@ -156,10 +150,10 @@
 
     <bean id="clusterServiceImpl" class="org.apache.unomi.services.services.ClusterServiceImpl"
           init-method="init" destroy-method="destroy">
-        <property name="address" value="${web.contextserver.address}"/>
-        <property name="port" value="${web.contextserver.port}"/>
-        <property name="secureAddress" value="${web.contextserver.secureAddress}"/>
-        <property name="securePort" value="${web.contextserver.securePort}"/>
+        <property name="address" value="${cluster.contextserver.address}"/>
+        <property name="port" value="${cluster.contextserver.port}"/>
+        <property name="secureAddress" value="${cluster.contextserver.secureAddress}"/>
+        <property name="securePort" value="${cluster.contextserver.securePort}"/>
         <property name="persistenceService" ref="persistenceService"/>
         <property name="karafCellarClusterManager" ref="karafCellarClusterManager" />
         <property name="karafCellarEventProducer" ref="karafCellarEventProducer" />

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/services/src/main/resources/org.apache.unomi.cluster.cfg
----------------------------------------------------------------------
diff --git a/services/src/main/resources/org.apache.unomi.cluster.cfg b/services/src/main/resources/org.apache.unomi.cluster.cfg
index a9ecf2e..565653a 100644
--- a/services/src/main/resources/org.apache.unomi.cluster.cfg
+++ b/services/src/main/resources/org.apache.unomi.cluster.cfg
@@ -17,4 +17,8 @@
 cluster.group=default
 cluster.jmxUsername=karaf
 cluster.jmxPassword=karaf
-cluster.jmxPort=1099
\ No newline at end of file
+cluster.jmxPort=1099
+contextserver.address=localhost
+contextserver.port=8181
+contextserver.secureAddress=localhost
+contextserver.securePort=9443

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/src/site/markdown/building-and-deploying.md
----------------------------------------------------------------------
diff --git a/src/site/markdown/building-and-deploying.md b/src/site/markdown/building-and-deploying.md
index 68e7668..f4fbfb8 100644
--- a/src/site/markdown/building-and-deploying.md
+++ b/src/site/markdown/building-and-deploying.md
@@ -105,7 +105,7 @@ files (at the end of the file):
        export JAVA_MAX_PERM_MEM=384M
     ```
     
-2. Install the WAR support, CXF and CDI (OpenWebBeans) into Karaf by doing the following in the Karaf command line:
+2. Install the WAR support, CXF and Karaf Cellar into Karaf by doing the following in the Karaf command line:
 
     ```
        feature:repo-add cxf 3.0.2

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/src/site/markdown/configuration.md
----------------------------------------------------------------------
diff --git a/src/site/markdown/configuration.md b/src/site/markdown/configuration.md
index db3473d..df8afb7 100644
--- a/src/site/markdown/configuration.md
+++ b/src/site/markdown/configuration.md
@@ -23,25 +23,29 @@ Changing the default configuration
 
 If you want to change the default configuration, you can perform any modification you want in the $MY_KARAF_HOME/etc directory.
 
-The context server configuration is kept in the $MY_KARAF_HOME/etc/org.apache.unomi.web.cfg . It defines the
+The context server configuration is kept in the $MY_KARAF_HOME/etc/org.apache.unomi.cluster.cfg . It defines the
 addresses and port where it can be found :
 
     contextserver.address=localhost
     contextserver.port=8181
     contextserver.secureAddress=localhost
     contextserver.securePort=9443
-    contextserver.domain=apache.org
 
-If you need to specify an Elasticsearch cluster name that is 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.
+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.
 
-To change the cluster name, first create a file called 
+To change these settings, first create a file called 
 
     $MY_KARAF_HOME/etc/org.apache.unomi.persistence.elasticsearch.cfg
 
 with the following contents:
 
     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
     
 Secured events configuration
@@ -197,12 +201,15 @@ Integrating with an Apache HTTP web server
 If you want to setup an Apache HTTP web server in from of Apache Unomi, here is an example configuration using 
 mod_proxy.
 
-In your Unomi package directory, in /etc/org.apache.unomi.web.cfg for unomi.apache.org
+In your Unomi package directory, in /etc/org.apache.unomi.cluster.cfg for unomi.apache.org
    
    contextserver.address=unomi.apache.org
    contextserver.port=80
    contextserver.secureAddress=unomi.apache.org
    contextserver.securePort=443
+   
+and you will also need to change the contextserver.domain in the /etc/org.apache.unomi.web.cfg file
+
    contextserver.domain=apache.org
 
 Main virtual host config:

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/wab/pom.xml
----------------------------------------------------------------------
diff --git a/wab/pom.xml b/wab/pom.xml
index 5af699f..9e70cc2 100644
--- a/wab/pom.xml
+++ b/wab/pom.xml
@@ -53,24 +53,6 @@
         </dependency>
 
         <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-jcdi_1.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-atinject_1.0_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
-            <groupId>org.apache.geronimo.specs</groupId>
-            <artifactId>geronimo-annotation_1.1_spec</artifactId>
-            <scope>provided</scope>
-        </dependency>
-
-        <dependency>
           <groupId>com.fasterxml.jackson.core</groupId>
           <artifactId>jackson-databind</artifactId>
           <scope>provided</scope>
@@ -118,10 +100,6 @@
                             *
                         </Import-Package>
                         <Web-ContextPath>/</Web-ContextPath>
-                        <Require-Capability>
-                            org.ops4j.pax.cdi.extension; filter:="(extension=pax-cdi-extension)",
-                            osgi.extender; filter:="(osgi.extender=pax.cdi)"
-                        </Require-Capability>
                     </instructions>
                 </configuration>
             </plugin>

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/wab/src/main/java/org/apache/unomi/web/ContextServlet.java
----------------------------------------------------------------------
diff --git a/wab/src/main/java/org/apache/unomi/web/ContextServlet.java b/wab/src/main/java/org/apache/unomi/web/ContextServlet.java
index 2d536d9..c1c096c 100644
--- a/wab/src/main/java/org/apache/unomi/web/ContextServlet.java
+++ b/wab/src/main/java/org/apache/unomi/web/ContextServlet.java
@@ -30,6 +30,7 @@ import org.apache.unomi.persistence.spi.CustomObjectMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
@@ -59,6 +60,11 @@ public class ContextServlet extends HttpServlet {
     private String profileIdCookieName = "context-profile-id";
     private String profileIdCookieDomain;
 
+    @Override
+    public void init(ServletConfig config) throws ServletException {
+        super.init(config);
+        logger.info("ContextServlet initialized.");
+    }
 
     @Override
     public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException {
@@ -396,6 +402,7 @@ public class ContextServlet extends HttpServlet {
 
 
     public void destroy() {
+        logger.info("Context servlet shutdown.");
     }
 
     public void setProfileService(ProfileService profileService) {

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java
----------------------------------------------------------------------
diff --git a/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java b/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java
index 2b97f56..f8a9119 100644
--- a/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java
+++ b/wab/src/main/java/org/apache/unomi/web/EventsCollectorServlet.java
@@ -27,6 +27,7 @@ import org.apache.unomi.persistence.spi.CustomObjectMapper;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import javax.servlet.ServletConfig;
 import javax.servlet.ServletException;
 import javax.servlet.http.Cookie;
 import javax.servlet.http.HttpServlet;
@@ -47,6 +48,18 @@ public class EventsCollectorServlet extends HttpServlet {
     private PrivacyService privacyService;
 
     @Override
+    public void init(ServletConfig config) throws ServletException {
+        super.init(config);
+        logger.info("Event collector servlet initialized.");
+    }
+
+    @Override
+    public void destroy() {
+        super.destroy();
+        logger.info("Event collector servlet shutdown.");
+    }
+
+    @Override
     protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
 
         doEvent(req, resp);

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/wab/src/main/resources/org.apache.unomi.web.cfg
----------------------------------------------------------------------
diff --git a/wab/src/main/resources/org.apache.unomi.web.cfg b/wab/src/main/resources/org.apache.unomi.web.cfg
index e0a2889..6556597 100644
--- a/wab/src/main/resources/org.apache.unomi.web.cfg
+++ b/wab/src/main/resources/org.apache.unomi.web.cfg
@@ -15,7 +15,6 @@
 # limitations under the License.
 #
 
-contextserver.address=localhost
-contextserver.port=8181
-contextserver.secureAddress=localhost
-contextserver.securePort=9443
+# configure here the domain to use the for cookies setup by the Apache Unomi context servlet
+# by default the current request will be used to set the domain.
+# contextserver.domain=
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-unomi/blob/a4a0bdfe/wab/src/main/webapp/WEB-INF/beans.xml
----------------------------------------------------------------------
diff --git a/wab/src/main/webapp/WEB-INF/beans.xml b/wab/src/main/webapp/WEB-INF/beans.xml
deleted file mode 100644
index e69de29..0000000