Repository: EnMasseProject/enmasse
Pull request #3005 (2019-07-15 21:31:45)

Docs: issue-3002: Uninstall using Ansible 
and related install and uninstall doc fixes


Patch:
diff --git a/.jenkins/Jenkinsfile-pr b/.jenkins/Jenkinsfile-pr
index 985def409..e0fb630ca 100644
--- a/.jenkins/Jenkinsfile-pr
+++ b/.jenkins/Jenkinsfile-pr
@@ -83,9 +83,7 @@ pipeline {
         }
         stage('build') {
             when {
-                expression {
-                    env.TEST_ONLY == false
-                }
+                environment name: 'TEST_ONLY', value: 'false'
             }
             steps {
                 script {
@@ -96,9 +94,7 @@ pipeline {
         }
         stage('push docker images') {
             when {
-                expression {
-                    env.TEST_ONLY == false
-                }
+                environment name: 'TEST_ONLY', value: 'false'
             }
             steps {
                 sh 'oc login -u test -p test --server localhost:8443 --insecure-skip-tls-verify'
diff --git a/address-space-controller/pom.xml b/address-space-controller/pom.xml
index 728a575e2..706b4d360 100644
--- a/address-space-controller/pom.xml
+++ b/address-space-controller/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>address-space-controller</artifactId>
diff --git a/agent/pom.xml b/agent/pom.xml
index 47f1bef2c..bd682f92e 100644
--- a/agent/pom.xml
+++ b/agent/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.enmasse</groupId>
diff --git a/amqp-utils/pom.xml b/amqp-utils/pom.xml
index 3f1beba74..629053708 100644
--- a/amqp-utils/pom.xml
+++ b/amqp-utils/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>amqp-utils</artifactId>
diff --git a/api-common/pom.xml b/api-common/pom.xml
index 1ac0cb2f2..73da4e201 100644
--- a/api-common/pom.xml
+++ b/api-common/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>api-common</artifactId>
diff --git a/api-model/pom.xml b/api-model/pom.xml
index 1681d7626..aa485f2d5 100644
--- a/api-model/pom.xml
+++ b/api-model/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>api-model</artifactId>
diff --git a/api-server/pom.xml b/api-server/pom.xml
index f2e1e3b9c..76f05b204 100644
--- a/api-server/pom.xml
+++ b/api-server/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>api-server</artifactId>
diff --git a/broker-plugin/amqp-connector/pom.xml b/broker-plugin/amqp-connector/pom.xml
index 55b641cfb..d71cedd52 100644
--- a/broker-plugin/amqp-connector/pom.xml
+++ b/broker-plugin/amqp-connector/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>broker-plugin</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>amqp-connector</artifactId>
diff --git a/broker-plugin/jmx_exporter/pom.xml b/broker-plugin/jmx_exporter/pom.xml
index 28c1c5390..b21e59466 100644
--- a/broker-plugin/jmx_exporter/pom.xml
+++ b/broker-plugin/jmx_exporter/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>broker-plugin</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>jmx_exporter</artifactId>
diff --git a/broker-plugin/plugin/pom.xml b/broker-plugin/plugin/pom.xml
index 9c30ee00d..630897ac1 100644
--- a/broker-plugin/plugin/pom.xml
+++ b/broker-plugin/plugin/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>broker-plugin</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <packaging>pom</packaging>
   <modelVersion>4.0.0</modelVersion>
diff --git a/broker-plugin/pom.xml b/broker-plugin/pom.xml
index 06a597be0..967d9cf7f 100644
--- a/broker-plugin/pom.xml
+++ b/broker-plugin/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <packaging>pom</packaging>
   <modelVersion>4.0.0</modelVersion>
diff --git a/broker-plugin/sasl-delegation/pom.xml b/broker-plugin/sasl-delegation/pom.xml
index 2b875f57c..e148d6e24 100644
--- a/broker-plugin/sasl-delegation/pom.xml
+++ b/broker-plugin/sasl-delegation/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>broker-plugin</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>sasl-delegation</artifactId>
diff --git a/broker-plugin/tcnative/pom.xml b/broker-plugin/tcnative/pom.xml
index 3c6aed1a8..b1cff3f60 100644
--- a/broker-plugin/tcnative/pom.xml
+++ b/broker-plugin/tcnative/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>broker-plugin</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>tcnative</artifactId>
diff --git a/bundle/pom.xml b/bundle/pom.xml
index 4010c9b81..5e9dae7b5 100644
--- a/bundle/pom.xml
+++ b/bundle/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <artifactId>enmasse</artifactId>
         <groupId>io.enmasse</groupId>
-        <version>0.29-SNAPSHOT</version>
+        <version>0.30-SNAPSHOT</version>
     </parent>
     <packaging>pom</packaging>
     <name>EnMasse Bundles</name>
diff --git a/console/console-httpd/pom.xml b/console/console-httpd/pom.xml
index 03e486b7f..5aea0d56e 100644
--- a/console/console-httpd/pom.xml
+++ b/console/console-httpd/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>console</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.enmasse</groupId>
diff --git a/console/console-init/pom.xml b/console/console-init/pom.xml
index 9e29f05bd..1ff09c928 100644
--- a/console/console-init/pom.xml
+++ b/console/console-init/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>console</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.enmasse</groupId>
diff --git a/console/pom.xml b/console/pom.xml
index caec457d5..3d7da2a59 100644
--- a/console/pom.xml
+++ b/console/pom.xml
@@ -5,7 +5,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.enmasse</groupId>
diff --git a/controller-manager/pom.xml b/controller-manager/pom.xml
index 1fcfd2cc2..a4e0144f8 100644
--- a/controller-manager/pom.xml
+++ b/controller-manager/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <packaging>pom</packaging>
   <modelVersion>4.0.0</modelVersion>
diff --git a/discovery-lib/pom.xml b/discovery-lib/pom.xml
index 3fda8e650..f474f71aa 100644
--- a/discovery-lib/pom.xml
+++ b/discovery-lib/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>discovery-lib</artifactId>
diff --git a/documentation/assemblies/assembly-installing.adoc b/documentation/assemblies/assembly-installing.adoc
index a1e379b8d..c4cbdede6 100644
--- a/documentation/assemblies/assembly-installing.adoc
+++ b/documentation/assemblies/assembly-installing.adoc
@@ -1,6 +1,7 @@
 // This assembly is included in the following assemblies:
 //
 // assembly-service-admin-guide.adoc
+
 [id='installing-{context}']
 = Installing {ProductName}
 
@@ -28,12 +29,12 @@ endif::[]
 ifeval::["{cmdcli}" == "oc"]
 
 ifdef::OperatorSource[]
-{ProductName} can be installed by applying the YAML files using the `oc` command-line tool, by using
-the Operator Marketplace, or by running the link:https://www.ansible.com/[Ansible^] playbooks.
+{ProductName} can be installed by applying the YAML files using the OpenShift Container Platform command-line interface, by using
+the Operator Marketplace, or by running the link:https://www.ansible.com/[Ansible^] playbook.
 endif::OperatorSource[]
 
 ifndef::OperatorSource[]
-{ProductName} can be installed by applying the YAML files using the `oc` command-line tool, or by running the link:https://www.ansible.com/[Ansible^] playbooks.
+{ProductName} can be installed by applying the YAML files using the OpenShift Container Platform command-line interface, or by running the link:https://www.ansible.com/[Ansible^] playbook.
 endif::OperatorSource[]
 
 include::../common/snip-prerequisites-openshift.adoc[]
diff --git a/documentation/assemblies/assembly-service-admin-guide.adoc b/documentation/assemblies/assembly-service-admin-guide.adoc
index dae3eda48..d7786256a 100644
--- a/documentation/assemblies/assembly-service-admin-guide.adoc
+++ b/documentation/assemblies/assembly-service-admin-guide.adoc
@@ -15,7 +15,7 @@ include::assembly-configuring.adoc[leveloffset=+1]
 
 include::assembly-upgrading.adoc[leveloffset=+1]
 
-include::../modules/proc-uninstalling.adoc[leveloffset=+1]
+include::assembly-uninstalling.adoc[leveloffset=+1]
 
 include::assembly-monitoring.adoc[leveloffset=+1]
 
diff --git a/documentation/assemblies/assembly-uninstalling.adoc b/documentation/assemblies/assembly-uninstalling.adoc
new file mode 100644
index 000000000..b3cb0d9d9
--- /dev/null
+++ b/documentation/assemblies/assembly-uninstalling.adoc
@@ -0,0 +1,15 @@
+// This assembly is included in the following assemblies:
+//
+// assembly-service-admin-guide.adoc
+// Installing master.adoc
+
+[id='assembly-uninstalling-{context}']
+= Uninstalling {ProductName}
+
+You must uninstall {ProductName} using the same method that you used to install {ProductName}.
+
+include::../modules/proc-uninstalling.adoc[leveloffset=+1]
+
+include::../modules/proc-uninstalling-using-ansible.adoc[leveloffset=+1]
+
+
diff --git a/documentation/modules/proc-installing-using-ansible.adoc b/documentation/modules/proc-installing-using-ansible.adoc
index 605c305ef..7cc9c664a 100644
--- a/documentation/modules/proc-installing-using-ansible.adoc
+++ b/documentation/modules/proc-installing-using-ansible.adoc
@@ -1,6 +1,6 @@
 // Module included in the following assemblies:
 //
-// assembly-installing-openshift.adoc
+// assembly-installing.adoc
 
 [id='installing-using-ansible-{context}']
 = Installing {ProductName} using Ansible
@@ -8,7 +8,7 @@
 Installing {ProductName} using Ansible requires creating an inventory file with the variables for
 configuring the system. Example inventory files can be found in the `ansible/inventory` folder.
 
-An example inventory file that enables a minimal installation of {ProductName}:
+The following example inventory file enables a minimal installation of {ProductName}:
 
 [source,options="nowrap"]
 ----
@@ -18,27 +18,27 @@ include::../service_admin/example.inventory[]
 The following Ansible configuration settings are supported:
 
 .Ansible configuration settings
-[cols="25%a,25%a,25%a,25%a",options="header"]
+[cols="35%a,40%a,15%a,10%a",options="header"]
 |===
 |Name |Description |Default value | Required
-|namespace|Specifies the namespace where {ProductName} is installed.|Not applicable |yes
-|enable_rbac|Specifies whether to enable RBAC authentication of REST APIs|True |no
-|service_catalog|Specifies whether to enable integration with the Service Catalog|False |no
+|namespace|Specifies the project where {ProductName} is installed. |Not applicable |yes
+|enable_rbac|Specifies whether to enable RBAC authentication of REST APIs |True |no
+|service_catalog|Specifies whether to enable integration with the Service Catalog |False |no
 |authentication_services|Specifies the list of authentication services to deploy. Supported values are `none` and `standard`. |`none` |no
 |keycloak_admin_password|Specifies the admin password to use for the `standard` authentication service {AuthProductName} instance |Not applicable |yes (if `standard` authentication service is enabled)
-|api_server|Specifies whether to enable the REST API server|True |no
-|register_api_server|Specifies whether to register the API server with {KubePlatform} master|False |no
-|secure_api_server|Specifies whether to enable mutual TLS for the API server|False |no
-|install_example_plans|Specifies whether to install example plans and infrastructure configurations|True|no
-|monitoring_namespace|Specifies the namespace where the {ProductName} monitoring is installed.|Not applicable |yes
-|monitoring_operator|Specifies whether to install the monitoring infrastructure|Not applicable|no
-|monitoring|Specifies whether to install the service monitors, Prometheus rules, and Grafana dashboards for monitoring {ProductName}|Not applicable|no
+|api_server|Specifies whether to enable the REST API server |True |no
+|register_api_server|Specifies whether to register the API server with {KubePlatform} master |False |no
+|secure_api_server|Specifies whether to enable mutual TLS for the API server |False |no
+|install_example_plans|Specifies whether to install example plans and infrastructure configurations |True |no
+|monitoring_namespace|Specifies the project where {ProductName} monitoring is installed. |Not applicable |yes
+|monitoring_operator|Specifies whether to install the monitoring infrastructure |Not applicable |no
+|monitoring|Specifies whether to install the service monitors, Prometheus rules, and Grafana dashboards for monitoring {ProductName} |Not applicable |no
 |===
 
 
 .Procedure
 
-. (Optional) Create an inventory file.
+. Create an inventory file.
 
 . Run the Ansible playbook:
 +
diff --git a/documentation/modules/proc-installing-using-bundle.adoc b/documentation/modules/proc-installing-using-bundle.adoc
index 5ec00315d..7544de976 100644
--- a/documentation/modules/proc-installing-using-bundle.adoc
+++ b/documentation/modules/proc-installing-using-bundle.adoc
@@ -19,11 +19,11 @@ ifeval::["{cmdcli}" == "oc"]
 {cmdcli} login -u system:admin
 ----
 
-. (Optional) If you want to deploy to a namespace other than `{ProductNamespace}` you must run the following command and substitute `{ProductNamespace}` in subsequent steps:
+. (Optional) If you want to deploy to a project other than `{ProductNamespace}` you must run the following command and substitute `{ProductNamespace}` in subsequent steps:
 +
 [options="nowrap",subs="+quotes,attributes"]
 ----
-sed -i 's/{ProductNamespace}/_my-namespace_/' install/bundles/{ProductBundleName}/*.yaml
+sed -i 's/{ProductNamespace}/_my-project_/' install/bundles/{ProductBundleName}/*.yaml
 ----
 
 . Create the project where you want to deploy {ProductName}:
diff --git a/documentation/modules/proc-uninstalling-using-ansible.adoc b/documentation/modules/proc-uninstalling-using-ansible.adoc
new file mode 100644
index 000000000..215e4ea16
--- /dev/null
+++ b/documentation/modules/proc-uninstalling-using-ansible.adoc
@@ -0,0 +1,21 @@
+// Module included in the following assemblies:
+//
+// assembly-uninstalling.adoc
+
+[id='proc-uninstalling-using-ansible-{context}']
+= Uninstalling {ProductName} using Ansible
+
+Uninstalling {ProductName} using Ansible requires using the same inventory file that was used for installing {ProductName}. 
+
+NOTE: The playbook deletes the `{ProductNamespace}` project.
+
+.Procedure
+
+. Run the Ansible playbook, where `_inventory-file_` specifies the inventory file used at installation:
++
+[options="nowrap",subs="+quotes,attributes"]
+----
+ansible-playbook -i _inventory-file_ ansible/playbooks/openshift/uninstall.yml
+----
+
+
diff --git a/documentation/modules/proc-uninstalling.adoc b/documentation/modules/proc-uninstalling.adoc
index e52fac220..df2e5c8c7 100644
--- a/documentation/modules/proc-uninstalling.adoc
+++ b/documentation/modules/proc-uninstalling.adoc
@@ -6,6 +6,8 @@
 [id='uninstalling-{context}']
 = Uninstalling {ProductName}
 
+This method uninstalls {ProductName} that was installed using the YAML bundle.
+
 .Procedure 
 
 ifeval::["{cmdcli}" == "oc"]
@@ -18,7 +20,7 @@ ifeval::["{cmdcli}" == "oc"]
 endif::[]
 
 ifeval::["{cmdcli}" == "oc"]
-. Delete "cluster level" resources:
+. Delete the cluster-level resources:
 +
 [options="nowrap",subs="attributes"]
 ----
@@ -38,7 +40,7 @@ ifeval::["{cmdcli}" == "oc"]
 endif::[]
 
 ifeval::["{cmdcli}" == "kubectl"]
-. Delete "cluster level" resources:
+. Delete the cluster-level resources:
 +
 [options="nowrap",subs="attributes"]
 ----
diff --git a/iot/iot-application-base/pom.xml b/iot/iot-application-base/pom.xml
index fc66d337c..5f0277030 100644
--- a/iot/iot-application-base/pom.xml
+++ b/iot/iot-application-base/pom.xml
@@ -8,7 +8,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>iot</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
 
   <artifactId>iot-application-base</artifactId>
diff --git a/iot/iot-auth-service/pom.xml b/iot/iot-auth-service/pom.xml
index f05ff1ab0..531de748d 100644
--- a/iot/iot-auth-service/pom.xml
+++ b/iot/iot-auth-service/pom.xml
@@ -8,7 +8,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>iot-application-base</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
     <relativePath>../iot-application-base</relativePath>
   </parent>
 
diff --git a/iot/iot-device-registry-file/pom.xml b/iot/iot-device-registry-file/pom.xml
index da7dfc87a..0c0037415 100644
--- a/iot/iot-device-registry-file/pom.xml
+++ b/iot/iot-device-registry-file/pom.xml
@@ -8,7 +8,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>iot-application-base</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
     <relativePath>../iot-application-base</relativePath>
   </parent>
 
diff --git a/iot/iot-device-registry-infinispan/pom.xml b/iot/iot-device-registry-infinispan/pom.xml
index 1047d62b1..b218b0208 100644
--- a/iot/iot-device-registry-infinispan/pom.xml
+++ b/iot/iot-device-registry-infinispan/pom.xml
@@ -8,48 +8,15 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>iot-application-base</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
     <relativePath>../iot-application-base</relativePath>
   </parent>
 
   <artifactId>iot-device-registry-infinispan</artifactId>
 
-  <dependencyManagement>
-    <dependencies>
-      <!-- required to pull in a 2.x version of jackson -->
-      <dependency>
-        <groupId>org.apache.avro</groupId>
-        <artifactId>avro</artifactId>
-        <version>${avro.version}</version>
-      </dependency>
-      <!-- required due to CVE-2017-12629 -->
-      <dependency>
-        <groupId>org.apache.lucene</groupId>
-        <artifactId>lucene-core</artifactId>
-        <version>${lucene.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.lucene</groupId>
-        <artifactId>lucene-misc</artifactId>
-        <version>${lucene.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.lucene</groupId>
-        <artifactId>lucene-analyzers-common</artifactId>
-        <version>${lucene.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.lucene</groupId>
-        <artifactId>lucene-facet</artifactId>
-        <version>${lucene.version}</version>
-      </dependency>
-      <dependency>
-        <groupId>org.apache.lucene</groupId>
-        <artifactId>lucene-queryparser</artifactId>
-        <version>${lucene.version}</version>
-      </dependency>
-    </dependencies>
-  </dependencyManagement>
+  <properties>
+    <junit4.version>4.12</junit4.version>
+  </properties>
 
   <dependencies>
     <dependency>
@@ -62,16 +29,12 @@
     </dependency>
     <dependency>
       <groupId>org.infinispan</groupId>
-      <artifactId>infinispan-query</artifactId>
+      <artifactId>infinispan-core</artifactId>
     </dependency>
     <dependency>
       <groupId>org.infinispan</groupId>
       <artifactId>infinispan-client-hotrod</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.infinispan</groupId>
-      <artifactId>infinispan-remote-query-client</artifactId>
-    </dependency>
 
     <!-- Test dependencies -->
     <dependency>
@@ -97,6 +60,7 @@
     <dependency>
       <groupId>io.vertx</groupId>
       <artifactId>vertx-junit5</artifactId>
+      <scope>test</scope>
     </dependency>
     <dependency>
       <groupId>org.eclipse.hono</groupId>
@@ -105,10 +69,26 @@
       <type>test-jar</type>
       <scope>test</scope>
     </dependency>
+    <dependency>
+      <groupId>junit</groupId>
+      <artifactId>junit</artifactId>
+      <version>${junit4.version}</version>
+      <scope>test</scope>
+    </dependency>
     <dependency>
       <groupId>org.infinispan</groupId>
       <artifactId>infinispan-server-hotrod</artifactId>
       <scope>test</scope>
+      <exclusions>
+        <exclusion>
+          <groupId>org.apache.logging.log4j</groupId>
+          <artifactId>log4j-core</artifactId>
+        </exclusion>
+        <exclusion>
+          <groupId>org.apache.logging.log4j</groupId>
+          <artifactId>log4j-slf4j-impl</artifactId>
+        </exclusion>
+      </exclusions>
     </dependency>
     <dependency>
       <groupId>org.infinispan</groupId>
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheCredentialConfigProperties.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheCredentialConfigProperties.java
deleted file mode 100644
index e552af3c7..000000000
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheCredentialConfigProperties.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright 2019, EnMasse authors.
- * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
- */
-
-package io.enmasse.iot.registry.infinispan;
-
-/**
- * Configuration properties for Hono's Infinispan Credential service.
- *
- */
-public class CacheCredentialConfigProperties {
-}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheCredentialService.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheCredentialService.java
deleted file mode 100644
index 8b0175d9f..000000000
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheCredentialService.java
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- * Copyright 2019, EnMasse authors.
- * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
- */
-
-package io.enmasse.iot.registry.infinispan;
-
-import io.opentracing.Span;
-import io.vertx.core.AsyncResult;
-import io.vertx.core.Future;
-import io.vertx.core.Handler;
-import io.vertx.core.json.JsonArray;
-import io.vertx.core.json.JsonObject;
-import org.eclipse.hono.auth.HonoPasswordEncoder;
-import org.eclipse.hono.service.credentials.CompleteBaseCredentialsService;
-import org.eclipse.hono.util.CredentialsConstants;
-import org.eclipse.hono.util.CredentialsObject;
-import org.eclipse.hono.util.CredentialsResult;
-
-import org.infinispan.client.hotrod.Flag;
-import org.infinispan.client.hotrod.RemoteCache;
-import org.infinispan.client.hotrod.Search;
-import org.infinispan.query.dsl.Query;
-import org.infinispan.query.dsl.QueryFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Repository;
-
-import java.net.HttpURLConnection;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-/**
- * A credentials service that use an Infinispan as a backend service.
- * Infinispan is an open source project providing a distributed in-memory key/value data store
- *
- * <p>
- *@see <a href="https://infinspan.org">https://infinspan.org</a>
- *
- */
-@Repository
-@Primary
-public class CacheCredentialService extends CompleteBaseCredentialsService<CacheCredentialConfigProperties> {
-
-    private final RemoteCache<CredentialsKey, RegistryCredentialObject> credentialsCache;
-
-    /**
-     * Creates a new service instance for a password encoder.
-     *
-     * @param pwdEncoder The encoder to use for hashing clear text passwords.
-     * @throws NullPointerException if encoder is {@code null}.
-     */
-    @Autowired
-    protected CacheCredentialService(final RemoteCache<CredentialsKey,RegistryCredentialObject> cache, final HonoPasswordEncoder pwdEncoder) {
-        super(pwdEncoder);
-        this.credentialsCache = cache;
-    }
-
-    @Override
-    public void setConfig(final CacheCredentialConfigProperties configuration) {
-    }
-
-    @Override
-    public void add(final String tenantId, final JsonObject credentialsJson, final Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
-        final CredentialsObject credentials = Optional.ofNullable(credentialsJson)
-                .map(json -> json.mapTo(CredentialsObject.class)).orElse(null);
-
-        final CredentialsKey key = new CredentialsKey(tenantId, credentials.getAuthId(), credentials.getType());
-        final RegistryCredentialObject registryCredential = new RegistryCredentialObject(credentials, tenantId, credentialsJson);
-
-        credentialsCache.withFlags(Flag.FORCE_RETURN_VALUE).putIfAbsentAsync(key, registryCredential).thenAccept(result -> {
-            if (result == null) {
-                log.debug("Created credentials [tenant-id: {}, auth-id: {}, type: {}]", tenantId, credentials.getAuthId(), credentials.getType());
-                resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_CREATED)));
-            } else {
-                log.debug("Conflict, cannot create credentials [tenant-id: {}, auth-id: {}, type: {}]", tenantId, credentials.getAuthId(), credentials.getType());
-                resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_CONFLICT)));
-            }
-        });
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * The result object will include a <em>no-cache</em> directive.
-     */
-    @Override
-    public void get(final String tenantId, final String type, final String authId, final Span span,
-            final Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
-        get(tenantId, type, authId, null, span, resultHandler);
-    }
-
-    /**
-     * {@inheritDoc}
-     * <p>
-     * The result object will include a <em>no-cache</em> directive.
-     */
-    @Override
-    public void get(
-            final String tenantId,
-            final String type,
-            final String authId,
-            final JsonObject clientContext,
-            final Span span,
-            final Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
-
-        Objects.requireNonNull(tenantId);
-        Objects.requireNonNull(type);
-        Objects.requireNonNull(authId);
-        Objects.requireNonNull(resultHandler);
-
-        final CredentialsKey key = new CredentialsKey(tenantId, authId, type);
-
-        credentialsCache.getAsync(key).thenAccept(credential -> {
-            if (credential == null) {
-                log.debug("Credential not found [tenant-id: {}, auth-id: {}, type: {}]", tenantId, authId, type);
-                resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-            } else if (clientContext != null && !clientContext.isEmpty()) {
-                if (contextMatches(clientContext, new JsonObject(credential.getOriginalJson()))) {
-                    log.debug("Retrieve credential, context matches [tenant-id: {}, auth-id: {}, type: {}]", tenantId, authId, type);
-                    resultHandler.handle(Future.succeededFuture(
-                            CredentialsResult.from(HttpURLConnection.HTTP_OK,
-                                    new JsonObject(credential.getOriginalJson()))));
-                } else {
-                    log.debug("Context mismatch [tenant-id: {}, auth-id: {}, type: {}]", tenantId, authId, type);
-                    resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-                }
-            } else {
-                log.debug("Retrieve credential [tenant-id: {}, auth-id: {}, type: {}]", tenantId, authId, type);
-                resultHandler.handle(Future.succeededFuture(
-                        CredentialsResult.from(HttpURLConnection.HTTP_OK,
-                                new JsonObject(credential.getOriginalJson()))));
-            }
-        });
-    }
-
-    @Override
-    public void update(final String tenantId, final JsonObject otherKeys, final Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
-
-        final CredentialsObject credentials = Optional.ofNullable(otherKeys)
-                .map(json -> json.mapTo(CredentialsObject.class)).orElse(null);
-
-        final CredentialsKey key = new CredentialsKey(tenantId, credentials.getAuthId(), credentials.getType());
-        final RegistryCredentialObject registryCredential = new RegistryCredentialObject(credentials, tenantId, otherKeys);
-
-        credentialsCache.withFlags(Flag.FORCE_RETURN_VALUE).replaceAsync(key, registryCredential).thenAccept(result -> {
-            if (result == null){
-                log.debug("Cannot update credential : not found [tenant-id: {}, auth-id: {}, type: {}]", tenantId, credentials.getAuthId(), credentials.getType());
-                resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-            } else {
-                log.debug("Credential updated [tenant-id: {}, auth-id: {}, type: {}]", tenantId, credentials.getAuthId(), credentials.getType());
-                resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_NO_CONTENT)));
-            }
-        });
-    }
-
-    @Override
-    public void remove(final String tenantId, final String type, final String authId, final Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
-
-        final CredentialsKey key = new CredentialsKey(tenantId, authId, type);
-        credentialsCache.withFlags(Flag.FORCE_RETURN_VALUE).removeAsync(key).thenAccept(result -> {
-                    if (result == null){
-                        log.debug("Cannot remove credential : not found [tenant-id: {}, auth-id: {}, type: {}]", tenantId, authId, type);
-                        resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-                    } else {
-                        log.debug("removed credential : not found [tenant-id: {}, auth-id: {}, type: {}]", tenantId, authId, type);
-                        resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_NO_CONTENT)));
-                    }
-                }
-        );
-    }
-
-    @Override
-    public void removeAll(final String tenantId, final String deviceId, final Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
-
-        final List<RegistryCredentialObject>  matches = queryAllCredentialsForDevice(tenantId, deviceId);
-        if (matches.isEmpty()){
-            log.debug("Cannot remove credentials for device : not found [tenant-id: {}, deviceID {}]", tenantId, deviceId);
-            resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-        } else {
-            final List<CompletableFuture<RegistryCredentialObject>> futureResultList = new ArrayList<>();
-            matches.forEach(registryCredential -> {
-                final CredentialsKey key = new CredentialsKey(
-                        tenantId,
-                        new JsonObject(registryCredential.getOriginalJson()).getString(CredentialsConstants.FIELD_AUTH_ID),
-                        new JsonObject(registryCredential.getOriginalJson()).getString(CredentialsConstants.FIELD_TYPE));
-                futureResultList.add( credentialsCache.removeAsync(key));
-            });
-            CompletableFuture.allOf(futureResultList.toArray(new CompletableFuture[futureResultList.size()])).thenAccept( r-> {
-                log.debug("Removed {} credentials for device [tenant-id: {}, deviceID {}]", matches.size(), tenantId, deviceId);
-                resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_NO_CONTENT)));
-            });
-        }
-    }
-
-    @Override
-    public void getAll(final String tenantId, final String deviceId, final Span span, final Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
-
-        final JsonArray creds = new JsonArray();
-
-        queryAllCredentialsForDevice(tenantId, deviceId).forEach(result -> {
-            creds.add(new JsonObject(result.getOriginalJson()));
-        });
-
-        if (creds.isEmpty()) {
-            log.debug("Cannot retrieve credentials for device : not found [tenant-id: {}, deviceID {}]", tenantId, deviceId);
-            resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-        } else {
-
-            log.debug("Retrieved {} credentials for device [tenant-id: {}, deviceID {}]", creds.size(), tenantId, deviceId);
-            final JsonObject result = new JsonObject()
-                    .put(CredentialsConstants.FIELD_CREDENTIALS_TOTAL, creds.size())
-                    .put(CredentialsConstants.CREDENTIALS_ENDPOINT, creds);
-            resultHandler.handle(Future.succeededFuture(
-                    CredentialsResult.from(HttpURLConnection.HTTP_OK, result)));
-        }
-    }
-
-    // TODO : async request
-    private List<RegistryCredentialObject> queryAllCredentialsForDevice(final String tenantId, final String deviceId){
-        // Obtain a query factory for the cache
-        final QueryFactory queryFactory = Search.getQueryFactory(credentialsCache);
-        final Query query = queryFactory.from(RegistryCredentialObject.class)
-                .having("deviceId").eq(deviceId)
-                .and().having("tenantId").eq(tenantId)
-                .build();
-        // Execute the query
-        return query.list();
-    }
-
-    private boolean contextMatches(final JsonObject clientContext, final JsonObject storedCredential) {
-        final AtomicBoolean match = new AtomicBoolean(true);
-        clientContext.forEach(field -> {
-            if (storedCredential.containsKey(field.getKey())) {
-                if (!storedCredential.getString(field.getKey()).equals(field.getValue())) {
-                    match.set(false);
-                }
-            } else {
-                match.set(false);
-            }
-        });
-        return match.get();
-    }
-}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheProvider.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheProvider.java
new file mode 100644
index 000000000..bfbec976b
--- /dev/null
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheProvider.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2019, EnMasse authors.
+ * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
+ */
+
+package io.enmasse.iot.registry.infinispan;
+
+import javax.annotation.PreDestroy;
+
+import org.infinispan.client.hotrod.RemoteCache;
+import org.infinispan.client.hotrod.RemoteCacheManager;
+import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
+import org.infinispan.transaction.TransactionMode;
+import org.infinispan.util.concurrent.IsolationLevel;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import io.enmasse.iot.registry.infinispan.config.InfinispanProperties;
+
+@Component
+public class CacheProvider implements AutoCloseable {
+
+    private static final Logger logger = LoggerFactory.getLogger(CacheProvider.class);
+
+    private RemoteCacheManager remoteCacheManager;
+
+    @Autowired
+    public CacheProvider(final InfinispanProperties properties) {
+        logger.info("Using Infinispan - host: {}, port: {}", properties.getHost(), properties.getPort());
+
+        var config = new ConfigurationBuilder()
+
+                .addServer()
+                .host(properties.getHost())
+                .port(properties.getPort())
+
+                .build();
+
+        this.remoteCacheManager = new RemoteCacheManager(config);
+    }
+
+    @PreDestroy
+    @Override
+    public void close() throws Exception {
+       this.remoteCacheManager.close();
+    }
+
+    org.infinispan.configuration.cache.Configuration buildConfiguration() {
+        return new org.infinispan.configuration.cache.ConfigurationBuilder ()
+
+                .invocationBatching()
+                .enable()
+
+                .transaction()
+                .autoCommit(true)
+                .transactionMode(TransactionMode.TRANSACTIONAL)
+                .useSynchronization(true)
+                .recovery().disable()
+
+                .locking()
+                .isolationLevel(IsolationLevel.READ_COMMITTED)
+
+                .build();
+    }
+
+    public <K, V> RemoteCache<K, V> getOrCreateCache(final String cacheName) {
+        var configuration = buildConfiguration();
+
+        return this.remoteCacheManager
+            .administration()
+            .getOrCreateCache(cacheName, configuration);
+    }
+
+    public <K, V> RemoteCache<K, V> getCache(final String cacheName) {
+        return this.remoteCacheManager.getCache(cacheName);
+    }
+
+}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheRegistrationConfigProperties.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheRegistrationConfigProperties.java
deleted file mode 100644
index ee55c87d0..000000000
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheRegistrationConfigProperties.java
+++ /dev/null
@@ -1,12 +0,0 @@
-/*
- * Copyright 2019, EnMasse authors.
- * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
- */
-
-package io.enmasse.iot.registry.infinispan;
-
-/**
- * Configuration properties for Hono's Infinispan Registration service.
- */
-public class CacheRegistrationConfigProperties {
-}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheRegistrationService.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheRegistrationService.java
deleted file mode 100644
index f6b706d8e..000000000
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheRegistrationService.java
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * Copyright 2019, EnMasse authors.
- * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
- */
-
-package io.enmasse.iot.registry.infinispan;
-
-import io.vertx.core.AsyncResult;
-import io.vertx.core.Future;
-import io.vertx.core.Handler;
-import io.vertx.core.json.JsonObject;
-import org.eclipse.hono.service.registration.CompleteBaseRegistrationService;
-import org.eclipse.hono.util.RegistrationResult;
-import org.infinispan.client.hotrod.Flag;
-import org.infinispan.client.hotrod.RemoteCache;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Repository;
-
-import java.net.HttpURLConnection;
-
-/**
- * A Registration service that use an Infinispan as a backend service.
- * Infinispan is an open source project providing a distributed in-memory key/value data store
- *
- * <p>
- *@see <a href="https://infinspan.org">https://infinspan.org</a>
- *
- */
-@Repository
-@Primary
-public class CacheRegistrationService extends CompleteBaseRegistrationService<CacheRegistrationConfigProperties> {
-
-    private final RemoteCache<RegistrationKey, String> registrationCache;
-
-    @Autowired
-    protected CacheRegistrationService(final RemoteCache<RegistrationKey, String> cache) {
-        this.registrationCache = cache;
-    }
-
-    @Override
-    public void setConfig(final CacheRegistrationConfigProperties configuration) {
-    }
-
-    @Override
-    public void addDevice(final String tenantId, final String deviceId, final JsonObject otherKeys, final Handler<AsyncResult<RegistrationResult>> resultHandler) {
-
-        final RegistrationKey key = new RegistrationKey(tenantId, deviceId);
-
-        registrationCache.withFlags(Flag.FORCE_RETURN_VALUE).putIfAbsentAsync(key, otherKeys.encode()).thenAccept(result -> {
-            if ( result == null){
-                resultHandler.handle(Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_CREATED)));
-            } else {
-                resultHandler.handle(Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_CONFLICT)));
-            }
-        });
-    }
-
-    @Override
-    public void updateDevice(final String tenantId, final String deviceId, final JsonObject otherKeys, final Handler<AsyncResult<RegistrationResult>> resultHandler) {
-
-        final RegistrationKey key = new RegistrationKey(tenantId, deviceId);
-        registrationCache.withFlags(Flag.FORCE_RETURN_VALUE).replaceAsync(key, otherKeys.encode()).thenAccept( result -> {
-            if ( result == null){
-                resultHandler.handle(Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-            } else {
-                resultHandler.handle(Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_NO_CONTENT)));
-            }
-        });
-    }
-
-    @Override
-    public void removeDevice(final String tenantId, final String deviceId, final Handler<AsyncResult<RegistrationResult>> resultHandler) {
-
-        final RegistrationKey key = new RegistrationKey(tenantId, deviceId);
-        registrationCache.withFlags(Flag.FORCE_RETURN_VALUE).removeAsync(key).thenAccept( result -> {
-            if ( result == null){
-                resultHandler.handle(Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-            } else {
-                resultHandler.handle(Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_NO_CONTENT)));
-            }
-        });
-    }
-
-    @Override
-    public void getDevice(final String tenantId, final String deviceId, final Handler<AsyncResult<RegistrationResult>> resultHandler) {
-        final RegistrationKey key = new RegistrationKey(tenantId, deviceId);
-
-        registrationCache.withFlags(Flag.FORCE_RETURN_VALUE).getAsync(key).thenAccept( result -> {
-            if ( result == null){
-                resultHandler.handle(Future.succeededFuture(RegistrationResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-            } else {
-                resultHandler.handle(Future.succeededFuture(
-                        RegistrationResult.from(HttpURLConnection.HTTP_OK, getResultPayload(deviceId, new JsonObject(result)))));
-            }
-        });
-    }
-}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheTenantConfigProperties.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheTenantConfigProperties.java
deleted file mode 100644
index 9990ed414..000000000
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheTenantConfigProperties.java
+++ /dev/null
@@ -1,13 +0,0 @@
-/*
- * Copyright 2019, EnMasse authors.
- * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
- */
-
-package io.enmasse.iot.registry.infinispan;
-
-/**
- * Configuration properties for Hono's Infinispan Tenant service.
- *
- */
-public class CacheTenantConfigProperties {
-}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheTenantService.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheTenantService.java
deleted file mode 100644
index 88081513d..000000000
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CacheTenantService.java
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Copyright 2019, EnMasse authors.
- * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
- */
-
-package io.enmasse.iot.registry.infinispan;
-
-import io.opentracing.Span;
-import io.vertx.core.AsyncResult;
-import io.vertx.core.Future;
-import io.vertx.core.Handler;
-import io.vertx.core.json.JsonObject;
-import org.eclipse.hono.service.tenant.CompleteBaseTenantService;
-import org.eclipse.hono.util.TenantObject;
-import org.eclipse.hono.util.TenantResult;
-import org.infinispan.client.hotrod.Flag;
-import org.infinispan.client.hotrod.RemoteCache;
-import org.infinispan.client.hotrod.Search;
-import org.infinispan.query.dsl.Query;
-import org.infinispan.query.dsl.QueryFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.annotation.Primary;
-import org.springframework.stereotype.Repository;
-
-import javax.security.auth.x500.X500Principal;
-import java.net.HttpURLConnection;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-
-/**
- * A tenant service that use an Infinispan as a backend service.
- * Infinispan is an open source project providing a distributed in-memory key/value data store
- *
- * <p>
- *@see <a href="https://infinspan.org">https://infinspan.org</a>
- *
- */
-@Repository
-@Primary
-public class CacheTenantService extends CompleteBaseTenantService<CacheTenantConfigProperties> {
-
-    private final RemoteCache<String, RegistryTenantObject> tenantsCache;
-
-    @Autowired
-    protected CacheTenantService(final RemoteCache<String, RegistryTenantObject> cache) {
-        this.tenantsCache = cache;
-    }
-
-    @Override
-    public void setConfig(final CacheTenantConfigProperties configuration) {
-    }
-
-    @Override
-    public void add(final String tenantId, final JsonObject tenantObj, final Handler<AsyncResult<TenantResult<JsonObject>>> resultHandler) {
-
-        final TenantObject tenantDetails = Optional.ofNullable(tenantObj)
-                .map(json -> json.mapTo(TenantObject.class)).orElse(null);
-        tenantDetails.setTenantId(tenantId);
-
-        //verify if a duplicate cert exists
-        if (tenantDetails.getTrustedCaSubjectDn() != null) {
-            final RegistryTenantObject tenant = searchByCert(tenantDetails.getTrustedCaSubjectDn().getName());
-            if (tenant != null) {
-                resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_CONFLICT)));
-                return;
-            }
-        }
-
-        tenantsCache.withFlags(Flag.FORCE_RETURN_VALUE).putIfAbsentAsync(tenantId, new RegistryTenantObject(tenantDetails)).thenAccept(result -> {
-            if (result == null) {
-                resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_CREATED)));
-            } else {
-                resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_CONFLICT)));
-            }
-        });
-
-    }
-
-    @Override
-    public void update(final String tenantId, final JsonObject tenantObj, final Handler<AsyncResult<TenantResult<JsonObject>>> resultHandler) {
-
-        final TenantObject tenantDetails = Optional.ofNullable(tenantObj)
-                .map(json -> json.mapTo(TenantObject.class)).orElse(null);
-
-        //verify if a duplicate cert exists
-        if (tenantDetails.getTrustedCaSubjectDn() != null) {
-            final RegistryTenantObject tenant = searchByCert(tenantDetails.getTrustedCaSubjectDn().getName());
-            if (tenant != null) {
-                resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_CONFLICT)));
-                return;
-            }
-        }
-
-        tenantsCache.containsKeyAsync(tenantId).thenAccept(containsKey -> {
-            if (containsKey) {
-                tenantsCache.replaceAsync(tenantId, new RegistryTenantObject(tenantDetails)).thenAccept(result -> {
-                    resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_NO_CONTENT)));
-                });
-            } else {
-                resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-            }
-        });
-    }
-
-    @Override
-    public void remove(final String tenantId, final Handler<AsyncResult<TenantResult<JsonObject>>> resultHandler) {
-
-        tenantsCache.withFlags(Flag.FORCE_RETURN_VALUE).removeAsync(tenantId).thenAccept(result -> {
-            if (result != null) {
-                resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_NO_CONTENT)));
-            } else {
-                resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-            }
-        });
-    }
-
-    @Override
-    public void get(final String tenantId, final Span span, final Handler<AsyncResult<TenantResult<JsonObject>>> resultHandler) {
-
-        Objects.requireNonNull(tenantId);
-        Objects.requireNonNull(resultHandler);
-
-        tenantsCache.getAsync(tenantId).thenAccept(registryTenantObject -> {
-            if (registryTenantObject == null) {
-                resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-            } else {
-                resultHandler.handle(Future.succeededFuture(
-                        TenantResult.from(HttpURLConnection.HTTP_OK, new JsonObject(registryTenantObject.getTenantObject()))));
-            }
-        });
-    }
-
-    @Override
-    public void get(final X500Principal subjectDn, final Span span, final Handler<AsyncResult<TenantResult<JsonObject>>> resultHandler) {
-
-        if (subjectDn == null) {
-            resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_BAD_REQUEST)));
-        } else {
-
-            final RegistryTenantObject searchResult = searchByCert(subjectDn.getName());
-
-            if (searchResult == null) {
-                resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_NOT_FOUND)));
-            } else {
-                resultHandler.handle(Future.succeededFuture(TenantResult.from(HttpURLConnection.HTTP_OK,
-                        new JsonObject(searchResult.getTenantObject()))));
-            }
-        }
-    }
-
-    // infinispan async querying coming soon™
-    private RegistryTenantObject searchByCert(final String subjectDnName){
-
-        final QueryFactory queryFactory = Search.getQueryFactory(tenantsCache);
-        final Query query = queryFactory
-                .from(RegistryTenantObject.class)
-                .having("trustedCa")
-                .contains(subjectDnName).build();
-
-        final List<RegistryTenantObject> matches = query.list();
-
-        // TODO make a difference between not found and conflict?
-        if (matches.size() != 1){
-            return null;
-        } else {
-            return matches.get(0);
-        }
-    }
-}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/InfinispanRegistry.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/InfinispanRegistry.java
index bd0fc5ea5..0207d3eeb 100644
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/InfinispanRegistry.java
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/InfinispanRegistry.java
@@ -13,6 +13,7 @@ import org.eclipse.hono.service.AbstractApplication;
 import org.eclipse.hono.service.HealthCheckProvider;
 import org.eclipse.hono.service.auth.AuthenticationService;
 import org.eclipse.hono.service.credentials.CredentialsService;
+import org.eclipse.hono.service.deviceconnection.DeviceConnectionService;
 import org.eclipse.hono.service.registration.RegistrationService;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.boot.SpringApplication;
@@ -20,14 +21,9 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
 import org.springframework.context.annotation.ComponentScan;
 import org.springframework.context.annotation.Configuration;
 
-/**
- * A Spring Boot application exposing an AMQP based endpoint that implements Hono's device registry.
- * <p>
- * The application implements Hono's <a href="https://www.eclipse.org/hono/api/Device-Registration-API/">Device Registration API</a>
- * and <a href="https://www.eclipse.org/hono/api/Credentials-API/">Credentials API</a>.
- * </p>
- */
-@ComponentScan(basePackages = {"org.eclipse.hono.service.auth", "io.enmasse.iot.registry.infinispan"})
+@ComponentScan("org.eclipse.hono.service.auth")
+@ComponentScan( "io.enmasse.iot.registry.infinispan")
+@ComponentScan( "io.enmasse.iot.registry.infinispan.config")
 @Configuration
 @EnableAutoConfiguration
 public class InfinispanRegistry extends AbstractApplication {
@@ -35,6 +31,7 @@ public class InfinispanRegistry extends AbstractApplication {
     private AuthenticationService authenticationService;
     private CredentialsService credentialsService;
     private RegistrationService registrationService;
+    private DeviceConnectionService deviceConnectionService;
 
     /**
      * Sets the credentials service implementation this server is based on.
@@ -69,6 +66,11 @@ public class InfinispanRegistry extends AbstractApplication {
         this.authenticationService = Objects.requireNonNull(authenticationService);
     }
 
+    @Autowired
+    public void setDeviceConnectionService(DeviceConnectionService deviceConnectionService) {
+        this.deviceConnectionService = deviceConnectionService;
+    }
+
     @Override
     protected final Future<Void> deployRequiredVerticles(final int maxInstances) {
 
@@ -76,7 +78,9 @@ public class InfinispanRegistry extends AbstractApplication {
         CompositeFuture.all(
                 deployAuthenticationService(), // we only need 1 authentication service
                 deployRegistrationService(),
-                deployCredentialsService()).setHandler(ar -> {
+                deployCredentialsService(),
+                deployDeviceConnectionService()
+            ).setHandler(ar -> {
             if (ar.succeeded()) {
                 result.complete();
             } else {
@@ -86,10 +90,17 @@ public class InfinispanRegistry extends AbstractApplication {
         return result;
     }
 
+    private Future<String> deployDeviceConnectionService() {
+        final Future<String> result = Future.future();
+        log.info("Starting device connection service {}", deviceConnectionService);
+        getVertx().deployVerticle(deviceConnectionService, result);
+        return result;
+    }
+
     private Future<String> deployCredentialsService() {
         final Future<String> result = Future.future();
         log.info("Starting credentials service {}", credentialsService);
-        getVertx().deployVerticle(credentialsService, result.completer());
+        getVertx().deployVerticle(credentialsService, result);
         return result;
     }
 
@@ -99,7 +110,7 @@ public class InfinispanRegistry extends AbstractApplication {
             result.fail("authentication service is not a verticle");
         } else {
             log.info("Starting authentication service {}", authenticationService);
-            getVertx().deployVerticle((Verticle) authenticationService, result.completer());
+            getVertx().deployVerticle((Verticle) authenticationService, result);
         }
         return result;
     }
@@ -107,7 +118,7 @@ public class InfinispanRegistry extends AbstractApplication {
     private Future<String> deployRegistrationService() {
         final Future<String> result = Future.future();
         log.info("Starting registration service {}", registrationService);
-        getVertx().deployVerticle(registrationService, result.completer());
+        getVertx().deployVerticle(registrationService, result);
         return result;
     }
 
@@ -128,6 +139,9 @@ public class InfinispanRegistry extends AbstractApplication {
         if (HealthCheckProvider.class.isInstance(registrationService)) {
             registerHealthchecks((HealthCheckProvider) registrationService);
         }
+        if (HealthCheckProvider.class.isInstance(deviceConnectionService)) {
+            registerHealthchecks((HealthCheckProvider) deviceConnectionService);
+        }
         return Future.succeededFuture();
     }
 
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/InfinispanRegistryConfig.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/InfinispanRegistryConfig.java
deleted file mode 100644
index cdfa1c7c3..000000000
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/InfinispanRegistryConfig.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Copyright 2019, EnMasse authors.
- * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
- */
-
-package io.enmasse.iot.registry.infinispan;
-
-import java.util.UUID;
-import org.eclipse.hono.deviceregistry.ApplicationConfig;
-import org.eclipse.hono.service.tenant.TenantAmqpEndpoint;
-import org.eclipse.hono.service.tenant.TenantHttpEndpoint;
-import org.infinispan.client.hotrod.RemoteCache;
-import org.infinispan.client.hotrod.RemoteCacheManager;
-import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller;
-import org.infinispan.configuration.cache.ConfigurationBuilder;
-import org.infinispan.protostream.SerializationContext;
-import org.infinispan.protostream.annotations.ProtoSchemaBuilder;
-import org.infinispan.query.remote.client.ProtobufMetadataManagerConstants;
-import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-import java.io.IOException;
-import org.springframework.context.annotation.Scope;
-
-/**
- * Spring Boot configuration for the Device Registry application.
- *
- */
-@Configuration
-public class InfinispanRegistryConfig extends ApplicationConfig {
-
-    @Bean
-    public RemoteCache<CredentialsKey, RegistryCredentialObject> getCredentialsCache() throws IOException {
-        return getCache();
-    }
-
-    @Bean
-    public RemoteCache<RegistrationKey, String> getRegistrationCache() throws IOException {
-        return getCache();
-    }
-
-    @Bean
-    public RemoteCache<String, RegistryTenantObject> getTenantCache() throws IOException {
-        return getCache();
-    }
-
-    /**
-     * Connects to an infinispan server and create a randomly named RemoteCache.
-     * The constructor will use the hotrod-client.properties file that must be in the classpath.
-     *
-     * @throws IOException if the Protobuf spec file cannot be created.
-     * @return an RemoteCacheManager bean.
-     */
-    protected <K, V> RemoteCache<K,V> getCache() throws IOException {
-
-        final RemoteCacheManager remoteCacheManager = new RemoteCacheManager();
-        final SerializationContext serCtx = ProtoStreamMarshaller.getSerializationContext(remoteCacheManager);
-
-        // genereate the protobuff schema
-        String generatedSchema = new ProtoSchemaBuilder()
-                .addClass(RegistryTenantObject.class)
-                .addClass(RegistryCredentialObject.class)
-                .addClass(CredentialsKey.class)
-                .addClass(RegistrationKey.class)
-                .packageName("registry")
-                .fileName("registry.proto")
-                .build(serCtx);
-
-        // register the schema with the server
-        remoteCacheManager.getCache(ProtobufMetadataManagerConstants.PROTOBUF_METADATA_CACHE_NAME)
-            .put("registry.proto", generatedSchema);
-
-        final String cacheName = UUID.randomUUID().toString();
-        return remoteCacheManager.administration().createCache(cacheName, new ConfigurationBuilder().build());
-    }
-
-    /**
-     * Creates a new instance of an AMQP 1.0 protocol handler for Hono's <em>Tenant</em> API.
-     *
-     * @return The handler.
-     */
-    @Bean
-    @Override
-    @Scope("prototype")
-    @ConditionalOnBean(name="CacheTenantService")
-    public TenantAmqpEndpoint tenantAmqpEndpoint() {
-        return new TenantAmqpEndpoint(vertx());
-    }
-
-    /**
-     * Creates a new instance of an HTTP protocol handler for Hono's <em>Tenant</em> API.
-     *
-     * @return The handler.
-     */
-    @Bean
-    @Override
-    @Scope("prototype")
-    @ConditionalOnBean(name="CacheTenantService")
-    public TenantHttpEndpoint tenantHttpEndpoint() {
-        return new TenantHttpEndpoint(vertx());
-    }
-}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/RegistryCredentialObject.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/RegistryCredentialObject.java
deleted file mode 100644
index 6ccca81f9..000000000
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/RegistryCredentialObject.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Copyright 2019, EnMasse authors.
- * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
- */
-
-package io.enmasse.iot.registry.infinispan;
-
-import io.vertx.core.json.JsonObject;
-import org.eclipse.hono.util.CredentialsObject;
-
-import org.infinispan.protostream.annotations.ProtoDoc;
-import org.infinispan.protostream.annotations.ProtoField;
-
-/**
- * A custom class to be used as value in the backend key-value storage.
- * This store credentials details.
- *
- *  See {@link CacheTenantService CacheTenantService} class.
- */
-@ProtoDoc("@Indexed")
-public class RegistryCredentialObject {
-
-    private String tenantId;
-    private String deviceId;
-    private String originalJson;
-
-    /**
-     * Constructor without arguments for the protobuilder.
-     */
-    public RegistryCredentialObject(){
-    }
-
-    /**
-     * Create a a RegistryCredentialObject with the credentials details.
-     *
-     * @param honoCredential the credential object, in a {@link org.eclipse.hono.util.CredentialsObject Hono CredentialsObject util class}.
-     * @param tenantId the tenant ID associated with the credential.
-     * @param originalJson the raw JSON object contained in the original creation request.
-     */
-    public RegistryCredentialObject(final CredentialsObject honoCredential, final String tenantId, final JsonObject originalJson){
-        this.tenantId = tenantId;
-        this.deviceId = honoCredential.getDeviceId();
-        this.originalJson = originalJson.encode();
-    }
-
-    @ProtoDoc("@Field")
-    @ProtoField(number = 3, required = true)
-    public String getOriginalJson() {
-        return originalJson;
-    }
-
-    @ProtoDoc("@Field")
-    @ProtoField(number = 2, required = true)
-    public String getDeviceId(){
-        return deviceId;
-    }
-
-    @ProtoDoc("@Field")
-    @ProtoField(number = 1, required = true)
-    public String getTenantId() {
-        return tenantId;
-    }
-
-    public void setTenantId(String tenantId) {
-        this.tenantId = tenantId;
-    }
-
-    public void setDeviceId(String deviceId) {
-        this.deviceId = deviceId;
-    }
-
-    public void setOriginalJson(String originalJson) {
-        this.originalJson = originalJson;
-    }
-}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/RegistryTenantObject.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/RegistryTenantObject.java
deleted file mode 100644
index 5e5bd320c..000000000
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/RegistryTenantObject.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * Copyright 2019, EnMasse authors.
- * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
- */
-
-package io.enmasse.iot.registry.infinispan;
-
-import io.vertx.core.json.JsonObject;
-import org.eclipse.hono.util.TenantObject;
-
-import org.infinispan.protostream.annotations.ProtoDoc;
-import org.infinispan.protostream.annotations.ProtoField;
-
-/**
- * A custom class to be used as value in the backend key-value storage.
- * This store tenants details.
- *
- *  See {@link CacheTenantService CacheTenantService} class.
- */
-@ProtoDoc("@Indexed")
-public class RegistryTenantObject {
-
-    private String tenantId;
-    private String trustedCa;
-    private String tenantObject;
-
-    /**
-     *  Constructor without arguments for the protobuilder.
-     */
-    public RegistryTenantObject() {
-    }
-
-    /**
-     * Create a a RegistryTenantObject with the Tenant details.
-     * @param tenant the tenant object, in a {@link org.eclipse.hono.util.TenantObject Hono TenantObject util class}.
-     */
-    public RegistryTenantObject(final TenantObject tenant) {
-        this.tenantId = tenant.getTenantId();
-
-        if (tenant.getTrustedCaSubjectDn() != null ){
-            this.trustedCa = tenant.getTrustedCaSubjectDn().getName();
-        } else {
-            this.trustedCa = null;
-        }
-
-        this.tenantObject = JsonObject.mapFrom(tenant).encode();
-    }
-
-    @ProtoDoc("@Field")
-    @ProtoField(number = 3, required = true)
-    public String getTenantObject() {
-        return tenantObject;
-    }
-
-    @ProtoDoc("@Field")
-    @ProtoField(number = 1, required = true)
-    public String getTenantId() {
-        return tenantId;
-    }
-
-    // Matching TenantConstants.FIELD_PAYLOAD_TRUSTED_CA;
-    @ProtoDoc("@Field")
-    @ProtoField(number = 2)
-    public String getTrustedCa() {
-        return trustedCa;
-    }
-
-    public void setTenantId(String tenantId) {
-        this.tenantId = tenantId;
-    }
-
-    public void setTrustedCa(String trustedCa) {
-        this.trustedCa = trustedCa;
-    }
-
-    public void setTenantObject(String tenantObject) {
-        this.tenantObject = tenantObject;
-    }
-}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/config/InfinispanProperties.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/config/InfinispanProperties.java
new file mode 100644
index 000000000..715f32d1d
--- /dev/null
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/config/InfinispanProperties.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2019, EnMasse authors.
+ * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
+ */
+
+package io.enmasse.iot.registry.infinispan.config;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+@ConfigurationProperties("enmasse.iot.device.registry.infinispan")
+public class InfinispanProperties {
+
+    private static final String DEFAULT_HOST = "localhost";
+    private static final int DEFAULT_PORT = org.infinispan.client.hotrod.impl.ConfigurationProperties.DEFAULT_HOTROD_PORT;
+
+    private String host = DEFAULT_HOST;
+    private int port = DEFAULT_PORT;
+
+    public void setHost(String host) {
+        this.host = host;
+    }
+
+    public String getHost() {
+        return host;
+    }
+
+    public void setPort(int port) {
+        this.port = port;
+    }
+
+    public int getPort() {
+        return port;
+    }
+
+}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/config/InfinispanRegistryConfig.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/config/InfinispanRegistryConfig.java
new file mode 100644
index 000000000..379efbc3b
--- /dev/null
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/config/InfinispanRegistryConfig.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2019, EnMasse authors.
+ * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
+ */
+
+package io.enmasse.iot.registry.infinispan.config;
+
+import org.eclipse.hono.deviceregistry.ApplicationConfig;
+import org.eclipse.hono.service.tenant.TenantAmqpEndpoint;
+import org.eclipse.hono.service.tenant.TenantHttpEndpoint;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+import org.springframework.context.annotation.Scope;
+
+/**
+ * Spring Boot configuration for the Device Registry application.
+ *
+ */
+@Configuration
+public class InfinispanRegistryConfig extends ApplicationConfig {
+
+    /**
+     * Creates a new instance of an AMQP 1.0 protocol handler for Hono's <em>Tenant</em> API.
+     *
+     * @return The handler.
+     */
+    @Bean
+    @Override
+    @Scope("prototype")
+    @ConditionalOnBean(name="CacheTenantService")
+    public TenantAmqpEndpoint tenantAmqpEndpoint() {
+        return new TenantAmqpEndpoint(vertx());
+    }
+
+    /**
+     * Creates a new instance of an HTTP protocol handler for Hono's <em>Tenant</em> API.
+     *
+     * @return The handler.
+     */
+    @Bean
+    @Override
+    @Scope("prototype")
+    @ConditionalOnBean(name="CacheTenantService")
+    public TenantHttpEndpoint tenantHttpEndpoint() {
+        return new TenantHttpEndpoint(vertx());
+    }
+}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/credentials/CacheCredentialService.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/credentials/CacheCredentialService.java
new file mode 100644
index 000000000..72c3ef4de
--- /dev/null
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/credentials/CacheCredentialService.java
@@ -0,0 +1,213 @@
+/*
+ * Copyright 2019, EnMasse authors.
+ * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
+ */
+
+package io.enmasse.iot.registry.infinispan.credentials;
+
+import io.enmasse.iot.registry.infinispan.CacheProvider;
+import io.opentracing.Span;
+import io.vertx.core.AsyncResult;
+import io.vertx.core.Future;
+import io.vertx.core.Handler;
+import io.vertx.core.json.JsonObject;
+
+import static io.enmasse.iot.registry.infinispan.util.MoreFutures.completeHandler;
+import static java.net.HttpURLConnection.HTTP_CONFLICT;
+import static java.net.HttpURLConnection.HTTP_CREATED;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static java.net.HttpURLConnection.HTTP_OK;
+
+import java.util.Iterator;
+import java.util.Map;
+
+import org.eclipse.hono.auth.HonoPasswordEncoder;
+import org.eclipse.hono.service.credentials.CompleteBaseCredentialsService;
+import org.eclipse.hono.util.CredentialsConstants;
+import org.eclipse.hono.util.CredentialsResult;
+import org.infinispan.client.hotrod.Flag;
+import org.infinispan.client.hotrod.RemoteCache;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Repository;
+
+@Repository
+@Primary
+public class CacheCredentialService extends CompleteBaseCredentialsService<Void> {
+
+    private final RemoteCache<CredentialsKey, String> cache;
+
+    /**
+     * Creates a new service instance for a password encoder.
+     *
+     * @param pwdEncoder The encoder to use for hashing clear text passwords.
+     * @throws NullPointerException if encoder is {@code null}.
+     */
+    @Autowired
+    protected CacheCredentialService(final CacheProvider provider, final HonoPasswordEncoder pwdEncoder) {
+        this(provider
+                .<CredentialsKey, String>getOrCreateCache("credentials"),
+                pwdEncoder);
+    }
+
+    CacheCredentialService(RemoteCache<CredentialsKey, String> cache, final HonoPasswordEncoder pwdEncoder) {
+        super(pwdEncoder);
+        this.cache = cache;
+    }
+
+    @Override
+    public void setConfig(final Void configuration) {}
+
+    @Override
+    public void getAll(String tenantId, String deviceId, Span span, Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
+        handleUnimplementedOperation(resultHandler);
+    }
+
+    @Override
+    public void removeAll(String tenantId, String deviceId, Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
+        /*
+         * This implementation is far from optimal, but it will be gone
+         * once we switch to the new API of Hono.
+         */
+        final Iterator<Map.Entry<CredentialsKey, String>> i = cache.entrySet().iterator();
+        while (i.hasNext()) {
+            var entry = i.next();
+            if (isForDevice(tenantId, deviceId, entry.getKey(), entry.getValue())) {
+                i.remove();
+            }
+        }
+
+        resultHandler.handle(Future.succeededFuture(CredentialsResult.from(HTTP_NO_CONTENT)));
+    }
+
+    /**
+     * Test if a credentials entry is of the requested tenant/device combination.
+     *
+     * @param tenantId The requested tenant id.
+     * @param deviceId The requested device id.
+     * @param credentialsKey The credentials key.
+     * @param json The JSON payload.
+     * @return {@code true} if the entry matches, {@code false} otherwise.
+     */
+    private static boolean isForDevice(String tenantId, String deviceId, CredentialsKey credentialsKey, String json) {
+        if (!credentialsKey.getTenantId().equals(tenantId)) {
+            return false;
+        }
+
+        if (json == null || json.isBlank()) {
+            return false;
+        }
+
+        final JsonObject credentials = new JsonObject(json);
+        var currentDeviceId = credentials.getString(CredentialsConstants.FIELD_PAYLOAD_DEVICE_ID);
+        if (currentDeviceId == null) {
+            return false;
+        }
+
+        return currentDeviceId.equals(deviceId);
+    }
+
+    @Override
+    public void get(String tenantId, String type, String authId, Span span, Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
+        get(tenantId, type, authId, null, span, resultHandler);
+    }
+
+    @Override
+    public void get(String tenantId, String type, String authId, JsonObject clientContext, Span span, Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
+
+        var key = new CredentialsKey(tenantId, authId, type);
+
+        var future = cache
+                .getAsync(key)
+                .thenApplyAsync(r -> {
+                    if (r != null) {
+                        return CredentialsResult.<JsonObject>from(HTTP_OK, new JsonObject(r));
+                    } else {
+                        return CredentialsResult.<JsonObject>from(HTTP_NOT_FOUND);
+                    }
+                });
+
+        completeHandler(future, resultHandler);
+
+    }
+
+    @Override
+    public void add(String tenantId, JsonObject otherKeys, Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
+
+        final String authId = otherKeys.getString(CredentialsConstants.FIELD_AUTH_ID);
+        final String type = otherKeys.getString(CredentialsConstants.FIELD_TYPE);
+
+        var key = new CredentialsKey(tenantId, authId, type);
+
+        add(key, otherKeys, resultHandler);
+
+    }
+
+    private void add(CredentialsKey key, JsonObject payload, Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
+
+        var future = cache
+                .withFlags(Flag.FORCE_RETURN_VALUE)
+                .putIfAbsentAsync(key, payload.encode())
+                .thenApplyAsync(r -> {
+                    if (r == null) {
+                        return CredentialsResult.<JsonObject>from(HTTP_CREATED);
+                    } else {
+                        return CredentialsResult.<JsonObject>from(HTTP_CONFLICT);
+                    }
+                });
+
+        completeHandler(future, resultHandler);
+
+    }
+
+    @Override
+    public void update(String tenantId, JsonObject otherKeys, Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
+
+        final String authId = otherKeys.getString(CredentialsConstants.FIELD_AUTH_ID);
+        final String type = otherKeys.getString(CredentialsConstants.FIELD_TYPE);
+
+        var key = new CredentialsKey(tenantId, authId, type);
+
+        update(key, otherKeys, resultHandler);
+
+    }
+
+    private void update(CredentialsKey key, JsonObject payload, Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
+
+        var future = cache
+                .withFlags(Flag.FORCE_RETURN_VALUE)
+                .replaceAsync(key, payload.encode())
+                .thenApplyAsync(r -> {
+                    if (r == null) {
+                        return CredentialsResult.<JsonObject>from(HTTP_NOT_FOUND);
+                    } else {
+                        return CredentialsResult.<JsonObject>from(HTTP_NO_CONTENT);
+                    }
+                });
+
+        completeHandler(future, resultHandler);
+
+    }
+
+    @Override
+    public void remove(String tenantId, String type, String authId, Handler<AsyncResult<CredentialsResult<JsonObject>>> resultHandler) {
+
+        var key = new CredentialsKey(tenantId, authId, type);
+
+        var future = cache
+                .withFlags(Flag.FORCE_RETURN_VALUE)
+                .removeAsync(key)
+                .thenApplyAsync(r -> {
+                    if (r == null) {
+                        return CredentialsResult.<JsonObject>from(HTTP_NOT_FOUND);
+                    } else {
+                        return CredentialsResult.<JsonObject>from(HTTP_NO_CONTENT);
+                    }
+                });
+
+        completeHandler(future, resultHandler);
+
+    }
+
+}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CredentialsKey.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/credentials/CredentialsKey.java
similarity index 83%
rename from iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CredentialsKey.java
rename to iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/credentials/CredentialsKey.java
index 3d6bcee3e..eb1f8621b 100644
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/CredentialsKey.java
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/credentials/CredentialsKey.java
@@ -3,11 +3,10 @@
  * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
  */
 
-package io.enmasse.iot.registry.infinispan;
+package io.enmasse.iot.registry.infinispan.credentials;
 
+import java.io.Serializable;
 import java.util.Objects;
-import org.infinispan.protostream.annotations.ProtoDoc;
-import org.infinispan.protostream.annotations.ProtoField;
 
 /**
  * A custom class to be used as key in the backend key-value storage.
@@ -15,8 +14,9 @@ import org.infinispan.protostream.annotations.ProtoField;
  *
  *  See {@link CacheCredentialService CacheCredentialService} class.
  */
-@ProtoDoc("@Indexed")
-public class CredentialsKey {
+public class CredentialsKey implements Serializable {
+
+    private static final long serialVersionUID = 1L;
 
     private String tenantId;
     private String authId;
@@ -72,20 +72,14 @@ public class CredentialsKey {
         this.type = type;
     }
 
-    @ProtoDoc("@Field")
-    @ProtoField(number = 1, required = true)
     public String getTenantId() {
         return tenantId;
     }
 
-    @ProtoDoc("@Field")
-    @ProtoField(number = 2, required = true)
     public String getAuthId() {
         return authId;
     }
 
-    @ProtoDoc("@Field")
-    @ProtoField(number = 3, required = true)
     public String getType() {
         return type;
     }
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/devcon/CacheDeviceConnectionService.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/devcon/CacheDeviceConnectionService.java
new file mode 100644
index 000000000..6a7afdae4
--- /dev/null
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/devcon/CacheDeviceConnectionService.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2019, EnMasse authors.
+ * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
+ */
+
+package io.enmasse.iot.registry.infinispan.devcon;
+
+import io.enmasse.iot.registry.infinispan.CacheProvider;
+import io.opentracing.Span;
+import io.vertx.core.AsyncResult;
+import io.vertx.core.Handler;
+import io.vertx.core.json.JsonObject;
+
+import static io.enmasse.iot.registry.infinispan.util.MoreFutures.completeHandler;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.eclipse.hono.util.DeviceConnectionResult.from;
+import org.eclipse.hono.service.deviceconnection.BaseDeviceConnectionService;
+import org.eclipse.hono.service.deviceconnection.DeviceConnectionService;
+import org.eclipse.hono.util.DeviceConnectionConstants;
+import org.eclipse.hono.util.DeviceConnectionResult;
+import org.infinispan.client.hotrod.RemoteCache;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Repository;
+
+/**
+ * A {@link DeviceConnectionService} that use an Infinispan as a backend service.
+ * Infinispan is an open source project providing a distributed in-memory key/value data store
+ *
+ * <p>
+ *
+ * @see <a href="https://infinspan.org">https://infinspan.org</a>
+ *
+ */
+@Repository
+@Primary
+public class CacheDeviceConnectionService extends BaseDeviceConnectionService<Void> {
+
+    private final RemoteCache<DeviceConnectionKey, String> cache;
+
+    @Autowired
+    protected CacheDeviceConnectionService(final CacheProvider provider) {
+        this(provider.getOrCreateCache("state"));
+    }
+
+    CacheDeviceConnectionService(final RemoteCache<DeviceConnectionKey, String> cache) {
+        this.cache = cache;
+    }
+
+    @Override
+    public void setConfig(final Void configuration) {}
+
+    @Override
+    public void getLastKnownGatewayForDevice(String tenantId, String deviceId, Span span, Handler<AsyncResult<DeviceConnectionResult>> resultHandler) {
+
+        var key = new DeviceConnectionKey(tenantId, deviceId);
+
+        var future = this.cache
+                .getAsync(key)
+                .thenApply(result -> {
+                    if (result == null) {
+                        return from(HTTP_NOT_FOUND);
+                    } else {
+                        return from(HTTP_OK, result);
+                    }
+                });
+
+        completeHandler(future, resultHandler);
+    }
+
+    @Override
+    public void setLastKnownGatewayForDevice(String tenantId, String deviceId, String gatewayId, Span span, Handler<AsyncResult<DeviceConnectionResult>> resultHandler) {
+
+        var key = new DeviceConnectionKey(tenantId, deviceId);
+
+        /*
+         * Currently we are simply setting/replacing the value. This only works as long as the
+         * gatewayId is the only value in this object
+         */
+
+        var value = new JsonObject();
+        value.put(DeviceConnectionConstants.FIELD_GATEWAY_ID, gatewayId);
+
+        var future = this.cache
+                .putAsync(key, value.encode())
+                .thenApply(result -> {
+                    return from(HTTP_NO_CONTENT);
+                });
+
+        completeHandler(future, resultHandler);
+    }
+
+
+}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/devcon/DeviceConnectionKey.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/devcon/DeviceConnectionKey.java
new file mode 100644
index 000000000..242e853eb
--- /dev/null
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/devcon/DeviceConnectionKey.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2019, EnMasse authors.
+ * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
+ */
+
+package io.enmasse.iot.registry.infinispan.devcon;
+
+import java.io.Serializable;
+import java.util.Objects;
+
+public class DeviceConnectionKey implements Serializable {
+
+    private static final long serialVersionUID = 1L;
+
+    private String tenantId;
+    private String deviceId;
+
+    public DeviceConnectionKey() {}
+
+    public DeviceConnectionKey(String tenantId, String deviceId) {
+        this.tenantId = tenantId;
+        this.deviceId = deviceId;
+    }
+
+    public String getTenantId() {
+        return tenantId;
+    }
+
+    public void setTenantId(String tenantId) {
+        this.tenantId = tenantId;
+    }
+
+    public String getDeviceId() {
+        return deviceId;
+    }
+
+    public void setDeviceId(String deviceId) {
+        this.deviceId = deviceId;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(deviceId, tenantId);
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+        if (this == obj)
+            return true;
+        if (obj == null)
+            return false;
+        if (getClass() != obj.getClass())
+            return false;
+        DeviceConnectionKey other = (DeviceConnectionKey) obj;
+        return Objects.equals(deviceId, other.deviceId) && Objects.equals(tenantId, other.tenantId);
+    }
+
+}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/device/CacheRegistrationService.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/device/CacheRegistrationService.java
new file mode 100644
index 000000000..c132926b2
--- /dev/null
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/device/CacheRegistrationService.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright 2019, EnMasse authors.
+ * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
+ */
+
+package io.enmasse.iot.registry.infinispan.device;
+
+import io.enmasse.iot.registry.infinispan.CacheProvider;
+import io.vertx.core.AsyncResult;
+import io.vertx.core.Handler;
+import io.vertx.core.json.JsonObject;
+import org.eclipse.hono.service.registration.CompleteBaseRegistrationService;
+import org.eclipse.hono.util.RegistrationResult;
+import org.infinispan.client.hotrod.Flag;
+import org.infinispan.client.hotrod.RemoteCache;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Primary;
+import org.springframework.stereotype.Repository;
+
+import static io.enmasse.iot.registry.infinispan.util.MoreFutures.completeHandler;
+import static java.net.HttpURLConnection.HTTP_CONFLICT;
+import static java.net.HttpURLConnection.HTTP_CREATED;
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_NO_CONTENT;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.eclipse.hono.util.RegistrationResult.from;
+
+/**
+ * A Registration service that use an Infinispan as a backend service.
+ * Infinispan is an open source project providing a distributed in-memory key/value data store
+ *
+ * <p>
+ *
+ * @see <a href="https://infinspan.org">https://infinspan.org</a>
+ *
+ */
+@Repository
+@Primary
+public class CacheRegistrationService extends CompleteBaseRegistrationService<Void> {
+
+    private final RemoteCache<RegistrationKey, String> cache;
+
+    @Autowired
+    protected CacheRegistrationService(CacheProvider provider) {
+        this(provider
+                .<RegistrationKey,String>getOrCreateCache("devices"));
+    }
+
+    CacheRegistrationService(RemoteCache<RegistrationKey, String> cache) {
+        this.cache = cache;
+    }
+
+    @Override
+    public void setConfig(final Void configuration) {}
+
+    @Override
+    public void addDevice(final String tenantId, final String deviceId, final JsonObject otherKeys, final Handler<AsyncResult<RegistrationResult>> resultHandler) {
+
+        var key = new RegistrationKey(tenantId, deviceId);
+
+        var future = cache
+                .withFlags(Flag.FORCE_RETURN_VALUE)
+                .putIfAbsentAsync(key, otherKeys.encode())
+                .thenApplyAsync(result -> {
+                    if (result == null) {
+                        return from(HTTP_CREATED);
+                    } else {
+                        return from(HTTP_CONFLICT);
+                    }
+                });
+
+        completeHandler(future, resultHandler);
+
+    }
+
+    @Override
+    public void updateDevice(final String tenantId, final String deviceId, final JsonObject otherKeys, final Handler<AsyncResult<RegistrationResult>> resultHandler) {
+
+        var key = new RegistrationKey(tenantId, deviceId);
+
+        var future = cache
+                .withFlags(Flag.FORCE_RETURN_VALUE)
+                .replaceAsync(key, otherKeys.encode())
+                .thenApplyAsync(result -> {
+                    if (result == null) {
+                        return from(HTTP_NOT_FOUND);
+                    } else {
+                        return from(HTTP_NO_CONTENT);
+                    }
+                });
+
+        completeHandler(future, resultHandler);
+    }
+
+    @Override
+    public void removeDevice(final String tenantId, final String deviceId, final Handler<AsyncResult<RegistrationResult>> resultHandler) {
+
+        var key = new RegistrationKey(tenantId, deviceId);
+
+        var future = cache
+                .withFlags(Flag.FORCE_RETURN_VALUE)
+                .removeAsync(key)
+                .thenApplyAsync(result -> {
+                    if (result == null) {
+                        return from(HTTP_NOT_FOUND);
+                    } else {
+                        return from(HTTP_NO_CONTENT);
+                    }
+                });
+
+        completeHandler(future, resultHandler);
+    }
+
+    @Override
+    public void getDevice(final String tenantId, final String deviceId, final Handler<AsyncResult<RegistrationResult>> resultHandler) {
+
+        var key = new RegistrationKey(tenantId, deviceId);
+
+        var future = cache
+                .getAsync(key)
+                .thenApplyAsync(result -> {
+                    if (result == null) {
+                        return from(HTTP_NOT_FOUND);
+                    } else {
+                        return from(HTTP_OK, getResultPayload(deviceId, new JsonObject(result)));
+                    }
+                });
+
+        completeHandler(future, resultHandler);
+    }
+}
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/RegistrationKey.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/device/RegistrationKey.java
similarity index 75%
rename from iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/RegistrationKey.java
rename to iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/device/RegistrationKey.java
index 33075a625..6b8163edb 100644
--- a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/RegistrationKey.java
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/device/RegistrationKey.java
@@ -3,27 +3,24 @@
  * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
  */
 
-package io.enmasse.iot.registry.infinispan;
+package io.enmasse.iot.registry.infinispan.device;
 
+import java.io.Serializable;
 import java.util.Objects;
-import org.infinispan.protostream.annotations.ProtoDoc;
-import org.infinispan.protostream.annotations.ProtoField;
 
 /**
  * A custom class to be used as key in the backend key-value storage.
- * This uses the uniques values of a registration to create a unique key to store the registration details.
+ * This uses the unique values of a registration to create a unique key to store the registration details.
  *
  *  See {@link CacheRegistrationService CacheRegistrationService} class.
  */
-@ProtoDoc("@Indexed")
-public class RegistrationKey {
+public class RegistrationKey implements Serializable {
+
+    private static final long serialVersionUID = 1L;
 
     private String tenantId;
     private String deviceId;
 
-    /**
-     * Constructor without arguments for the protobuilder.
-     */
     public RegistrationKey() {
     }
 
@@ -56,8 +53,6 @@ public class RegistrationKey {
         return Objects.hash(tenantId, deviceId);
     }
 
-    @ProtoDoc("@Field")
-    @ProtoField(number = 1, required = true)
     public String getTenantId() {
         return tenantId;
     }
@@ -66,8 +61,6 @@ public class RegistrationKey {
         this.tenantId = tenantId;
     }
 
-    @ProtoDoc("@Field")
-    @ProtoField(number = 2, required = true)
     public String getDeviceId() {
         return deviceId;
     }
diff --git a/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/util/MoreFutures.java b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/util/MoreFutures.java
new file mode 100644
index 000000000..3b562cfea
--- /dev/null
+++ b/iot/iot-device-registry-infinispan/src/main/java/io/enmasse/iot/registry/infinispan/util/MoreFutures.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2019, EnMasse authors.
+ * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
+ */
+
+package io.enmasse.iot.registry.infinispan.util;
+
+import java.util.concurrent.CompletableFuture;
+
+import io.vertx.core.AsyncResult;
+import io.vertx.core.Future;
+import io.vertx.core.Handler;
+
+public final class MoreFutures {
+    private MoreFutures() {}
+
+    public static <T> void completeHandler(final CompletableFuture<T> future, final Handler<AsyncResult<T>> handler) {
+        future.whenComplete((result, error) -> {
+            if (error == null) {
+                handler.handle(Future.succeededFuture(result));
+            } else {
+                handler.handle(Future.failedFuture(error));
+            }
+        });
+    }
+
+}
diff --git a/iot/iot-device-registry-infinispan/src/main/resources/banner.txt b/iot/iot-device-registry-infinispan/src/main/resources/banner.txt
new file mode 100644
index 000000000..7a69fc2c6
--- /dev/null
+++ b/iot/iot-device-registry-infinispan/src/main/resources/banner.txt
@@ -0,0 +1,13 @@
+
+  ______       __  __                      _____   _______ 
+ |  ____|     |  \/  |                    |_   _| |__   __|
+ | |__   _ __ | \  / | __ _ ___ ___  ___    | |  ___ | |   
+ |  __| | '_ \| |\/| |/ _` / __/ __|/ _ \   | | / _ \| |   
+ | |____| | | | |  | | (_| \__ \__ \  __/  _| || (_) | |   
+ |______|_| |_|_|  |_|\__,_|___/___/\___| |_____\___/|_|   
+                                                           
+
+EnMasse IoT Device Registry ${application.formatted-version}
+using Spring Boot ${spring-boot.formatted-version}
+
+Go to https://enmasse.io for more information.
diff --git a/iot/iot-device-registry-infinispan/src/main/resources/cache-configuration.xml b/iot/iot-device-registry-infinispan/src/main/resources/cache-configuration.xml
deleted file mode 100644
index 1b012b146..000000000
--- a/iot/iot-device-registry-infinispan/src/main/resources/cache-configuration.xml
+++ /dev/null
@@ -1,10 +0,0 @@
-<infinispan>
-    <cache-container default-cache="local">
-        <transport cluster="mycluster"/>
-        <local-cache name="local"/>
-        <invalidation-cache name="invalidation" mode="SYNC"/>
-        <replicated-cache name="repl-sync" mode="SYNC"/>
-        <distributed-cache name="dist-sync" mode="SYNC"/>
-    </cache-container>
-</infinispan>
-
diff --git a/iot/iot-device-registry-infinispan/src/main/resources/hotrod-client.properties b/iot/iot-device-registry-infinispan/src/main/resources/hotrod-client.properties
deleted file mode 100644
index dde1f8534..000000000
--- a/iot/iot-device-registry-infinispan/src/main/resources/hotrod-client.properties
+++ /dev/null
@@ -1,22 +0,0 @@
-infinispan.client.hotrod.server_list = ${infinispanserver}
-infinispan.client.hotrod.marshaller = org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller
-infinispan.client.hotrod.async_executor_factory = org.infinispan.client.hotrod.impl.async.DefaultAsyncExecutorFactory
-infinispan.client.hotrod.default_executor_factory.pool_size = 1
-infinispan.client.hotrod.default_executor_factory.queue_size = 10000
-infinispan.client.hotrod.tcp_no_delay = true
-infinispan.client.hotrod.request_balancing_strategy = org.infinispan.client.hotrod.impl.transport.tcp.RoundRobinBalancingStrategy
-infinispan.client.hotrod.key_size_estimate = 64
-infinispan.client.hotrod.value_size_estimate = 512
-infinispan.client.hotrod.force_return_value = true
-infinispan.client.hotrod.client_intelligence = HASH_DISTRIBUTION_AWARE
-infinispan.client.hotrod.batch_Size = 10000
-
-## below is connection pooling config
-maxActive=-1
-maxTotal = -1
-maxIdle = -1
-whenExhaustedAction = 1
-timeBetweenEvictionRunsMillis=120000
-minEvictableIdleTimeMillis=300000
-testWhileIdle = true
-minIdle = 1
diff --git a/iot/iot-gc/pom.xml b/iot/iot-gc/pom.xml
index 113faa205..af31a2d88 100644
--- a/iot/iot-gc/pom.xml
+++ b/iot/iot-gc/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>iot-application-base</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
     <relativePath>../iot-application-base</relativePath>
   </parent>
   <packaging>pom</packaging>
diff --git a/iot/iot-http-adapter/pom.xml b/iot/iot-http-adapter/pom.xml
index 66529d43c..5ad2938cf 100644
--- a/iot/iot-http-adapter/pom.xml
+++ b/iot/iot-http-adapter/pom.xml
@@ -8,7 +8,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>iot-application-base</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
     <relativePath>../iot-application-base</relativePath>
   </parent>
 
diff --git a/iot/iot-mqtt-adapter/pom.xml b/iot/iot-mqtt-adapter/pom.xml
index 1125726ac..7a6f4bf19 100644
--- a/iot/iot-mqtt-adapter/pom.xml
+++ b/iot/iot-mqtt-adapter/pom.xml
@@ -8,7 +8,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>iot-application-base</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
     <relativePath>../iot-application-base</relativePath>
   </parent>
 
diff --git a/iot/iot-proxy-configurator/pom.xml b/iot/iot-proxy-configurator/pom.xml
index d0f063439..3bfafc817 100644
--- a/iot/iot-proxy-configurator/pom.xml
+++ b/iot/iot-proxy-configurator/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>iot-application-base</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
     <relativePath>../iot-application-base</relativePath>
   </parent>
   <packaging>pom</packaging>
diff --git a/iot/iot-tenant-service/pom.xml b/iot/iot-tenant-service/pom.xml
index b7bcd4bc3..d5de2f28e 100644
--- a/iot/iot-tenant-service/pom.xml
+++ b/iot/iot-tenant-service/pom.xml
@@ -8,7 +8,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>iot-application-base</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
     <relativePath>../iot-application-base</relativePath>
   </parent>
 
diff --git a/iot/pom.xml b/iot/pom.xml
index 52fd7c930..ee82eae9b 100644
--- a/iot/pom.xml
+++ b/iot/pom.xml
@@ -7,7 +7,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <artifactId>iot</artifactId>
   <packaging>pom</packaging>
@@ -84,7 +84,7 @@
 
       <dependency>
         <groupId>org.infinispan</groupId>
-        <artifactId>infinispan-query</artifactId>
+        <artifactId>infinispan-core</artifactId>
         <version>${infinispan.version}</version>
       </dependency>
       <dependency>
@@ -92,11 +92,6 @@
         <artifactId>infinispan-client-hotrod</artifactId>
         <version>${infinispan.version}</version>
       </dependency>
-      <dependency>
-        <groupId>org.infinispan</groupId>
-        <artifactId>infinispan-remote-query-client</artifactId>
-        <version>${infinispan.version}</version>
-      </dependency>
       <dependency>
         <groupId>org.infinispan</groupId>
         <artifactId>infinispan-server-hotrod</artifactId>
diff --git a/k8s-api/pom.xml b/k8s-api/pom.xml
index 9f1e8b935..836518c4e 100644
--- a/k8s-api/pom.xml
+++ b/k8s-api/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.enmasse</groupId>
diff --git a/keycloak-plugin/pom.xml b/keycloak-plugin/pom.xml
index e9b95ac74..bc0731e50 100644
--- a/keycloak-plugin/pom.xml
+++ b/keycloak-plugin/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <packaging>pom</packaging>
   <modelVersion>4.0.0</modelVersion>
diff --git a/keycloak-plugin/sasl-plugin/pom.xml b/keycloak-plugin/sasl-plugin/pom.xml
index 713147c71..4f7205e45 100644
--- a/keycloak-plugin/sasl-plugin/pom.xml
+++ b/keycloak-plugin/sasl-plugin/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>keycloak</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>sasl-plugin</artifactId>
diff --git a/keycloak-user-api/pom.xml b/keycloak-user-api/pom.xml
index 5c7b3c76b..4cac4a7b5 100644
--- a/keycloak-user-api/pom.xml
+++ b/keycloak-user-api/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.enmasse</groupId>
diff --git a/metrics-api/pom.xml b/metrics-api/pom.xml
index 8256fb578..c8c195cf3 100644
--- a/metrics-api/pom.xml
+++ b/metrics-api/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.enmasse</groupId>
diff --git a/mqtt-gateway/pom.xml b/mqtt-gateway/pom.xml
index bc36e0620..aab8154a0 100644
--- a/mqtt-gateway/pom.xml
+++ b/mqtt-gateway/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>mqtt-gateway</artifactId>
diff --git a/mqtt-lwt/pom.xml b/mqtt-lwt/pom.xml
index ac84fb79f..b9e778f34 100644
--- a/mqtt-lwt/pom.xml
+++ b/mqtt-lwt/pom.xml
@@ -3,7 +3,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>mqtt-lwt</artifactId>
diff --git a/none-authservice/pom.xml b/none-authservice/pom.xml
index ae335f3c1..292340c50 100644
--- a/none-authservice/pom.xml
+++ b/none-authservice/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>none-authservice</artifactId>
diff --git a/pkg/controller/iotconfig/infinispan_device_registry.go b/pkg/controller/iotconfig/infinispan_device_registry.go
index 1ecaacb19..53a60c6e2 100644
--- a/pkg/controller/iotconfig/infinispan_device_registry.go
+++ b/pkg/controller/iotconfig/infinispan_device_registry.go
@@ -7,13 +7,14 @@ package iotconfig
 
 import (
 	"context"
-	"k8s.io/apimachinery/pkg/apis/meta/v1"
+	"strings"
 
-	"k8s.io/apimachinery/pkg/util/intstr"
+	"k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	"github.com/enmasseproject/enmasse/pkg/util"
 	"github.com/enmasseproject/enmasse/pkg/util/recon"
 	routev1 "github.com/openshift/api/route/v1"
+	"k8s.io/apimachinery/pkg/util/intstr"
 
 	"sigs.k8s.io/controller-runtime/pkg/reconcile"
 
@@ -94,6 +95,8 @@ func (r *ReconcileIoTConfig) reconcileInfinispanDeviceRegistryDeployment(config
 
 		// environment
 
+		toks := strings.Split(config.Spec.ServicesConfig.DeviceRegistry.Infinispan.ServerAddress, ":")
+
 		container.Env = []corev1.EnvVar{
 			{Name: "SPRING_CONFIG_LOCATION", Value: "file:///etc/config/"},
 			{Name: "SPRING_PROFILES_ACTIVE", Value: ""},
@@ -105,7 +108,8 @@ func (r *ReconcileIoTConfig) reconcileInfinispanDeviceRegistryDeployment(config
 
 			{Name: "HONO_REGISTRY_SVC_SIGNING_SHARED_SECRET", Value: *config.Status.AuthenticationServicePSK},
 
-			{Name: "JAVA_OPTS", Value: `-Dinfinispanserver=` + config.Spec.ServicesConfig.DeviceRegistry.Infinispan.ServerAddress},
+			{Name: "ENMASSE_IOT_DEVICE_REGISTRY_INFINISPAN_HOST", Value: toks[0]},
+			{Name: "ENMASSE_IOT_DEVICE_REGISTRY_INFINISPAN_PORT", Value: toks[1]},
 		}
 
 		AppendStandardHonoJavaOptions(container)
diff --git a/pom.properties b/pom.properties
index 6fbade79c..2336844d7 100644
--- a/pom.properties
+++ b/pom.properties
@@ -2,6 +2,6 @@ application.display.name=EnMasse
 application.globalconsole.display.name=EnMasse Console
 application.bundle.prefix=enmasse
 license.advice.text=EnMasse comprises the following components:
-release.version=0.29-SNAPSHOT
-maven.version=0.29-SNAPSHOT
+release.version=0.30-SNAPSHOT
+maven.version=0.30-SNAPSHOT
 application.docs=https://enmasse.io/documentation/
diff --git a/pom.xml b/pom.xml
index 63598709e..48eb361e3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -6,7 +6,7 @@
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
     <packaging>pom</packaging>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
 
     <name>EnMasse</name>
     <url>http://enmasse.io/</url>
diff --git a/service-broker/pom.xml b/service-broker/pom.xml
index 5c2f94494..6ad72cc73 100644
--- a/service-broker/pom.xml
+++ b/service-broker/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>service-broker</artifactId>
diff --git a/standard-controller/pom.xml b/standard-controller/pom.xml
index eedd58d1d..045c582ef 100644
--- a/standard-controller/pom.xml
+++ b/standard-controller/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>standard-controller</artifactId>
diff --git a/topic-forwarder/pom.xml b/topic-forwarder/pom.xml
index fec2f66b8..1ab8e2ae6 100644
--- a/topic-forwarder/pom.xml
+++ b/topic-forwarder/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <artifactId>topic-forwarder</artifactId>


Test patch:
diff --git a/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/CacheTenantServiceTest.java b/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/CacheTenantServiceTest.java
deleted file mode 100644
index 560ebcd38..000000000
--- a/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/CacheTenantServiceTest.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright 2019, EnMasse authors.
- * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
- */
-
-package io.enmasse.iot.registry.infinispan;
-
-import io.vertx.junit5.VertxExtension;
-
-import org.eclipse.hono.service.tenant.AbstractCompleteTenantServiceTest;
-import org.eclipse.hono.service.tenant.CompleteTenantService;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
-import org.junit.jupiter.api.extension.ExtendWith;
-import java.io.IOException;
-
-/**
- * Tests verifying behavior of {@link CacheTenantService}.
- *
- */
-@Disabled
-@ExtendWith(VertxExtension.class)
-public class CacheTenantServiceTest extends AbstractCompleteTenantServiceTest {
-
-    private static CacheTenantService service;
-    private static EmbeddedHotRodServer server;
-
-    /**
-     * Spin up the service using Infinispan EmbeddedCache.
-     * @throws IOException if the Protobuf spec file cannot be found.
-     */
-    @BeforeEach
-    public void setUp() throws IOException {
-        server = new EmbeddedHotRodServer();
-        service = new CacheTenantService(server.getCache());
-    }
-
-    /**
-     *
-     *
-     * @return
-     */
-    @AfterEach
-    public void cleanUp() {
-        server.stop();
-    }
-
-    @Override
-    public CompleteTenantService getCompleteTenantService() {
-        return service;
-    }
-}
\ No newline at end of file
diff --git a/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/EmbeddedHotRodServer.java b/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/EmbeddedHotRodServer.java
index 44d01cceb..c717e86b2 100644
--- a/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/EmbeddedHotRodServer.java
+++ b/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/EmbeddedHotRodServer.java
@@ -7,74 +7,55 @@ package io.enmasse.iot.registry.infinispan;
 
 import java.io.IOException;
 
-import java.util.UUID;
 import org.infinispan.client.hotrod.RemoteCache;
-import org.infinispan.client.hotrod.RemoteCacheManager;
-import org.infinispan.client.hotrod.configuration.ConfigurationBuilder;
-import org.infinispan.client.hotrod.marshall.ProtoStreamMarshaller;
 import org.infinispan.manager.DefaultCacheManager;
-import org.infinispan.protostream.SerializationContext;
-import org.infinispan.protostream.annotations.ProtoSchemaBuilder;
-import org.infinispan.query.remote.client.ProtobufMetadataManagerConstants;
-
 import org.infinispan.server.hotrod.HotRodServer;
 import org.infinispan.server.hotrod.configuration.HotRodServerConfiguration;
 import org.infinispan.server.hotrod.configuration.HotRodServerConfigurationBuilder;
 
+import io.enmasse.iot.registry.infinispan.config.InfinispanProperties;
+
 /**
-* This is heavily inspired from Tristan Tarrant's SimpleEmbeddedHotRodServer.
-* Mimics a remote server using an embedded cache
-*
-* https://github.com/tristantarrant/infinispan-playground-embedded-hotrod/blob/master/src/main/java/net/dataforte/infinispan/playground/embeddedhotrod/SimpleEmbeddedHotRodServer.java
-*/
+ * This is heavily inspired from Tristan Tarrant's SimpleEmbeddedHotRodServer.
+ * Mimics a remote server using an embedded cache
+ *
+ * https://github.com/tristantarrant/infinispan-playground-embedded-hotrod/blob/master/src/main/java/net/dataforte/infinispan/playground/embeddedhotrod/SimpleEmbeddedHotRodServer.java
+ */
 public class EmbeddedHotRodServer {
 
-    private final RemoteCacheManager manager;
     private final HotRodServer server;
     private final DefaultCacheManager defaultCacheManager;
-
-    private final String CACHE_NAME = UUID.randomUUID().toString();
+    private CacheProvider provider;
 
     public EmbeddedHotRodServer() throws IOException {
 
-        org.infinispan.configuration.cache.ConfigurationBuilder embeddedBuilder = new org.infinispan.configuration.cache.ConfigurationBuilder();
-        defaultCacheManager = new DefaultCacheManager(embeddedBuilder.build());
-        defaultCacheManager.createCache(CACHE_NAME, embeddedBuilder.build());
+        var config = new org.infinispan.configuration.cache.ConfigurationBuilder()
+                .build();
+        defaultCacheManager = new DefaultCacheManager(config);
 
-        HotRodServerConfiguration build = new HotRodServerConfigurationBuilder().build();
+        final HotRodServerConfiguration build = new HotRodServerConfigurationBuilder()
+                .build();
         server = new HotRodServer();
-            server.start(build, defaultCacheManager);
+        server.start(build, defaultCacheManager);
 
-        ConfigurationBuilder remoteBuilder = new ConfigurationBuilder()
-            .addServers("localhost")
-            .marshaller(new ProtoStreamMarshaller());
-        manager = new RemoteCacheManager(remoteBuilder.build());
-
-        final SerializationContext serialCtx = ProtoStreamMarshaller.getSerializationContext(manager);
+        final InfinispanProperties properties = new InfinispanProperties();
+        this.provider = new CacheProvider(properties);
+    }
 
-        // generate the protobuf schema
-        String generatedSchema = new ProtoSchemaBuilder()
-                    .addClass(RegistryTenantObject.class)
-                    .addClass(RegistryCredentialObject.class)
-                    .addClass(CredentialsKey.class)
-                    .addClass(RegistrationKey.class)
-                    .packageName("registry")
-                    .fileName("registry.proto")
-                    .build(serialCtx);
+    public <K, V> RemoteCache<K, V> getCache(String cacheName) {
+        var config = provider.buildConfiguration();
 
-        // register the schema with the server
-        RemoteCache<String, String> rcache = manager.getCache(ProtobufMetadataManagerConstants.PROTOBUF_METADATA_CACHE_NAME);
-        rcache.put("registry.proto", generatedSchema);
+        defaultCacheManager.defineConfiguration(cacheName, config);
+        return provider.getCache(cacheName);
     }
 
-    public <K, V> RemoteCache<K,V> getCache(){
-        return manager.getCache(CACHE_NAME);
-    }
+    public void stop() throws Exception {
+        try {
+            provider.close();
+        } finally {
+            defaultCacheManager.stop();
+            server.stop();
+        }
 
-    public void stop() {
-        defaultCacheManager.removeCache(CACHE_NAME);
-        manager.stop();
-        defaultCacheManager.stop();
-        server.stop();
     }
 }
diff --git a/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/CacheCredentialsServiceTest.java b/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/credentials/CacheCredentialsServiceTest.java
similarity index 55%
rename from iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/CacheCredentialsServiceTest.java
rename to iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/credentials/CacheCredentialsServiceTest.java
index d35ae6b53..3d0688901 100644
--- a/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/CacheCredentialsServiceTest.java
+++ b/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/credentials/CacheCredentialsServiceTest.java
@@ -2,7 +2,7 @@
  * Copyright 2019, EnMasse authors.
  * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
  */
-package io.enmasse.iot.registry.infinispan;
+package io.enmasse.iot.registry.infinispan.credentials;
 
 import org.eclipse.hono.auth.SpringBasedHonoPasswordEncoder;
 import org.eclipse.hono.service.credentials.AbstractCompleteCredentialsServiceTest;
@@ -13,7 +13,10 @@ import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.extension.ExtendWith;
 
+import io.enmasse.iot.registry.infinispan.EmbeddedHotRodServer;
+import io.enmasse.iot.registry.infinispan.credentials.CacheCredentialService;
 import io.vertx.junit5.VertxExtension;
+import io.vertx.junit5.VertxTestContext;
 
 import java.io.IOException;
 
@@ -21,28 +24,23 @@ import java.io.IOException;
  * Tests verifying behavior of {@link CacheCredentialService}.
  *
  */
-@Disabled
 @ExtendWith(VertxExtension.class)
 public class CacheCredentialsServiceTest extends AbstractCompleteCredentialsServiceTest {
 
-    private static CacheCredentialService service;
-    private static EmbeddedHotRodServer server;
+    private CacheCredentialService service;
+    private EmbeddedHotRodServer server;
 
     /**
      * Spin up the service using Infinispan EmbeddedCache.
      */
     @BeforeEach
     public void setUp() throws IOException {
-
         server = new EmbeddedHotRodServer();
-        service = new CacheCredentialService(server.getCache(), new SpringBasedHonoPasswordEncoder());
+        service = new CacheCredentialService(server.getCache("credentials"), new SpringBasedHonoPasswordEncoder());
     }
 
-    /**
-     * Stop the Embedded Infinispan Server.
-     */
     @AfterEach
-    public void cleanUp() {
+    public void cleanUp() throws Exception {
         server.stop();
     }
 
@@ -50,4 +48,16 @@ public class CacheCredentialsServiceTest extends AbstractCompleteCredentialsServ
     public CompleteCredentialsService getCompleteCredentialsService() {
         return service;
     }
+
+    @Disabled("We don't support access by device-id")
+    @Override
+    public void testRemoveCredentialsByDeviceSucceeds(VertxTestContext ctx) {
+        super.testRemoveCredentialsByDeviceSucceeds(ctx);
+    }
+
+    @Disabled("We don't use client contexts")
+    @Override
+    public void testGetCredentialsFailsForWrongClientContext(VertxTestContext ctx) {
+        super.testGetCredentialsFailsForWrongClientContext(ctx);
+    }
 }
diff --git a/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/devcon/CacheDeviceConnectionServiceTest.java b/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/devcon/CacheDeviceConnectionServiceTest.java
new file mode 100644
index 000000000..546a275d2
--- /dev/null
+++ b/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/devcon/CacheDeviceConnectionServiceTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2019, EnMasse authors.
+ * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
+ */
+
+package io.enmasse.iot.registry.infinispan.devcon;
+
+import org.eclipse.hono.util.DeviceConnectionConstants;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+
+import io.enmasse.iot.registry.infinispan.EmbeddedHotRodServer;
+import io.enmasse.iot.registry.infinispan.device.CacheRegistrationService;
+import io.opentracing.noop.NoopSpan;
+import io.vertx.core.Future;
+import io.vertx.junit5.VertxExtension;
+import io.vertx.junit5.VertxTestContext;
+
+import static java.net.HttpURLConnection.HTTP_NOT_FOUND;
+import static java.net.HttpURLConnection.HTTP_OK;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+import java.io.IOException;
+import java.util.UUID;
+
+/**
+ * Tests verifying behavior of {@link CacheRegistrationService}.
+ *
+ */
+@ExtendWith(VertxExtension.class)
+public class CacheDeviceConnectionServiceTest {
+
+    private static final String DEFAULT_TENANT = "my.tenant";
+
+    private CacheDeviceConnectionService service;
+    private EmbeddedHotRodServer server;
+
+    @BeforeEach
+    public void setUp() throws IOException {
+        server = new EmbeddedHotRodServer();
+        service = new CacheDeviceConnectionService(server.getCache("state"));
+    }
+
+    @AfterEach
+    public void cleanUp() throws Exception {
+        server.stop();
+    }
+
+    @Test
+    public void testGetNotFound(final VertxTestContext ctx) {
+
+        service.getLastKnownGatewayForDevice(DEFAULT_TENANT, "unknown-device", NoopSpan.INSTANCE,
+                ctx.succeeding(r -> ctx.verify(() -> {
+                    assertEquals(HTTP_NOT_FOUND, r.getStatus());
+                    ctx.completeNow();
+                })));
+
+    }
+
+    @Test
+    public void testCreateAndGet(final VertxTestContext ctx) {
+
+        final String deviceId = UUID.randomUUID().toString();
+
+        Future<Object> phase1 = Future.future();
+        service.setLastKnownGatewayForDevice(DEFAULT_TENANT, deviceId, "gw1", NoopSpan.INSTANCE, ctx.succeeding(phase1::complete));
+
+        Future<Object> phase2 = Future.future();
+        phase1.setHandler(x -> {
+            service.getLastKnownGatewayForDevice(DEFAULT_TENANT, deviceId, NoopSpan.INSTANCE, ctx.succeeding(r -> {
+                ctx.verify(() -> {
+                    assertEquals(HTTP_OK, r.getStatus());
+                    String gw = r.getPayload().getString(DeviceConnectionConstants.FIELD_GATEWAY_ID);
+                    assertEquals("gw1", gw);
+                    phase2.complete();
+                });
+            }));
+        });
+
+        Future<Object> phase3 = Future.future();
+        phase2.setHandler(x -> {
+            service.setLastKnownGatewayForDevice(DEFAULT_TENANT, deviceId, "gw2", NoopSpan.INSTANCE, ctx.succeeding(phase3::complete));
+        });
+
+        Future<Object> phase4 = Future.future();
+        phase3.setHandler(x -> {
+            service.getLastKnownGatewayForDevice(DEFAULT_TENANT, deviceId, NoopSpan.INSTANCE, ctx.succeeding(r -> {
+                ctx.verify(() -> {
+                    assertEquals(HTTP_OK, r.getStatus());
+                    String gw = r.getPayload().getString(DeviceConnectionConstants.FIELD_GATEWAY_ID);
+                    assertEquals("gw2", gw);
+                    phase4.complete();
+                });
+            }));
+        });
+
+        phase4.setHandler(ctx.succeeding(r -> ctx.completeNow()));
+
+    }
+
+}
diff --git a/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/CacheRegistrationServiceTest.java b/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/device/CacheRegistrationServiceTest.java
similarity index 67%
rename from iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/CacheRegistrationServiceTest.java
rename to iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/device/CacheRegistrationServiceTest.java
index 4554572fb..1f236a903 100644
--- a/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/CacheRegistrationServiceTest.java
+++ b/iot/iot-device-registry-infinispan/src/test/java/io/enmasse/iot/registry/infinispan/device/CacheRegistrationServiceTest.java
@@ -3,15 +3,16 @@
  * License: Apache License 2.0 (see the file LICENSE or http://apache.org/licenses/LICENSE-2.0.html).
  */
 
-package io.enmasse.iot.registry.infinispan;
+package io.enmasse.iot.registry.infinispan.device;
 
 import org.eclipse.hono.service.registration.AbstractCompleteRegistrationServiceTest;
 import org.eclipse.hono.service.registration.CompleteRegistrationService;
 import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.extension.ExtendWith;
 
+import io.enmasse.iot.registry.infinispan.EmbeddedHotRodServer;
+import io.enmasse.iot.registry.infinispan.device.CacheRegistrationService;
 import io.vertx.junit5.VertxExtension;
 
 import java.io.IOException;
@@ -20,31 +21,20 @@ import java.io.IOException;
  * Tests verifying behavior of {@link CacheRegistrationService}.
  *
  */
-@Disabled
 @ExtendWith(VertxExtension.class)
 public class CacheRegistrationServiceTest extends AbstractCompleteRegistrationServiceTest {
 
-    private static CacheRegistrationService service;
-    private static EmbeddedHotRodServer server;
+    private CacheRegistrationService service;
+    private EmbeddedHotRodServer server;
 
-    /**
-     * Spin up the service using Infinispan EmbeddedCache.
-     * @throws IOException if the Protobuf spec file cannot be found.
-     */
     @BeforeEach
     public void setUp() throws IOException {
-
         server = new EmbeddedHotRodServer();
-        service = new CacheRegistrationService(server.getCache());
+        service = new CacheRegistrationService(server.getCache("devices"));
     }
 
-    /**
-     *
-     *
-     * @return
-     */
     @AfterEach
-    public void cleanUp() {
+    public void cleanUp() throws Exception {
         server.stop();
     }
 
diff --git a/k8s-api-testutil/pom.xml b/k8s-api-testutil/pom.xml
index c5cbee8d6..4ec528106 100644
--- a/k8s-api-testutil/pom.xml
+++ b/k8s-api-testutil/pom.xml
@@ -4,7 +4,7 @@
   <parent>
     <groupId>io.enmasse</groupId>
     <artifactId>enmasse</artifactId>
-    <version>0.29-SNAPSHOT</version>
+    <version>0.30-SNAPSHOT</version>
   </parent>
   <modelVersion>4.0.0</modelVersion>
   <groupId>io.enmasse</groupId>
diff --git a/systemtests/pom.xml b/systemtests/pom.xml
index 2396ceea6..5a403b7d0 100644
--- a/systemtests/pom.xml
+++ b/systemtests/pom.xml
@@ -5,7 +5,7 @@
     <parent>
         <groupId>io.enmasse</groupId>
         <artifactId>enmasse</artifactId>
-        <version>0.29-SNAPSHOT</version>
+        <version>0.30-SNAPSHOT</version>
     </parent>
     <modelVersion>4.0.0</modelVersion>
     <artifactId>systemtests</artifactId>
diff --git a/systemtests/src/main/java/io/enmasse/systemtest/AdminResourcesManager.java b/systemtests/src/main/java/io/enmasse/systemtest/AdminResourcesManager.java
index b4f1586f8..a7f5670b5 100644
--- a/systemtests/src/main/java/io/enmasse/systemtest/AdminResourcesManager.java
+++ b/systemtests/src/main/java/io/enmasse/systemtest/AdminResourcesManager.java
@@ -4,7 +4,12 @@
  */
 package io.enmasse.systemtest;
 
-import io.enmasse.admin.model.v1.*;
+import io.enmasse.admin.model.v1.AddressPlan;
+import io.enmasse.admin.model.v1.AddressSpacePlan;
+import io.enmasse.admin.model.v1.AuthenticationService;
+import io.enmasse.admin.model.v1.BrokeredInfraConfig;
+import io.enmasse.admin.model.v1.InfraConfig;
+import io.enmasse.admin.model.v1.StandardInfraConfig;
 import io.enmasse.systemtest.utils.TestUtils;
 import io.fabric8.kubernetes.api.model.Pod;
 import org.slf4j.Logger;
@@ -18,14 +23,16 @@ import java.util.stream.Collectors;
 
 public class AdminResourcesManager {
 
-    private static Logger log = CustomLogger.getLogger();
+    private static AdminResourcesManager managerInstance = null;
+    private static Logger LOGGER;
     private ArrayList<AddressPlan> addressPlans;
     private ArrayList<AddressSpacePlan> addressSpacePlans;
     private ArrayList<StandardInfraConfig> standardInfraConfigs;
     private ArrayList<BrokeredInfraConfig> brokeredInfraConfigs;
     private ArrayList<AuthenticationService> authServices;
 
-    public void setUp() {
+    private AdminResourcesManager() {
+        LOGGER = CustomLogger.getLogger();
         addressPlans = new ArrayList<>();
         addressSpacePlans = new ArrayList<>();
         standardInfraConfigs = new ArrayList<>();
@@ -33,37 +40,50 @@ public class AdminResourcesManager {
         authServices = new ArrayList<>();
     }
 
+    //------------------------------------------------------------------------------------------------
+    // Singleton handling
+    //------------------------------------------------------------------------------------------------
+
+
+    public static synchronized AdminResourcesManager getInstance() {
+        if (managerInstance == null) {
+            managerInstance = new AdminResourcesManager();
+        }
+        return managerInstance;
+    }
+
     public void tearDown() throws Exception {
         if (!Environment.getInstance().skipCleanup()) {
             for (AddressSpacePlan addressSpacePlan : addressSpacePlans) {
                 Kubernetes.getInstance().getAddressSpacePlanClient().withName(addressSpacePlan.getMetadata().getName()).cascading(true).delete();
-                log.info("AddressSpace plan {} deleted", addressSpacePlan.getMetadata().getName());
+                LOGGER.info("AddressSpace plan {} deleted", addressSpacePlan.getMetadata().getName());
             }
 
             for (AddressPlan addressPlan : addressPlans) {
                 Kubernetes.getInstance().getAddressPlanClient().withName(addressPlan.getMetadata().getName()).cascading(true).delete();
-                log.info("Address plan {} deleted", addressPlan.getMetadata().getName());
+                LOGGER.info("Address plan {} deleted", addressPlan.getMetadata().getName());
             }
 
             for (StandardInfraConfig infraConfigDefinition : standardInfraConfigs) {
                 Kubernetes.getInstance().getStandardInfraConfigClient().withName(infraConfigDefinition.getMetadata().getName()).cascading(true).delete();
-                log.info("Standardinfraconfig {} deleted", infraConfigDefinition.getMetadata().getName());
+                LOGGER.info("Standardinfraconfig {} deleted", infraConfigDefinition.getMetadata().getName());
             }
 
             for (BrokeredInfraConfig infraConfigDefinition : brokeredInfraConfigs) {
                 Kubernetes.getInstance().getBrokeredInfraConfigClient().withName(infraConfigDefinition.getMetadata().getName()).cascading(true).delete();
-                log.info("Brokeredinfraconfig {} deleted", infraConfigDefinition.getMetadata().getName());
+                LOGGER.info("Brokeredinfraconfig {} deleted", infraConfigDefinition.getMetadata().getName());
             }
 
             for (AuthenticationService authService : authServices) {
                 Kubernetes.getInstance().getAuthenticationServiceClient().withName(authService.getMetadata().getName()).cascading(true).delete();
                 TestUtils.waitForNReplicas(0, false, Map.of("name", authService.getMetadata().getName()), Collections.emptyMap(), new TimeoutBudget(1, TimeUnit.MINUTES), 5000);
-                log.info("AuthService {} deleted", authService.getMetadata().getName());
+                LOGGER.info("AuthService {} deleted", authService.getMetadata().getName());
             }
 
             addressPlans.clear();
             addressSpacePlans.clear();
         }
+
     }
 
     //------------------------------------------------------------------------------------------------
@@ -75,7 +95,7 @@ public class AdminResourcesManager {
     }
 
     public void createAddressPlan(AddressPlan addressPlan, boolean replaceExisting) throws Exception {
-        log.info("Address plan {} will be created {}", addressPlan.getMetadata().getName(), addressPlan);
+        LOGGER.info("Address plan {} will be created {}", addressPlan.getMetadata().getName(), addressPlan);
         var client = Kubernetes.getInstance().getAddressPlanClient();
         if (replaceExisting) {
             client.createOrReplace(addressPlan);
@@ -108,7 +128,7 @@ public class AdminResourcesManager {
     }
 
     public void createAddressSpacePlan(AddressSpacePlan addressSpacePlan, boolean replaceExisting) throws Exception {
-        log.info("AddressSpace plan {} will be created {}", addressSpacePlan.getMetadata().getName(), addressSpacePlan);
+        LOGGER.info("AddressSpace plan {} will be created {}", addressSpacePlan.getMetadata().getName(), addressSpacePlan);
         var client = Kubernetes.getInstance().getAddressSpacePlanClient();
         if (replaceExisting) {
             client.createOrReplace(addressSpacePlan);
@@ -141,7 +161,7 @@ public class AdminResourcesManager {
     }
 
     public void createInfraConfig(InfraConfig infraConfigDefinition) throws Exception {
-        log.info("InfraConfig {} will be created {}", infraConfigDefinition.getMetadata().getName(), infraConfigDefinition);
+        LOGGER.info("InfraConfig {} will be created {}", infraConfigDefinition.getMetadata().getName(), infraConfigDefinition);
         if (infraConfigDefinition instanceof StandardInfraConfig) {
             var client = Kubernetes.getInstance().getStandardInfraConfigClient();
             client.createOrReplace((StandardInfraConfig) infraConfigDefinition);
@@ -179,7 +199,7 @@ public class AdminResourcesManager {
     }
 
     public void createAuthService(AuthenticationService authenticationService, boolean replaceExisting) throws Exception {
-        log.info("AuthService {} will be created {}", authenticationService.getMetadata().getName(), authenticationService);
+        LOGGER.info("AuthService {} will be created {}", authenticationService.getMetadata().getName(), authenticationService);
         var client = Kubernetes.getInstance().getAuthenticationServiceClient();
         if (replaceExisting) {
             client.createOrReplace(authenticationService);
@@ -194,7 +214,7 @@ public class AdminResourcesManager {
                             pod.getMetadata().getName().contains(desiredPodName)).count();
                     if (matching != 1) {
                         List<String> podNames = pods.stream().map(p -> p.getMetadata().getName()).collect(Collectors.toList());
-                        log.info("Still awaiting pod with name : {}, matching : {}, current pods  {}",
+                        LOGGER.info("Still awaiting pod with name : {}, matching : {}, current pods  {}",
                                 desiredPodName, matching, podNames);
                     }
 
@@ -211,4 +231,5 @@ public class AdminResourcesManager {
                                 pod.getMetadata().getName().contains(authService.getMetadata().getName())),
                 new TimeoutBudget(1, TimeUnit.MINUTES));
     }
+
 }
diff --git a/systemtests/src/main/java/io/enmasse/systemtest/iot/CredentialsRegistryClient.java b/systemtests/src/main/java/io/enmasse/systemtest/iot/CredentialsRegistryClient.java
index a10998322..50c3491de 100644
--- a/systemtests/src/main/java/io/enmasse/systemtest/iot/CredentialsRegistryClient.java
+++ b/systemtests/src/main/java/io/enmasse/systemtest/iot/CredentialsRegistryClient.java
@@ -65,20 +65,6 @@ public class CredentialsRegistryClient extends ApiClient {
         responsePromise.get(150000, TimeUnit.SECONDS);
     }
 
-    public JsonObject getCredentials(String tenantId, String deviceId) throws Exception {
-        return getCredentials(tenantId, deviceId, HttpURLConnection.HTTP_OK);
-    }
-
-    public JsonObject getCredentials(String tenantId, String deviceId, int expectedCode) throws Exception {
-        CompletableFuture<JsonObject> responsePromise = new CompletableFuture<>();
-        var requestPath = String.format("/%s/%s/%s", CREDENTIALS_PATH, tenantId, deviceId);
-        log.info("GET-credentials: path {};", requestPath);
-        client.get(endpoint.getPort(), endpoint.getHost(), requestPath)
-            .as(BodyCodec.jsonObject())
-            .send(ar -> responseHandler(ar, responsePromise, expectedCode, "Error getting credentials of device", false));
-        return responsePromise.get(150000, TimeUnit.SECONDS);
-    }
-
     public void updateCredentials(String tenantId, String deviceId, String authId, String password, Instant notAfter) throws Exception {
         CompletableFuture<JsonObject> responsePromise = new CompletableFuture<>();
         var requestPath = String.format("/%s/%s/%s/%s", CREDENTIALS_PATH, tenantId, authId, "hashed-password");
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/bases/TestBase.java b/systemtests/src/test/java/io/enmasse/systemtest/bases/TestBase.java
index 49bf6a200..f1f0ee07e 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/bases/TestBase.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/bases/TestBase.java
@@ -12,6 +12,7 @@ import io.enmasse.address.model.AddressSpace;
 import io.enmasse.address.model.AddressSpaceSchemaList;
 import io.enmasse.systemtest.AddressSpaceType;
 import io.enmasse.systemtest.AddressType;
+import io.enmasse.systemtest.AdminResourcesManager;
 import io.enmasse.systemtest.BrokerManagement;
 import io.enmasse.systemtest.CustomLogger;
 import io.enmasse.systemtest.DestinationPlan;
@@ -120,6 +121,26 @@ public abstract class TestBase implements ITestBase, ITestSeparator {
     private List<AddressSpace> addressSpaceList = new ArrayList<>();
     private boolean reuseAddressSpace;
 
+    protected static void simpleMQTTSendReceive(Address dest, IMqttClient client, int msgCount) throws Exception {
+        List<MqttMessage> messages = IntStream.range(0, msgCount).boxed().map(i -> {
+            MqttMessage m = new MqttMessage();
+            m.setPayload(String.format("mqtt-simple-send-receive-%s", i).getBytes(StandardCharsets.UTF_8));
+            m.setQos(1);
+            return m;
+        }).collect(Collectors.toList());
+
+        List<CompletableFuture<MqttMessage>> receiveFutures = MqttUtils.subscribeAndReceiveMessages(client, dest.getSpec().getAddress(), messages.size(), 1);
+        List<CompletableFuture<Void>> publishFutures = MqttUtils.publish(client, dest.getSpec().getAddress(), messages);
+
+        int publishCount = MqttUtils.awaitAndReturnCode(publishFutures, 1, TimeUnit.MINUTES);
+        assertThat("Incorrect count of messages published",
+                publishCount, is(messages.size()));
+
+        int receivedCount = MqttUtils.awaitAndReturnCode(receiveFutures, 1, TimeUnit.MINUTES);
+        assertThat("Incorrect count of messages received",
+                receivedCount, is(messages.size()));
+    }
+
     @BeforeEach
     public void setup() throws Exception {
         if (!reuseAddressSpace) {
@@ -134,6 +155,7 @@ public abstract class TestBase implements ITestBase, ITestSeparator {
         try {
             if (!environment.skipCleanup() && !reuseAddressSpace) {
                 deleteAddressspacesFromList();
+                AdminResourcesManager.getInstance().tearDown();
             } else {
                 log.warn("Remove address spaces in tear down - SKIPPED!");
             }
@@ -145,7 +167,7 @@ public abstract class TestBase implements ITestBase, ITestSeparator {
     }
 
     @AfterEach
-    public void closeMqttClient () {
+    public void closeMqttClient() {
         if (mqttClientFactory != null) {
             mqttClientFactory.close();
             mqttClientFactory = null;
@@ -165,15 +187,15 @@ public abstract class TestBase implements ITestBase, ITestSeparator {
         reuseAddressSpace = true;
     }
 
-    protected void unsetReuseAddressSpace() {
-        reuseAddressSpace = false;
-    }
-
 
     //================================================================================================
     //==================================== AddressSpace methods ======================================
     //================================================================================================
 
+    protected void unsetReuseAddressSpace() {
+        reuseAddressSpace = false;
+    }
+
     protected void createAddressSpaceList(AddressSpace... addressSpaces) throws Exception {
         String operationID = TimeMeasuringSystem.startOperation(SystemtestsOperation.CREATE_ADDRESS_SPACE);
         ArrayList<AddressSpace> spaces = new ArrayList<>();
@@ -289,14 +311,14 @@ public abstract class TestBase implements ITestBase, ITestSeparator {
         return kubernetes.getAddressSpaceClient().withName(addressSpaceName).get();
     }
 
-    protected AddressSpace getAddressSpace(String namespace, String addressSpaceName) {
-        return kubernetes.getAddressSpaceClient(namespace).withName(addressSpaceName).get();
-    }
-
     //================================================================================================
     //====================================== Address methods =========================================
     //================================================================================================
 
+    protected AddressSpace getAddressSpace(String namespace, String addressSpaceName) {
+        return kubernetes.getAddressSpaceClient(namespace).withName(addressSpaceName).get();
+    }
+
     protected void deleteAddresses(Address... destinations) throws Exception {
         logCollector.collectConfigMaps();
         logCollector.collectRouterState("deleteAddresses");
@@ -334,14 +356,14 @@ public abstract class TestBase implements ITestBase, ITestSeparator {
         AddressUtils.setAddresses(budget, true, addresses);
     }
 
-    protected void replaceAddress(Address destination) throws Exception {
-        AddressUtils.replaceAddress(destination, true, new TimeoutBudget(3, TimeUnit.MINUTES));
-    }
-
     //================================================================================================
     //======================================= User methods ===========================================
     //================================================================================================
 
+    protected void replaceAddress(Address destination) throws Exception {
+        AddressUtils.replaceAddress(destination, true, new TimeoutBudget(3, TimeUnit.MINUTES));
+    }
+
     protected User createOrUpdateUser(AddressSpace addressSpace, UserCredentials credentials) {
         User user = new UserBuilder()
                 .withNewMetadata()
@@ -420,14 +442,14 @@ public abstract class TestBase implements ITestBase, ITestSeparator {
         return null;
     }
 
-    protected boolean userExist(AddressSpace addressSpace, String username) {
-        return getUser(addressSpace, username) != null;
-    }
-
     //================================================================================================
     //======================================= Help methods ===========================================
     //================================================================================================
 
+    protected boolean userExist(AddressSpace addressSpace, String username) {
+        return getUser(addressSpace, username) != null;
+    }
+
     /**
      * give you a schema object
      *
@@ -985,8 +1007,9 @@ public abstract class TestBase implements ITestBase, ITestSeparator {
 
     protected void logWithSeparator(Logger logger, String... messages) {
         logger.info("--------------------------------------------------------------------------------");
-        for (String message : messages)
+        for (String message : messages) {
             logger.info(message);
+        }
     }
 
     /**
@@ -1198,26 +1221,6 @@ public abstract class TestBase implements ITestBase, ITestSeparator {
         }
     }
 
-    protected static void simpleMQTTSendReceive(Address dest, IMqttClient client, int msgCount) throws Exception {
-        List<MqttMessage> messages = IntStream.range(0, msgCount).boxed().map(i -> {
-            MqttMessage m = new MqttMessage();
-            m.setPayload(String.format("mqtt-simple-send-receive-%s", i).getBytes(StandardCharsets.UTF_8));
-            m.setQos(1);
-            return m;
-        }).collect(Collectors.toList());
-
-        List<CompletableFuture<MqttMessage>> receiveFutures = MqttUtils.subscribeAndReceiveMessages(client, dest.getSpec().getAddress(), messages.size(), 1);
-        List<CompletableFuture<Void>> publishFutures = MqttUtils.publish(client, dest.getSpec().getAddress(), messages);
-
-        int publishCount = MqttUtils.awaitAndReturnCode(publishFutures, 1, TimeUnit.MINUTES);
-        assertThat("Incorrect count of messages published",
-                publishCount, is(messages.size()));
-
-        int receivedCount = MqttUtils.awaitAndReturnCode(receiveFutures, 1, TimeUnit.MINUTES);
-        assertThat("Incorrect count of messages received",
-                receivedCount, is(messages.size()));
-    }
-
     protected List<String> extractBodyAsString(Future<List<Message>> msgs) throws Exception {
         return msgs.get(1, TimeUnit.MINUTES).stream().map(m -> (String) ((AmqpValue) m.getBody()).getValue()).collect(Collectors.toList());
     }
@@ -1235,18 +1238,20 @@ public abstract class TestBase implements ITestBase, ITestSeparator {
 
     protected <T extends Comparable<T>> void assertSorted(String message, Iterable<T> list, boolean reverse) {
         log.info("Assert sort reverse: " + reverse);
-        if (!reverse)
+        if (!reverse) {
             assertTrue(Ordering.natural().isOrdered(list), message);
-        else
+        } else {
             assertTrue(Ordering.natural().reverse().isOrdered(list), message);
+        }
     }
 
     protected <T> void assertSorted(String message, Iterable<T> list, boolean reverse, Comparator<T> comparator) {
         log.info("Assert sort reverse: " + reverse);
-        if (!reverse)
+        if (!reverse) {
             assertTrue(Ordering.from(comparator).isOrdered(list), message);
-        else
+        } else {
             assertTrue(Ordering.from(comparator).reverse().isOrdered(list), message);
+        }
     }
 
     protected void assertWaitForValue(int expected, Callable<Integer> fn, TimeoutBudget budget) throws Exception {
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/bases/infra/InfraTestBase.java b/systemtests/src/test/java/io/enmasse/systemtest/bases/infra/InfraTestBase.java
index 6a192fe11..a8b17ac97 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/bases/infra/InfraTestBase.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/bases/infra/InfraTestBase.java
@@ -7,8 +7,8 @@ package io.enmasse.systemtest.bases.infra;
 import io.enmasse.address.model.AddressSpace;
 import io.enmasse.admin.model.v1.AddressPlan;
 import io.enmasse.admin.model.v1.InfraConfig;
-import io.enmasse.systemtest.CustomLogger;
 import io.enmasse.systemtest.AdminResourcesManager;
+import io.enmasse.systemtest.CustomLogger;
 import io.enmasse.systemtest.TimeoutBudget;
 import io.enmasse.systemtest.ability.ITestBase;
 import io.enmasse.systemtest.bases.TestBase;
@@ -16,7 +16,6 @@ import io.enmasse.systemtest.utils.TestUtils;
 import io.fabric8.kubernetes.api.model.*;
 import io.fabric8.kubernetes.api.model.storage.StorageClass;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
 import org.opentest4j.AssertionFailedError;
 import org.slf4j.Logger;
 
@@ -37,22 +36,12 @@ public abstract class InfraTestBase extends TestBase implements ITestBase {
             "kubernetes.io/azure-file", "kubernetes.io/azure-disk", "kubernetes.io/glusterfs", "kubernetes.io/cinder",
             "kubernetes.io/portworx-volume", "kubernetes.io/rbd");
 
-    protected static final AdminResourcesManager adminManager = new AdminResourcesManager();
+    protected static final AdminResourcesManager adminManager = AdminResourcesManager.getInstance();
 
     protected InfraConfig testInfra;
     protected AddressPlan exampleAddressPlan;
     protected AddressSpace exampleAddressSpace;
 
-    @BeforeEach
-    void setUp() throws Exception {
-        adminManager.setUp();
-    }
-
-    @AfterEach
-    void tearDown() throws Exception {
-        adminManager.tearDown();
-    }
-
     protected void assertBroker(String brokerMemory, String brokerStorage, PodTemplateSpec templateSpec) {
         log.info("Checking broker infra");
         List<Pod> brokerPods = TestUtils.listBrokerPods(kubernetes, exampleAddressSpace);
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/bases/web/GlobalConsoleTest.java b/systemtests/src/test/java/io/enmasse/systemtest/bases/web/GlobalConsoleTest.java
index beaaebfc0..a9655ec36 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/bases/web/GlobalConsoleTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/bases/web/GlobalConsoleTest.java
@@ -23,7 +23,6 @@ import io.enmasse.systemtest.utils.AddressSpaceUtils;
 import io.enmasse.systemtest.utils.AuthServiceUtils;
 import io.enmasse.systemtest.utils.TestUtils;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
 import org.slf4j.Logger;
 
 import java.util.Optional;
@@ -36,17 +35,7 @@ public abstract class GlobalConsoleTest extends TestBase {
 
     private static Logger log = CustomLogger.getLogger();
     private GlobalConsolePage globalConsolePage;
-    private static final AdminResourcesManager adminManager = new AdminResourcesManager();
-
-    @BeforeEach
-    void setUpAdminManager() {
-        adminManager.setUp();
-    }
-
-    @AfterEach
-    public void tearDown() throws Exception {
-        adminManager.tearDown();
-    }
+    private static final AdminResourcesManager adminManager = AdminResourcesManager.getInstance();
 
     //============================================================================================
     //============================ do test methods ===============================================
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/bases/web/WebConsolePlansTest.java b/systemtests/src/test/java/io/enmasse/systemtest/bases/web/WebConsolePlansTest.java
index c5be23e82..1d1f6760c 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/bases/web/WebConsolePlansTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/bases/web/WebConsolePlansTest.java
@@ -27,7 +27,6 @@ import io.enmasse.systemtest.standard.TopicTest;
 import io.enmasse.systemtest.utils.AddressUtils;
 import io.enmasse.systemtest.utils.PlanUtils;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Tag;
 
 import java.util.Arrays;
@@ -39,19 +38,14 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 @Tag(isolated)
 public abstract class WebConsolePlansTest extends TestBase {
     SeleniumProvider selenium = SeleniumProvider.getInstance();
-    private static final AdminResourcesManager adminManager = new AdminResourcesManager();
+    private static final AdminResourcesManager adminManager = AdminResourcesManager.getInstance();
 
     private ConsoleWebPage consoleWebPage;
 
-    @BeforeEach
-    public void setUpWebConsoleTests() throws Exception {
-        adminManager.setUp();
-    }
 
     @AfterEach
     public void tearDownDrivers() throws Exception {
         selenium.tearDownDrivers();
-        adminManager.tearDown();
     }
 
     //============================================================================================
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/common/api/ApiServerTest.java b/systemtests/src/test/java/io/enmasse/systemtest/common/api/ApiServerTest.java
index e94d95512..c36a4cd89 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/common/api/ApiServerTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/common/api/ApiServerTest.java
@@ -37,17 +37,7 @@ import static org.junit.jupiter.api.Assertions.*;
 @Tag(isolated)
 public class ApiServerTest extends TestBase {
     private static Logger log = CustomLogger.getLogger();
-    private static final AdminResourcesManager adminManager = new AdminResourcesManager();
-
-    @BeforeEach
-    void setUp() {
-        adminManager.setUp();
-    }
-
-    @AfterEach
-    void tearDown() throws Exception {
-        adminManager.tearDown();
-    }
+    private static final AdminResourcesManager adminManager = AdminResourcesManager.getInstance();
 
     @Test
     void testRestApiGetSchema() throws Exception {
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/common/api/AuthServiceTest.java b/systemtests/src/test/java/io/enmasse/systemtest/common/api/AuthServiceTest.java
index 4f079e1e2..62dbd1b6f 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/common/api/AuthServiceTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/common/api/AuthServiceTest.java
@@ -26,16 +26,10 @@ import static io.enmasse.systemtest.TestTag.isolated;
 class AuthServiceTest extends TestBase {
 
     private static Logger log = CustomLogger.getLogger();
-    private static final AdminResourcesManager adminManager = new AdminResourcesManager();
-
-    @BeforeEach
-    void setUp() throws Exception {
-        adminManager.setUp();
-    }
+    private static final AdminResourcesManager adminManager = AdminResourcesManager.getInstance();
 
     @AfterEach
     void tearDown() throws Exception {
-        adminManager.tearDown();
         SystemtestsKubernetesApps.deletePostgresDB(kubernetes.getInfraNamespace());
     }
 
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/common/plans/PlansTest.java b/systemtests/src/test/java/io/enmasse/systemtest/common/plans/PlansTest.java
index 330b11c9c..b986936aa 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/common/plans/PlansTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/common/plans/PlansTest.java
@@ -45,17 +45,7 @@ import static org.junit.jupiter.api.Assertions.*;
 class PlansTest extends TestBase {
     SeleniumProvider selenium = SeleniumProvider.getInstance();
     private static Logger log = CustomLogger.getLogger();
-    private static final AdminResourcesManager adminManager = new AdminResourcesManager();
-
-    @BeforeEach
-    void setUpAdminManager() {
-        adminManager.setUp();
-    }
-
-    @AfterEach
-    void tearDown() throws Exception {
-        adminManager.tearDown();
-    }
+    private static final AdminResourcesManager adminManager = AdminResourcesManager.getInstance();
 
     @Test
     void testCreateAddressSpacePlan() throws Exception {
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/iot/MultipleProjectsTest.java b/systemtests/src/test/java/io/enmasse/systemtest/iot/MultipleProjectsTest.java
index e150271f3..7a5e5c609 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/iot/MultipleProjectsTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/iot/MultipleProjectsTest.java
@@ -241,7 +241,6 @@ public class MultipleProjectsTest extends IoTTestBase implements ITestBaseStanda
         String tenant = tenantId(ctx.getProject());
         String deviceId = ctx.getDeviceId();
         credentialsClient.deleteAllCredentials(tenant, deviceId);
-        credentialsClient.getCredentials(tenant, deviceId, HttpURLConnection.HTTP_NOT_FOUND);
         registryClient.deleteDeviceRegistration(tenant, deviceId);
         registryClient.getDeviceRegistration(tenant, deviceId, HttpURLConnection.HTTP_NOT_FOUND);
         ctx.getHttpAdapterClient().close();
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/iot/http/HttpAdapterTest.java b/systemtests/src/test/java/io/enmasse/systemtest/iot/http/HttpAdapterTest.java
index 505a718fd..2c1592939 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/iot/http/HttpAdapterTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/iot/http/HttpAdapterTest.java
@@ -93,7 +93,6 @@ public class HttpAdapterTest extends IoTTestBaseWithShared {
         }
         if (credentialsClient != null) {
             credentialsClient.deleteAllCredentials(tenantId(), deviceId);
-            credentialsClient.getCredentials(tenantId(), deviceId, HttpURLConnection.HTTP_NOT_FOUND);
         }
         if (registryClient != null) {
             registryClient.deleteDeviceRegistration(tenantId(), deviceId);
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/iot/mqtt/MqttAdapterTest.java b/systemtests/src/test/java/io/enmasse/systemtest/iot/mqtt/MqttAdapterTest.java
index 258501bbe..39b6eb775 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/iot/mqtt/MqttAdapterTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/iot/mqtt/MqttAdapterTest.java
@@ -134,7 +134,6 @@ public class MqttAdapterTest extends IoTTestBaseWithShared {
             logCollector.collectMqttAdapterQdrProxyState();
         }
         credentialsClient.deleteAllCredentials(tenantId(), deviceId);
-        credentialsClient.getCredentials(tenantId(), deviceId, HttpURLConnection.HTTP_NOT_FOUND);
         registryClient.deleteDeviceRegistration(tenantId(), deviceId);
         registryClient.getDeviceRegistration(tenantId(), deviceId, HttpURLConnection.HTTP_NOT_FOUND);
         if (adapterClient.isConnected()) {
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/iot/registry/DeviceRegistryTestBase.java b/systemtests/src/test/java/io/enmasse/systemtest/iot/registry/DeviceRegistryTestBase.java
index 0f2d9452f..11c7fa0bc 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/iot/registry/DeviceRegistryTestBase.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/iot/registry/DeviceRegistryTestBase.java
@@ -42,7 +42,6 @@ import io.enmasse.systemtest.iot.MessageSendTester;
 import io.enmasse.systemtest.iot.MessageSendTester.ConsumerFactory;
 import io.enmasse.systemtest.iot.MessageSendTester.Type;
 import io.enmasse.systemtest.utils.IoTUtils;
-import io.vertx.core.json.JsonArray;
 import io.vertx.core.json.JsonObject;
 
 @Tag(sharedIot)
@@ -202,23 +201,9 @@ public abstract class DeviceRegistryTestBase extends IoTTestBase {
             String password = "password1234";
             credentialsClient.addCredentials(tenantId(), randomDeviceId, authId, password);
 
-            JsonObject result = credentialsClient.getCredentials(tenantId(), randomDeviceId);
-            assertNotNull(result);
-            assertEquals(1, result.getInteger("total"));
-            JsonArray credentials = result.getJsonArray("credentials");
-            assertNotNull(credentials);
-            assertEquals(1, credentials.size());
-            JsonObject credential = credentials.getJsonObject(0);
-            assertNotNull(credential);
-            assertEquals(randomDeviceId, credential.getString("device-id"));
-            assertEquals(authId, credential.getString("auth-id"));
-            assertDefaultEnabled(credential);
-            //TODO chech secret[0].pwd-hash matches "password1234" hash, waiting for issue #2569 to be resolved
-
             checkCredentials(authId, password, false);
 
             credentialsClient.deleteAllCredentials(tenantId(), randomDeviceId);
-            credentialsClient.getCredentials(tenantId(), randomDeviceId, HttpURLConnection.HTTP_NOT_FOUND);
 
             client.deleteDeviceRegistration(tenantId(), randomDeviceId);
             client.getDeviceRegistration(tenantId(), randomDeviceId, HttpURLConnection.HTTP_NOT_FOUND);
@@ -250,23 +235,6 @@ public abstract class DeviceRegistryTestBase extends IoTTestBase {
             final String newPassword = "new-password1234";
             credentialsClient.updateCredentials(tenantId(), randomDeviceId, authId, newPassword, null);
 
-            JsonObject result = credentialsClient.getCredentials(tenantId(), randomDeviceId);
-            assertNotNull(result);
-            assertEquals(1, result.getInteger("total"));
-            JsonArray credentials = result.getJsonArray("credentials");
-            assertNotNull(credentials);
-            assertEquals(1, credentials.size());
-            JsonObject credential = credentials.getJsonObject(0);
-            assertNotNull(credential);
-            assertEquals(randomDeviceId, credential.getString("device-id"));
-            assertEquals(authId, credential.getString("auth-id"));
-            assertDefaultEnabled(credential);
-            JsonArray secrets = credential.getJsonArray("secrets");
-            assertNotNull(secrets);
-            assertEquals(1, secrets.size());
-            JsonObject secret = secrets.getJsonObject(0);
-            assertNotNull(secret);
-
             // expect failure due to cached info
 
             checkCredentials(authId, newPassword, true);
@@ -278,7 +246,6 @@ public abstract class DeviceRegistryTestBase extends IoTTestBase {
             checkCredentials(authId, newPassword, false);
 
             credentialsClient.deleteAllCredentials(tenantId(), randomDeviceId);
-            credentialsClient.getCredentials(tenantId(), randomDeviceId, HttpURLConnection.HTTP_NOT_FOUND);
 
             client.deleteDeviceRegistration(tenantId(), randomDeviceId);
             client.getDeviceRegistration(tenantId(), randomDeviceId, HttpURLConnection.HTTP_NOT_FOUND);
@@ -297,25 +264,6 @@ public abstract class DeviceRegistryTestBase extends IoTTestBase {
 
             credentialsClient.addCredentials(tenantId(), randomDeviceId, authId, newPassword, notAfter);
 
-            JsonObject result = credentialsClient.getCredentials(tenantId(), randomDeviceId);
-            assertNotNull(result);
-            assertEquals(1, result.getInteger("total"));
-            JsonArray credentials = result.getJsonArray("credentials");
-            assertNotNull(credentials);
-            assertEquals(1, credentials.size());
-            JsonObject credential = credentials.getJsonObject(0);
-            assertNotNull(credential);
-            assertEquals(randomDeviceId, credential.getString("device-id"));
-            assertEquals(authId, credential.getString("auth-id"));
-            assertDefaultEnabled(credential);
-            JsonArray secrets = credential.getJsonArray("secrets");
-            assertNotNull(secrets);
-            assertEquals(1, secrets.size());
-            JsonObject secret = secrets.getJsonObject(0);
-            assertNotNull(secret);
-            Instant actualNotAfter = secret.getInstant("not-after");
-            assertEquals(notAfter, actualNotAfter);
-
             // first check, must succeed
 
             checkCredentials(authId, newPassword, false);
@@ -328,7 +276,6 @@ public abstract class DeviceRegistryTestBase extends IoTTestBase {
             checkCredentials(authId, newPassword, true);
 
             credentialsClient.deleteAllCredentials(tenantId(), randomDeviceId);
-            credentialsClient.getCredentials(tenantId(), randomDeviceId, HttpURLConnection.HTTP_NOT_FOUND);
 
             client.deleteDeviceRegistration(tenantId(), randomDeviceId);
             client.getDeviceRegistration(tenantId(), randomDeviceId, HttpURLConnection.HTTP_NOT_FOUND);
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/marathon/PlansMarathonTest.java b/systemtests/src/test/java/io/enmasse/systemtest/marathon/PlansMarathonTest.java
index 5cf61c26d..b19e0043f 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/marathon/PlansMarathonTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/marathon/PlansMarathonTest.java
@@ -21,7 +21,6 @@ import io.enmasse.systemtest.standard.QueueTest;
 import io.enmasse.systemtest.utils.AddressUtils;
 import io.enmasse.systemtest.utils.PlanUtils;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Test;
 
 import java.util.ArrayList;
@@ -31,20 +30,12 @@ import java.util.List;
 
 class PlansMarathonTest extends MarathonTestBase {
 
-    private static final AdminResourcesManager adminManager = new AdminResourcesManager();
-
-    @BeforeEach
-    void setUp() {
-        adminManager.setUp();
-    }
+    private static final AdminResourcesManager adminManager = AdminResourcesManager.getInstance();
 
     @AfterEach
     void tearDown() throws Exception {
         logCollector.collectRouterState("planMarathonTearDown");
         logCollector.collectConfigMaps("plansMarathonTearDown");
-        if (!environment.skipCleanup()) {
-            adminManager.tearDown();
-        }
     }
 
     @Test
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/standard/PlansTest.java b/systemtests/src/test/java/io/enmasse/systemtest/standard/PlansTest.java
index 659bfac10..cd6239c3d 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/standard/PlansTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/standard/PlansTest.java
@@ -17,7 +17,6 @@ import io.enmasse.systemtest.bases.TestBaseWithShared;
 import io.enmasse.systemtest.utils.AddressUtils;
 import io.enmasse.systemtest.utils.PlanUtils;
 import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
 import org.junit.jupiter.api.Disabled;
 import org.junit.jupiter.api.Test;
 import java.util.ArrayList;
@@ -29,17 +28,7 @@ import static org.hamcrest.MatcherAssert.assertThat;
 
 class PlansTest extends TestBaseWithShared implements ITestBaseStandard {
 
-    private static final AdminResourcesManager adminManager = new AdminResourcesManager();
-
-    @BeforeEach
-    void setUp() {
-        adminManager.setUp();
-    }
-
-    @AfterEach
-    void tearDown() throws Exception {
-        adminManager.tearDown();
-    }
+    private static final AdminResourcesManager adminManager = AdminResourcesManager.getInstance();
 
     @Test
     @Disabled("test disabled because feature for appending address-plan is not implemented yet, issue: #904")
diff --git a/systemtests/src/test/java/io/enmasse/systemtest/standard/QueueTest.java b/systemtests/src/test/java/io/enmasse/systemtest/standard/QueueTest.java
index 69b62d414..a7b956c42 100644
--- a/systemtests/src/test/java/io/enmasse/systemtest/standard/QueueTest.java
+++ b/systemtests/src/test/java/io/enmasse/systemtest/standard/QueueTest.java
@@ -58,7 +58,7 @@ public class QueueTest extends TestBaseWithShared implements ITestBaseStandard {
         assertNotNull(numSent, "Sending messages didn't start");
         int actual = 0;
         try {
-            actual = numSent.get(1, TimeUnit.MINUTES);
+            actual = numSent.get(90, TimeUnit.SECONDS);
         } catch (TimeoutException t) {
             logCollector.collectRouterState("runQueueTestSend");
             fail("Sending messages timed out after sending " + predicate.actual());
@@ -69,7 +69,7 @@ public class QueueTest extends TestBaseWithShared implements ITestBaseStandard {
         Future<List<Message>> received = client.recvMessages(dest.getSpec().getAddress(), predicate);
         actual = 0;
         try {
-            actual = received.get(1, TimeUnit.MINUTES).size();
+            actual = received.get(90, TimeUnit.SECONDS).size();
         } catch (TimeoutException t) {
             logCollector.collectRouterState("runQueueTestRecv");
             fail("Receiving messages timed out after " + predicate.actual() + " msgs received");