You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2020/02/11 21:47:07 UTC

[celix] branch develop updated: Feature/gh 142 rsa issues (#153)

This is an automated email from the ASF dual-hosted git repository.

pnoltes pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/celix.git


The following commit(s) were added to refs/heads/develop by this push:
     new 16235c3  Feature/gh 142 rsa issues (#153)
16235c3 is described below

commit 16235c321f081ffc67bf86ceb8667891d6d36f69
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Tue Feb 11 22:46:58 2020 +0100

    Feature/gh 142 rsa issues (#153)
    
    Fixes several issues for remote services
    
    * gh-142: Refactors RSA tests and adds an additional remote service example for testing
    * gh-142: Adds test for ffi and string as input argument handling.
    * gh-142: Fixes some issue with remote calls and string input/output.
    * gh-142: Extends remote services test for string, const string, enums and complex types and fixes several issues in remote services
    * gh-142: Replace mutex with rw lock in rsa to support handling multiple calls and adds missing test for libdfi
    * #142: Fixes a memory leak in handling pre allocated output arguments for remote services
    * #142: Fixes an issue in remote service etcd for configuring the ttl.
    * #142: Refactors remote calculator client to use celix_ api.
---
 .travis.yml                                        |   2 +-
 CMakeLists.txt                                     |   8 +-
 .../pubsub_discovery/src/pubsub_discovery_impl.c   |   2 +-
 .../src/endpoint_discovery_server.c                |   2 +-
 .../discovery_etcd/src/discovery_impl.c            |  12 +-
 .../discovery_etcd/src/discovery_impl.h            |   7 -
 .../discovery_etcd/src/etcd_watcher.c              |  74 ++------
 .../discovery_etcd/src/etcd_watcher.h              |   7 -
 bundles/remote_services/examples/CMakeLists.txt    |   8 +-
 .../examples/calculator_api/CMakeLists.txt         |   4 +-
 .../calculator_api/include/calculator_service.h    |  17 +-
 .../org.apache.celix.calc.api.Calculator.avpr      |   0
 ...org.apache.celix.calc.api.Calculator.descriptor |   0
 .../examples/calculator_service/CMakeLists.txt     |   2 +-
 .../calculator_service/src/calculator_activator.c  |  88 +++------
 .../calculator_service/src/calculator_impl.c       |  37 ++--
 .../calculator_service/src/calculator_impl.h       |  14 +-
 .../examples/calculator_shell/CMakeLists.txt       |   2 +-
 .../examples/calculator_shell/src/add_command.c    |  92 ++++-----
 .../examples/calculator_shell/src/add_command.h    |  10 +-
 .../src/calculator_shell_activator.c               | 110 +++--------
 ...org.apache.celix.calc.api.Calculator.descriptor |  11 --
 .../examples/calculator_shell/src/sqrt_command.c   |  87 +++++----
 .../examples/calculator_shell/src/sqrt_command.h   |  10 +-
 .../examples/calculator_shell/src/sub_command.c    |  94 ++++-----
 .../examples/calculator_shell/src/sub_command.h    |  10 +-
 .../CMakeLists.txt                                 |  16 +-
 .../remote_example_api/include/remote_example.h    |  66 +++++++
 .../org.apache.celix.RemoteExample.descriptor      |  18 ++
 .../CMakeLists.txt                                 |  16 +-
 .../src/remote_example_activator.c                 |  62 ++++++
 .../src/remote_example_impl.c                      | 129 +++++++++++++
 .../src/remote_example_impl.h                      |  40 ++++
 .../src/import_registration_dfi.c                  |   2 +-
 .../src/remote_service_admin_dfi.c                 |  24 +--
 .../remote_service_admin_dfi/test/CMakeLists.txt   |  16 +-
 .../test/server.properties.in                      |   2 +-
 .../test/src/rsa_client_server_tests.cpp           | 127 ++++++-------
 .../test/src/rsa_tests.cpp                         | 153 +++++++--------
 .../test/src/run_tests.cpp                         |   1 +
 .../test/src/tst_activator.c                       | 211 +++++++++++++++++++--
 .../test/src/tst_service.h                         |  10 +-
 bundles/shell/shell/CMakeLists.txt                 |   6 +-
 bundles/shell/shell/deprecated_api/command.h       |   9 +-
 bundles/shell/shell/src/activator.c                |   2 +-
 bundles/shell/shell/src/help_command.c             |   5 +
 bundles/shell/shell/src/shell.c                    |   4 +-
 bundles/shell/shell/src/shell_private.h            |   6 +-
 bundles/shell/shell/test/CMakeLists.txt            |   4 +-
 bundles/shell/shell/test/src/shell_tests.cpp       |   2 +-
 libs/dfi/include/dyn_function.h                    |  13 ++
 libs/dfi/include/dyn_type.h                        |   2 +-
 libs/dfi/src/avrobin_serializer.c                  |   6 +
 libs/dfi/src/dyn_function.c                        |   5 +
 libs/dfi/src/dyn_type.c                            |  39 ++--
 libs/dfi/src/json_rpc.c                            |  93 +++++++--
 libs/dfi/src/json_serializer.c                     |  16 +-
 libs/dfi/test/dyn_avpr_function_tests.cpp          |  44 ++++-
 libs/dfi/test/dyn_function_tests.cpp               |  32 ++++
 libs/etcdlib/api/etcd.h                            |  30 ++-
 libs/framework/src/celix_framework_factory.c       |   2 +-
 61 files changed, 1201 insertions(+), 722 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 2980ab1..33994bd 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -88,7 +88,7 @@ before_script:
 script:
   - if [ "$SANITIZE" == 1 ]; then export BUILD_OPTIONS="${BUILD_OPTIONS} DENABLE_ADDRESS_SANITIZER=ON"; fi
   - if [ "$USE_ZIP_INSTEAD_OF_JAR" == 1 ]; then export BUILD_OPTIONS="${BUILD_OPTIONS} -DDCELIX_USE_ZIP_INSTEAD_OF_JAR=ON"; fi
-  - if [ "$ONLY_V3_API" == 1 ]; then export BUILD_OPTIONS="${BUILD_OPTIONS} -DCELIX_ADD_DEPRECATED_API=OFF"; fi
+  - if [ "$ONLY_V3_API" == 1 ]; then export BUILD_OPTIONS="${BUILD_OPTIONS} -DCELIX_INSTALL_DEPRECATED_API=OFF"; fi
   - cd build
   - if [ "$CC" = "gcc" ] && [ "$TRAVIS_OS_NAME" = "linux" ]; then export BUILD_OPTS="${BUILD_OPTS} -DENABLE_CODE_COVERAGE=ON"; fi
   - if [ "$TRAVIS_OS_NAME" = "linux" ] && [ -z "$ANDROID" ]; then cmake -DCMAKE_BUILD_TYPE=Debug ${BUILD_OPTIONS} ${BUILD_OPTIONS_LINUX} -DBUILD_FRAMEWORK_TESTS=ON -DBUILD_UTILS-TESTS=ON -DENABLE_TESTING=ON ${BUILD_OPTS} -DCMAKE_INSTALL_PREFIX=../install ..; fi
diff --git a/CMakeLists.txt b/CMakeLists.txt
index ac6681b..a887f39 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -99,7 +99,13 @@ if (ENABLE_TESTING)
     enable_testing()
 endif()
 
-option(CELIX_ADD_DEPRECATED_API "whether to use and install deprecated apis (i.e. header without a celix_ prefix." ON)
+option(CELIX_INSTALL_DEPRECATED_API "whether to install (and use) deprecated apis (i.e. header without a celix_ prefix." ON)
+
+option(CELIX_ADD_DEPRECATED_ATTRIBUTES "If enabled add deprecated attributes to deprecated services/functions." ON)
+if (CELIX_ADD_DEPRECATED_ATTRIBUTES)
+    set(CMAKE_C_FLAGS "-DCELIX_ADD_DEPRECATED_ATTRIBUTES ${CMAKE_C_FLAGS}")
+    set(CMAKE_CXX_FLAGS "-DCELIX_ADD_DEPRECATED_ATTRIBUTES ${CMAKE_CXX_FLAGS}")
+endif ()
 
 option(CELIX_ADD_OPENSSL_DEP "Enabled building Celix framework & etcdlib with OpenSSL library dependency. This can help in some libcurl resolving issues" OFF)
 set(CELIX_OPTIONAL_EXTRA_LIBS "")
diff --git a/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c b/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
index 3e9eab6..964afd9 100644
--- a/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
+++ b/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
@@ -164,7 +164,7 @@ static void psd_watchForChange(pubsub_discovery_t *disc, bool *connectedPtr, lon
         char *action = NULL;
         char *value = NULL;
         char *readKey = NULL;
-        //TODO add interruptable etcdlib_wait -> which returns a handle to interrupt and a can be used for a wait call
+        //TODO add interruptable etcdlib_watch -> which returns a handle to interrupt and a can be used for a wait call
         int rc = etcdlib_watch(disc->etcdlib, disc->pubsubPath, watchIndex, &action, NULL, &value, &readKey, mIndex);
         if (rc == ETCDLIB_RC_ERROR) {
             L_ERROR("[PSD] Communicating with etcd. rc is %i, action value is %s\n", rc, action);
diff --git a/bundles/remote_services/discovery_common/src/endpoint_discovery_server.c b/bundles/remote_services/discovery_common/src/endpoint_discovery_server.c
index 5ad8e87..ba31c9d 100644
--- a/bundles/remote_services/discovery_common/src/endpoint_discovery_server.c
+++ b/bundles/remote_services/discovery_common/src/endpoint_discovery_server.c
@@ -40,7 +40,7 @@
 
 // defines how often the webserver is restarted (with an increased port number)
 #define MAX_NUMBER_OF_RESTARTS     15
-#define DEFAULT_SERVER_THREADS "1"
+#define DEFAULT_SERVER_THREADS     "5"
 
 #define CIVETWEB_REQUEST_NOT_HANDLED 0
 #define CIVETWEB_REQUEST_HANDLED 1
diff --git a/bundles/remote_services/discovery_etcd/src/discovery_impl.c b/bundles/remote_services/discovery_etcd/src/discovery_impl.c
index f4cd825..ecde542 100644
--- a/bundles/remote_services/discovery_etcd/src/discovery_impl.c
+++ b/bundles/remote_services/discovery_etcd/src/discovery_impl.c
@@ -16,13 +16,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * discovery_impl.c
- *
- * \date        Aug 8, 2014
- * \author      <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright   Apache License, Version 2.0
- */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -31,16 +24,13 @@
 #include <netdb.h>
 #include <netinet/in.h>
 
-#include "celix_constants.h"
+
 #include "celix_threads.h"
 #include "bundle_context.h"
-#include "array_list.h"
 #include "utils.h"
 #include "celix_errno.h"
 #include "filter.h"
 #include "service_reference.h"
-#include "service_registration.h"
-#include "remote_constants.h"
 
 
 #include "discovery.h"
diff --git a/bundles/remote_services/discovery_etcd/src/discovery_impl.h b/bundles/remote_services/discovery_etcd/src/discovery_impl.h
index adf8e4b..096ef4c 100644
--- a/bundles/remote_services/discovery_etcd/src/discovery_impl.h
+++ b/bundles/remote_services/discovery_etcd/src/discovery_impl.h
@@ -16,13 +16,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * discovery_impl.h
- *
- *  \date       Sep 29, 2011
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
 
 #ifndef DISCOVERY_IMPL_H_
 #define DISCOVERY_IMPL_H_
diff --git a/bundles/remote_services/discovery_etcd/src/etcd_watcher.c b/bundles/remote_services/discovery_etcd/src/etcd_watcher.c
index d464cf1..1c22422 100644
--- a/bundles/remote_services/discovery_etcd/src/etcd_watcher.c
+++ b/bundles/remote_services/discovery_etcd/src/etcd_watcher.c
@@ -16,22 +16,15 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * etcd_watcher.c
- *
- * \date       16 Sep 2014
- * \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright  Apache License, Version 2.0
- */
 
 #include <stdbool.h>
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
 
+#include "celix_api.h"
 #include "log_helper.h"
 #include "log_service.h"
-#include "celix_constants.h"
 #include "utils.h"
 #include "discovery.h"
 #include "discovery_impl.h"
@@ -44,6 +37,7 @@
 
 struct etcd_watcher {
     etcdlib_t *etcdlib;
+    int ttl;
 
     discovery_t *discovery;
     log_helper_t **loghelper;
@@ -140,19 +134,17 @@ static celix_status_t etcdWatcher_addAlreadyExistingWatchpoints(etcd_watcher_t *
 
 static celix_status_t etcdWatcher_addOwnFramework(etcd_watcher_t *watcher)
 {
-    celix_status_t status = CELIX_BUNDLE_EXCEPTION;
     char localNodePath[MAX_LOCALNODE_LENGTH];
     char *value;
  	char url[MAX_VALUE_LENGTH];
     int modIndex;
     char* endpoints = NULL;
-    const char* ttlStr = NULL;
-    int ttl;
 
 	celix_bundle_context_t *context = watcher->discovery->context;
 	endpoint_discovery_server_t *server = watcher->discovery->server;
 
     // register own framework
+    celix_status_t status;
     if ((status = etcdWatcher_getLocalNodePath(context, localNodePath)) != CELIX_SUCCESS) {
         return status;
     }
@@ -163,32 +155,17 @@ static celix_status_t etcdWatcher_addOwnFramework(etcd_watcher_t *watcher)
 
 	endpoints = url;
 
-    if ((bundleContext_getProperty(context, CFG_ETCD_TTL, &ttlStr) != CELIX_SUCCESS) || !ttlStr) {
-        ttl = DEFAULT_ETCD_TTL;
-    }
-    else
-    {
-        char* endptr = (char *) ttlStr;
-        errno = 0;
-        ttl = strtol(ttlStr, &endptr, 10);
-        if (*endptr || errno != 0) {
-            ttl = DEFAULT_ETCD_TTL;
-        }
-    }
+	watcher->ttl = celix_bundleContext_getPropertyAsLong(context, CFG_ETCD_TTL, DEFAULT_ETCD_TTL);
 
 	if (etcdlib_get(watcher->etcdlib, localNodePath, &value, &modIndex) != ETCDLIB_RC_OK) {
-		etcdlib_set(watcher->etcdlib, localNodePath, endpoints, ttl, false);
-	}
-	else if (etcdlib_set(watcher->etcdlib, localNodePath, endpoints, ttl, true) != ETCDLIB_RC_OK)  {
+		etcdlib_set(watcher->etcdlib, localNodePath, endpoints, watcher->ttl, false);
+	} else if (etcdlib_set(watcher->etcdlib, localNodePath, endpoints, watcher->ttl , true) != ETCDLIB_RC_OK)  {
 		logHelper_log(*watcher->loghelper, OSGI_LOGSERVICE_WARNING, "Cannot register local discovery");
     }
-    else {
-        status = CELIX_SUCCESS;
-    }
 
 	FREE_MEM(value);
 
-    return status;
+    return CELIX_SUCCESS;
 }
 
 
@@ -281,8 +258,8 @@ static void* etcdWatcher_run(void* data) {
 			}
 
 			highestModified = modIndex;
-        } else if (time(NULL) - timeBeforeWatch <= (DEFAULT_ETCD_TTL / 4)) {
-			sleep(DEFAULT_ETCD_TTL / 4);
+        } else if (time(NULL) - timeBeforeWatch <= (watcher->ttl / 4)) {
+			sleep(watcher->ttl / 4);
         }
 
         FREE_MEM(action);
@@ -291,7 +268,7 @@ static void* etcdWatcher_run(void* data) {
         FREE_MEM(rkey);
 
 		// update own framework uuid
-		if (time(NULL) - timeBeforeWatch > (DEFAULT_ETCD_TTL / 4)) {
+		if (time(NULL) - timeBeforeWatch > (watcher->ttl / 4)) {
 			etcdWatcher_addOwnFramework(watcher);
 			timeBeforeWatch = time(NULL);
 		}
@@ -306,12 +283,6 @@ static void* etcdWatcher_run(void* data) {
  */
 celix_status_t etcdWatcher_create(discovery_t *discovery, celix_bundle_context_t *context, etcd_watcher_t **watcher)
 {
-	celix_status_t status = CELIX_SUCCESS;
-
-	const char* etcd_server = NULL;
-	const char* etcd_port_string = NULL;
-	int etcd_port = 0;
-
 	if (discovery == NULL) {
 		return CELIX_BUNDLE_EXCEPTION;
 	}
@@ -325,32 +296,17 @@ celix_status_t etcdWatcher_create(discovery_t *discovery, celix_bundle_context_t
 		(*watcher)->discovery = discovery;
 		(*watcher)->loghelper = &discovery->loghelper;
 		(*watcher)->entries = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+        (*watcher)->ttl = DEFAULT_ETCD_TTL;
 	}
 
-	if ((bundleContext_getProperty(context, CFG_ETCD_SERVER_IP, &etcd_server) != CELIX_SUCCESS) || !etcd_server) {
-		etcd_server = DEFAULT_ETCD_SERVER_IP;
-	}
+	const char* etcd_server = celix_bundleContext_getProperty(context, CFG_ETCD_SERVER_IP, DEFAULT_ETCD_SERVER_IP);
+	long etcd_port = celix_bundleContext_getPropertyAsLong(context, CFG_ETCD_SERVER_PORT, DEFAULT_ETCD_SERVER_PORT);
 
-	if ((bundleContext_getProperty(context, CFG_ETCD_SERVER_PORT, &etcd_port_string) != CELIX_SUCCESS) || !etcd_port_string) {
-		etcd_port = DEFAULT_ETCD_SERVER_PORT;
-	}
-	else
-	{
-		char* endptr = (char*)etcd_port_string;
-		errno = 0;
-		etcd_port =  strtol(etcd_port_string, &endptr, 10);
-		if (*endptr || errno != 0) {
-			etcd_port = DEFAULT_ETCD_SERVER_PORT;
-		}
-	}
-
-	(*watcher)->etcdlib = etcdlib_create(etcd_server, etcd_port, CURL_GLOBAL_DEFAULT);
+	(*watcher)->etcdlib = etcdlib_create(etcd_server, (int)etcd_port, CURL_GLOBAL_DEFAULT);
+	celix_status_t status = CELIX_SUCCESS;
 	if ((*watcher)->etcdlib == NULL) {
 		status = CELIX_BUNDLE_EXCEPTION;
-	} else {
-		status = CELIX_SUCCESS;
 	}
-
     if (status == CELIX_SUCCESS) {
         etcdWatcher_addOwnFramework(*watcher);
         status = celixThreadMutex_create(&(*watcher)->watcherLock, NULL);
diff --git a/bundles/remote_services/discovery_etcd/src/etcd_watcher.h b/bundles/remote_services/discovery_etcd/src/etcd_watcher.h
index 67428ae..454a67e 100644
--- a/bundles/remote_services/discovery_etcd/src/etcd_watcher.h
+++ b/bundles/remote_services/discovery_etcd/src/etcd_watcher.h
@@ -16,13 +16,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * etcd_watcher.h
- *
- * \date       17 Sep 2014
- * \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- * \copyright  Apache License, Version 2.0
- */
 
 #ifndef ETCD_WATCHER_H_
 #define ETCD_WATCHER_H_
diff --git a/bundles/remote_services/examples/CMakeLists.txt b/bundles/remote_services/examples/CMakeLists.txt
index b0c9a5c..17dcabf 100644
--- a/bundles/remote_services/examples/CMakeLists.txt
+++ b/bundles/remote_services/examples/CMakeLists.txt
@@ -21,6 +21,9 @@ if (RSA_EXAMPLES)
     add_subdirectory(calculator_service)
     add_subdirectory(calculator_shell)
 
+    add_subdirectory(remote_example_api)
+    add_subdirectory(remote_example_service)
+
 
 #    TODO refactor shm remote service admin to use dfi
 #    if (BUILD_RSA_REMOTE_SERVICE_ADMIN_SHM AND BUILD_RSA_DISCOVERY_SHM)
@@ -51,11 +54,12 @@ if (RSA_EXAMPLES)
             BUNDLES
                 Celix::rsa_discovery_etcd
                 Celix::rsa_topology_manager
-                Celix::rsa_dfi calculator
+                Celix::rsa_dfi
                 Celix::shell
                 Celix::shell_tui
                 Celix::log_service
                 Celix::log_writer_stdout
+                calculator
             PROPERTIES
                 RSA_PORT=18888
         )
@@ -69,8 +73,8 @@ if (RSA_EXAMPLES)
                 Celix::shell_tui
                 Celix::log_service
                 Celix::log_writer_stdout
-                calculator_shell
                 Celix::rsa_discovery_etcd
+                calculator_shell
             PROPERTIES
                 RSA_PORT=28888
         )
diff --git a/bundles/remote_services/examples/calculator_api/CMakeLists.txt b/bundles/remote_services/examples/calculator_api/CMakeLists.txt
index a87945f..3b0e334 100644
--- a/bundles/remote_services/examples/calculator_api/CMakeLists.txt
+++ b/bundles/remote_services/examples/calculator_api/CMakeLists.txt
@@ -18,5 +18,5 @@
 add_library(calculator_api INTERFACE)
 target_include_directories(calculator_api INTERFACE include)
 set_target_properties(calculator_api PROPERTIES
-    "INTERFACE_CALCULATOR_DESCRIPTOR"
-    "${CMAKE_CURRENT_LIST_DIR}/include/org.apache.celix.calc.api.Calculator.avpr")
+    "INTERFACE_DESCRIPTOR"
+    "${CMAKE_CURRENT_LIST_DIR}/org.apache.celix.calc.api.Calculator.avpr")
diff --git a/bundles/remote_services/examples/calculator_api/include/calculator_service.h b/bundles/remote_services/examples/calculator_api/include/calculator_service.h
index 19e9741..6458554 100644
--- a/bundles/remote_services/examples/calculator_api/include/calculator_service.h
+++ b/bundles/remote_services/examples/calculator_api/include/calculator_service.h
@@ -16,13 +16,6 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * calculator_service.h
- *
- *  \date       Oct 5, 2011
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
 
 #ifndef CALCULATOR_SERVICE_H_
 #define CALCULATOR_SERVICE_H_
@@ -30,8 +23,6 @@
 #define CALCULATOR_SERVICE              "org.apache.celix.calc.api.Calculator"
 #define CALCULATOR_CONFIGURATION_TYPE   "org.amdatu.remote.admin.http"
 
-typedef struct calculator calculator_t;
-
 typedef struct calculator_service calculator_service_t;
 
 /*
@@ -44,10 +35,10 @@ typedef struct calculator_service calculator_service_t;
  * }
  */
 struct calculator_service {
-    calculator_t *calculator;
-    int (*add)(calculator_t *calculator, double a, double b, double *result);
-    int (*sub)(calculator_t *calculator, double a, double b, double *result);
-    int (*sqrt)(calculator_t *calculator, double a, double *result);
+    void *handle;
+    int (*add)(void *handle, double a, double b, double *result);
+    int (*sub)(void *handle, double a, double b, double *result);
+    int (*sqrt)(void *handle, double a, double *result);
 };
 
 
diff --git a/bundles/remote_services/examples/calculator_api/include/org.apache.celix.calc.api.Calculator.avpr b/bundles/remote_services/examples/calculator_api/org.apache.celix.calc.api.Calculator.avpr
similarity index 100%
rename from bundles/remote_services/examples/calculator_api/include/org.apache.celix.calc.api.Calculator.avpr
rename to bundles/remote_services/examples/calculator_api/org.apache.celix.calc.api.Calculator.avpr
diff --git a/bundles/remote_services/examples/calculator_api/include/org.apache.celix.calc.api.Calculator.descriptor b/bundles/remote_services/examples/calculator_api/org.apache.celix.calc.api.Calculator.descriptor
similarity index 100%
rename from bundles/remote_services/examples/calculator_api/include/org.apache.celix.calc.api.Calculator.descriptor
rename to bundles/remote_services/examples/calculator_api/org.apache.celix.calc.api.Calculator.descriptor
diff --git a/bundles/remote_services/examples/calculator_service/CMakeLists.txt b/bundles/remote_services/examples/calculator_service/CMakeLists.txt
index b47a3ae..2d55e0b 100644
--- a/bundles/remote_services/examples/calculator_service/CMakeLists.txt
+++ b/bundles/remote_services/examples/calculator_service/CMakeLists.txt
@@ -25,5 +25,5 @@ add_celix_bundle(calculator
 target_include_directories(calculator PRIVATE src)
 target_link_libraries(calculator PRIVATE Celix::rsa_spi calculator_api)
 
-get_target_property(DESCR calculator_api INTERFACE_CALCULATOR_DESCRIPTOR)
+get_target_property(DESCR calculator_api INTERFACE_DESCRIPTOR)
 celix_bundle_files(calculator ${DESCR} DESTINATION .)
diff --git a/bundles/remote_services/examples/calculator_service/src/calculator_activator.c b/bundles/remote_services/examples/calculator_service/src/calculator_activator.c
index 41737f1..e616fb4 100644
--- a/bundles/remote_services/examples/calculator_service/src/calculator_activator.c
+++ b/bundles/remote_services/examples/calculator_service/src/calculator_activator.c
@@ -16,88 +16,44 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * calculator_activator.c
- *
- *  \date       Oct 5, 2011
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
 
 #include <stdlib.h>
 
-#include "bundle_activator.h"
-#include "bundle_context.h"
-#include "service_registration.h"
+#include <celix_api.h>
 
 #include "calculator_impl.h"
 #include "remote_constants.h"
 
 struct activator {
     calculator_t *calculator;
-    calculator_service_t *service;
-
-    service_registration_t *calculatorReg;
+    calculator_service_t service;
+    long svcId;
 };
 
-celix_status_t bundleActivator_create(celix_bundle_context_t *context, void **userData) {
-    celix_status_t status = CELIX_SUCCESS;
-    struct activator *activator;
+celix_status_t calculatorBndStart(struct activator *act, celix_bundle_context_t *ctx) {
+    act->svcId = -1L;
+    act->calculator = calculator_create();
+    if (act->calculator != NULL) {
+        act->service.handle = act->calculator;
+        act->service.add = (void*)calculator_add;
+        act->service.sub = (void*)calculator_sub;
+        act->service.sqrt = (void*)calculator_sqrt;
 
-    activator = calloc(1, sizeof(*activator));
-    if (!activator) {
-        status = CELIX_ENOMEM;
-    } else {
-        activator->calculatorReg = NULL;
+        celix_properties_t *properties = celix_properties_create();
+        celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_INTERFACES, CALCULATOR_SERVICE);
+        celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_CONFIGS, CALCULATOR_CONFIGURATION_TYPE);
 
-        *userData = activator;
+        act->svcId = celix_bundleContext_registerService(ctx, &act->service, CALCULATOR_SERVICE, properties);
     }
-
-    return status;
+    return CELIX_SUCCESS;
 }
 
-celix_status_t bundleActivator_start(void * userData, celix_bundle_context_t *context) {
-    celix_status_t status = CELIX_SUCCESS;
-    struct activator *activator = userData;
-
-    status = calculator_create(&activator->calculator);
-    if (status == CELIX_SUCCESS) {
-        activator->service = calloc(1, sizeof(*activator->service));
-        if (!activator->service) {
-            status = CELIX_ENOMEM;
-        } else {
-            activator->service->calculator = activator->calculator;
-            activator->service->add = calculator_add;
-            activator->service->sub = calculator_sub;
-            activator->service->sqrt = calculator_sqrt;
-
-            celix_properties_t *properties = celix_properties_create();
-            celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_INTERFACES, CALCULATOR_SERVICE);
-            celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_CONFIGS, CALCULATOR_CONFIGURATION_TYPE);
-            bundleContext_registerService(context, CALCULATOR_SERVICE, activator->service, properties, &activator->calculatorReg);
-        }
+celix_status_t calculatorBndStop(struct activator *act, celix_bundle_context_t *ctx) {
+    celix_bundleContext_unregisterService(ctx, act->svcId);
+    if (act->calculator != NULL) {
+        calculator_destroy(act->calculator);
     }
-
-    return status;
-}
-
-celix_status_t bundleActivator_stop(void * userData, celix_bundle_context_t *context) {
-    celix_status_t status = CELIX_SUCCESS;
-    struct activator *activator = userData;
-
-    serviceRegistration_unregister(activator->calculatorReg);
-
-    free(activator->service);
-
-    calculator_destroy(&activator->calculator);
-
-    return status;
+    return CELIX_SUCCESS;
 }
 
-celix_status_t bundleActivator_destroy(void * userData, celix_bundle_context_t *context) {
-    celix_status_t status = CELIX_SUCCESS;
-
-    free(userData);
-
-    return status;
-}
+CELIX_GEN_BUNDLE_ACTIVATOR(struct activator, calculatorBndStart, calculatorBndStop);
diff --git a/bundles/remote_services/examples/calculator_service/src/calculator_impl.c b/bundles/remote_services/examples/calculator_service/src/calculator_impl.c
index ad59820..db6b7b8 100644
--- a/bundles/remote_services/examples/calculator_service/src/calculator_impl.c
+++ b/bundles/remote_services/examples/calculator_service/src/calculator_impl.c
@@ -16,13 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * calculator_impl.c
- *
- *  \date       Oct 5, 2011
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
+
 
 #include <math.h>
 
@@ -31,24 +25,17 @@
 
 #include "calculator_impl.h"
 
-celix_status_t calculator_create(calculator_t **calculator) {
-    celix_status_t status = CELIX_SUCCESS;
-
-    *calculator = calloc(1, sizeof(**calculator));
-    if (!*calculator) {
-        status = CELIX_ENOMEM;
-    }
-
-    return status;
+calculator_t* calculator_create(void) {
+    struct calculator *calc = calloc(1, sizeof(*calc));
+    return calc;
 }
 
-celix_status_t calculator_destroy(calculator_t **calculator) {
-    free(*calculator);
-    return CELIX_SUCCESS;
+void calculator_destroy(calculator_t *calculator) {
+    free(calculator);
 }
 
-celix_status_t calculator_add(calculator_t *calculator, double a, double b, double *result) {
-    celix_status_t status = CELIX_SUCCESS;
+int calculator_add(calculator_t *calculator __attribute__((unused)), double a, double b, double *result) {
+    int status = CELIX_SUCCESS;
 
     *result = a + b;
     printf("CALCULATOR: Add: %f + %f = %f\n", a, b, *result);
@@ -56,8 +43,8 @@ celix_status_t calculator_add(calculator_t *calculator, double a, double b, doub
     return status;
 }
 
-celix_status_t calculator_sub(calculator_t *calculator, double a, double b, double *result) {
-    celix_status_t status = CELIX_SUCCESS;
+int calculator_sub(calculator_t *calculator __attribute__((unused)), double a, double b, double *result) {
+    int status = CELIX_SUCCESS;
 
     *result = a - b;
     printf("CALCULATOR: Sub: %f + %f = %f\n", a, b, *result);
@@ -65,8 +52,8 @@ celix_status_t calculator_sub(calculator_t *calculator, double a, double b, doub
     return status;
 }
 
-celix_status_t calculator_sqrt(calculator_t *calculator, double a, double *result) {
-    celix_status_t status = CELIX_SUCCESS;
+int calculator_sqrt(calculator_t *calculator __attribute__((unused)), double a, double *result) {
+    int status = CELIX_SUCCESS;
 
     if (a > 0) {
         *result = sqrt(a);
diff --git a/bundles/remote_services/examples/calculator_service/src/calculator_impl.h b/bundles/remote_services/examples/calculator_service/src/calculator_impl.h
index 94023f8..c70b2f9 100644
--- a/bundles/remote_services/examples/calculator_service/src/calculator_impl.h
+++ b/bundles/remote_services/examples/calculator_service/src/calculator_impl.h
@@ -31,13 +31,13 @@
 
 #include "calculator_service.h"
 
-struct calculator {
-};
+typedef struct calculator {
+} calculator_t;
 
-celix_status_t calculator_create(calculator_t **calculator);
-celix_status_t calculator_destroy(calculator_t **calculator);
-celix_status_t calculator_add(calculator_t *calculator, double a, double b, double *result);
-celix_status_t calculator_sub(calculator_t *calculator, double a, double b, double *result);
-celix_status_t calculator_sqrt(calculator_t *calculator, double a, double *result);
+calculator_t* calculator_create(void);
+void calculator_destroy(calculator_t *calculator);
+int calculator_add(calculator_t *calculator, double a, double b, double *result);
+int calculator_sub(calculator_t *calculator, double a, double b, double *result);
+int calculator_sqrt(calculator_t *calculator, double a, double *result);
 
 #endif /* CALCULATOR_IMPL_H_ */
diff --git a/bundles/remote_services/examples/calculator_shell/CMakeLists.txt b/bundles/remote_services/examples/calculator_shell/CMakeLists.txt
index 14087e3..2c0158a 100644
--- a/bundles/remote_services/examples/calculator_shell/CMakeLists.txt
+++ b/bundles/remote_services/examples/calculator_shell/CMakeLists.txt
@@ -28,7 +28,7 @@ target_include_directories(calculator_shell PRIVATE src)
 target_link_libraries(calculator_shell PRIVATE Celix::shell_api calculator_api)
 
 celix_bundle_files(calculator_shell
-    ../calculator_api/include/org.apache.celix.calc.api.Calculator.avpr
+    ../calculator_api/org.apache.celix.calc.api.Calculator.avpr
     #src/org.apache.celix.calc.api.Calculator2.descriptor ##Use this descriptor in case you want to try out versioning!
     DESTINATION .
 )
diff --git a/bundles/remote_services/examples/calculator_shell/src/add_command.c b/bundles/remote_services/examples/calculator_shell/src/add_command.c
index 7084f81..094a0e3 100644
--- a/bundles/remote_services/examples/calculator_shell/src/add_command.c
+++ b/bundles/remote_services/examples/calculator_shell/src/add_command.c
@@ -16,70 +16,74 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * add_command.c
- *
- *  \date       Oct 13, 2011
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
 
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
 
-#include "array_list.h"
-#include "bundle_context.h"
+#include "celix_api.h"
 #include "add_command.h"
 #include "calculator_service.h"
+#include "celix_utils.h"
 
 
 static celix_status_t addCommand_isNumeric(char *number, bool *ret);
 
-void addCommand_execute(celix_bundle_context_t *context, char *line, FILE *out, FILE *err) {
-    celix_status_t status = CELIX_SUCCESS;
-    service_reference_pt calculatorService = NULL;
+struct calc_callback_data {
+    double a;
+    double b;
+    double result;
+    int rc;
+};
 
-    status = bundleContext_getServiceReference(context, (char *) CALCULATOR_SERVICE, &calculatorService);
-    if (calculatorService == NULL) {
-        fprintf(err, "ADD: Cannot get reference for %s.\n", CALCULATOR_SERVICE);
-    }
-    if (status == CELIX_SUCCESS) {
-        char *token = line;
-        strtok_r(line, " ", &token);
-        char *aStr = strtok_r(NULL, " ", &token);
-        char *bStr = strtok_r(NULL, " ", &token);
-        bool aNumeric, bNumeric;
-        if (aStr != NULL && bStr != NULL) {
-            addCommand_isNumeric(aStr, &aNumeric);
-            addCommand_isNumeric(bStr, &bNumeric);
-            if (aNumeric && bNumeric) {
-                calculator_service_t *calculator = NULL;
-                status = bundleContext_getService(context, calculatorService, (void *) &calculator);
-                if (status == CELIX_SUCCESS && calculator != NULL) {
-                    double a = atof(aStr);
-                    double b = atof(bStr);
-                    double result = 0;
-                    status = calculator->add(calculator->calculator, a, b, &result);
-                    if (status == CELIX_SUCCESS) {
-                        fprintf(out, "CALCULATOR_SHELL: Add: %f + %f = %f\n", a, b, result);
-                    } else {
-                        fprintf(err, "ADD: Unexpected exception in Calc service\n");
-                    }
-                } else {
-                    fprintf(err, "No calc service available\n");
-                }
+static void calcCallback(void *handle, void *svc) {
+    struct calc_callback_data *data = handle;
+    calculator_service_t *calc = svc;
+    data->rc = calc->add(calc->handle, data->a, data->b, &data->result);
+}
+
+bool addCommand_execute(void *handle, const char *const_line, FILE *out, FILE *err) {
+    bool ok = true;
+    celix_bundle_context_t *context = handle;
+
+    char *line = celix_utils_strdup(const_line);
+
+    char *token = line;
+    strtok_r(line, " ", &token);
+    char *aStr = strtok_r(NULL, " ", &token);
+    char *bStr = strtok_r(NULL, " ", &token);
+    bool aNumeric, bNumeric;
+    if (aStr != NULL && bStr != NULL) {
+        addCommand_isNumeric(aStr, &aNumeric);
+        addCommand_isNumeric(bStr, &bNumeric);
+        if (aNumeric && bNumeric) {
+            struct calc_callback_data data;
+
+            data.a = atof(aStr);
+            data.b = atof(bStr);
+            data.result = 0;
+            data.rc = 0;
+            bool called = celix_bundleContext_useService(context, CALCULATOR_SERVICE, &data, calcCallback);
+            if (called && data.rc == 0) {
+                fprintf(out, "CALCULATOR_SHELL: Add: %f + %f = %f\n", data.a, data.b, data.result);
+            } else if (!called) {
+                fprintf(err, "ADD: calculator service not available\n");
+                ok = false;
             } else {
-                fprintf(err, "ADD: Requires 2 numerical parameter\n");
+                fprintf(err, "ADD: Unexpected exception in Calc service\n");
+                ok = false;
             }
         } else {
             fprintf(err, "ADD: Requires 2 numerical parameter\n");
+            ok = false;
         }
     } else {
-        fprintf(err, "No calc service available\n");
+        fprintf(err, "ADD: Requires 2 numerical parameter\n");
+        ok = false;
     }
 
-    //return status;
+    free(line);
+    return ok;
 }
 
 static celix_status_t addCommand_isNumeric(char *number, bool *ret) {
diff --git a/bundles/remote_services/examples/calculator_shell/src/add_command.h b/bundles/remote_services/examples/calculator_shell/src/add_command.h
index 505fbab..40a4de3 100644
--- a/bundles/remote_services/examples/calculator_shell/src/add_command.h
+++ b/bundles/remote_services/examples/calculator_shell/src/add_command.h
@@ -16,17 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * add_command.h
- *
- *  \date       Oct 13, 2011
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
+
 
 #ifndef ADD_COMMAND_H_
 #define ADD_COMMAND_H_
 
-void addCommand_execute(celix_bundle_context_t *context, char *line, FILE *out, FILE *err);
+bool addCommand_execute(void *handle, const char *line, FILE *out, FILE *err);
 
 #endif /* ADD_COMMAND_H_ */
diff --git a/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c b/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c
index 05f5736..6cf1d5a 100644
--- a/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c
+++ b/bundles/remote_services/examples/calculator_shell/src/calculator_shell_activator.c
@@ -19,101 +19,51 @@
 
 #include <stdlib.h>
 #include <string.h>
-#include <celix_shell_command.h>
 
-#include "bundle_activator.h"
-#include "bundle_context.h"
-#include "service_registration.h"
+
+#include "celix_shell_command.h"
+#include "celix_api.h"
 
 #include "add_command.h"
 #include "sub_command.h"
 #include "sqrt_command.h"
 
-struct activator {
-    service_registration_t *addCommand;
-    celix_shell_command_t *addCmd;
-    celix_shell_command_t *addCmdSrv;
-
-    service_registration_t *subCommand;
-    celix_shell_command_t *subCmd;
-    celix_shell_command_t *subCmdSrv;
-
-    service_registration_t *sqrtCommand;
-    celix_shell_command_t *sqrtCmd;
-    celix_shell_command_t *sqrtCmdSrv;
-};
-
-celix_status_t bundleActivator_create(celix_bundle_context_t *context, void **userData) {
-    celix_status_t status = CELIX_SUCCESS;
-    if (status == CELIX_SUCCESS) {
-        *userData = calloc(1, sizeof(struct activator));
-        if (!*userData) {
-            status = CELIX_ENOMEM;
-        } else {
-            ((struct activator *) (*userData))->addCommand = NULL;
-            ((struct activator *) (*userData))->subCommand = NULL;
-            ((struct activator *) (*userData))->sqrtCommand = NULL;
-
-            ((struct activator *) (*userData))->addCmd = NULL;
-            ((struct activator *) (*userData))->subCmd = NULL;
-            ((struct activator *) (*userData))->sqrtCmd = NULL;
-
-            ((struct activator *) (*userData))->addCmdSrv = NULL;
-            ((struct activator *) (*userData))->subCmdSrv = NULL;
-            ((struct activator *) (*userData))->sqrtCmdSrv = NULL;
-        }
-    }
-
-    return status;
-}
-
-celix_status_t bundleActivator_start(void * userData, celix_bundle_context_t *context) {
-    celix_status_t status = CELIX_SUCCESS;
-
-    struct activator * activator = (struct activator *) userData;
-
-    activator->addCmdSrv = calloc(1, sizeof(*activator->addCmdSrv));
-    activator->addCmdSrv->handle = context;
-    activator->addCmdSrv->executeCommand = (void *)addCommand_execute;
+typedef struct calc_shell_activator {
+    long addCmdSvcId;
+    celix_shell_command_t addCmd;
+    long subCmdSvcId;
+    celix_shell_command_t subCmd;
+    long sqrtCmdSvcId;
+    celix_shell_command_t sqrtCmd;
+} calc_shell_activator_t;
+
+static celix_status_t calcShell_start(calc_shell_activator_t *activator, celix_bundle_context_t *ctx) {
+    activator->addCmd.handle = ctx;
+    activator->addCmd.executeCommand = addCommand_execute;
     celix_properties_t *props = celix_properties_create();
     celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "add");
-    bundleContext_registerService(context, (char *)CELIX_SHELL_COMMAND_SERVICE_NAME, activator->addCmdSrv, props, &activator->addCommand);
+    activator->addCmdSvcId = celix_bundleContext_registerService(ctx, &activator->addCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
 
-
-    activator->sqrtCmdSrv = calloc(1, sizeof(*activator->sqrtCmdSrv));
-    activator->sqrtCmdSrv->handle = context;
-    activator->sqrtCmdSrv->executeCommand = (void *)sqrtCommand_execute;
-    props = celix_properties_create();
-    celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "sqrt");
-    bundleContext_registerService(context, (char *)CELIX_SHELL_COMMAND_SERVICE_NAME, activator->sqrtCmdSrv, props, &activator->sqrtCommand);
-
-    activator->subCmdSrv = calloc(1, sizeof(*activator->subCmdSrv));
-    activator->subCmdSrv->handle = context;
-    activator->subCmdSrv->executeCommand = (void *)subCommand_execute;
+    activator->subCmd.handle = ctx;
+    activator->subCmd.executeCommand = subCommand_execute;
     props = celix_properties_create();
     celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "sub");
-    bundleContext_registerService(context, (char *)CELIX_SHELL_COMMAND_SERVICE_NAME, activator->subCmdSrv, props, &activator->subCommand);
-
-    return status;
-}
+    activator->subCmdSvcId = celix_bundleContext_registerService(ctx, &activator->subCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
 
+    activator->sqrtCmd.handle = ctx;
+    activator->sqrtCmd.executeCommand = sqrtCommand_execute;
+    props = celix_properties_create();
+    celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "sqrt");
+    activator->sqrtCmdSvcId = celix_bundleContext_registerService(ctx, &activator->sqrtCmd, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
 
-celix_status_t bundleActivator_stop(void * userData, celix_bundle_context_t *context) {
-    celix_status_t status = CELIX_SUCCESS;
-    struct activator * activator = (struct activator *) userData;
-    serviceRegistration_unregister(activator->addCommand);
-    serviceRegistration_unregister(activator->subCommand);
-    serviceRegistration_unregister(activator->sqrtCommand);
-
-    free(activator->addCmdSrv);
-    free(activator->subCmdSrv);
-    free(activator->sqrtCmdSrv);
-
-    return status;
+    return CELIX_SUCCESS;
 }
 
-celix_status_t bundleActivator_destroy(void * userData, celix_bundle_context_t *context) {
-    free(userData);
+static celix_status_t calcShell_stop(calc_shell_activator_t *activator, celix_bundle_context_t *ctx) {
+    celix_bundleContext_unregisterService(ctx, activator->addCmdSvcId);
+    celix_bundleContext_unregisterService(ctx, activator->subCmdSvcId);
+    celix_bundleContext_unregisterService(ctx, activator->sqrtCmdSvcId);
     return CELIX_SUCCESS;
 }
 
+CELIX_GEN_BUNDLE_ACTIVATOR(calc_shell_activator_t, calcShell_start, calcShell_stop);
diff --git a/bundles/remote_services/examples/calculator_shell/src/org.apache.celix.calc.api.Calculator.descriptor b/bundles/remote_services/examples/calculator_shell/src/org.apache.celix.calc.api.Calculator.descriptor
deleted file mode 100644
index 35b4df7..0000000
--- a/bundles/remote_services/examples/calculator_shell/src/org.apache.celix.calc.api.Calculator.descriptor
+++ /dev/null
@@ -1,11 +0,0 @@
-:header
-type=interface
-name=calculator
-version=1.2.3
-:annotations
-classname=org.example.Calculator
-:types
-:methods
-add(DD)D=add(#am=handle;PDD#am=pre;*D)N
-sub(DD)D=sub(#am=handle;PDD#am=pre;*D)N
-sqrt(D)D=sqrt(#am=handle;PD#am=pre;*D)N
diff --git a/bundles/remote_services/examples/calculator_shell/src/sqrt_command.c b/bundles/remote_services/examples/calculator_shell/src/sqrt_command.c
index 07de852..175040a 100644
--- a/bundles/remote_services/examples/calculator_shell/src/sqrt_command.c
+++ b/bundles/remote_services/examples/calculator_shell/src/sqrt_command.c
@@ -16,66 +16,71 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * sqrt_command.c
- *
- *  \date       Oct 13, 2011
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
+
 
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
 
-#include "array_list.h"
-#include "bundle_context.h"
+#include "celix_api.h"
+#include "celix_utils.h"
 #include "sqrt_command.h"
 #include "calculator_service.h"
 
 static celix_status_t sqrtCommand_isNumeric(char *number, bool *ret);
 
-void sqrtCommand_execute(celix_bundle_context_t *context, char *line, FILE *out, FILE *err) {
-    celix_status_t status = CELIX_SUCCESS;
-    service_reference_pt calculatorService = NULL;
+struct calc_callback_data {
+    double a;
+    double result;
+    int rc;
+};
 
-    status = bundleContext_getServiceReference(context, (char *) CALCULATOR_SERVICE, &calculatorService);
-    if (calculatorService == NULL) {
-        fprintf(err, "SQRT: Cannot get reference for %s.\n", CALCULATOR_SERVICE);
-    }
-    if (status == CELIX_SUCCESS) {
-        char *token = line;
-        strtok_r(line, " ", &token);
-        char *aStr = strtok_r(NULL, " ", &token);
-        if(aStr != NULL){
-            bool numeric;
-            sqrtCommand_isNumeric(aStr, &numeric);
-            if (numeric) {
-                calculator_service_t *calculator = NULL;
-                status = bundleContext_getService(context, calculatorService, (void *) &calculator);
-                if (status == CELIX_SUCCESS && calculator != NULL) {
-                    double a = atof(aStr);
-                    double result = 0;
-                    status = calculator->sqrt(calculator->calculator, a, &result);
-                    if (status == CELIX_SUCCESS) {
-                        fprintf(out, "CALCULATOR_SHELL: Sqrt: %f = %f\n", a, result);
-                    } else {
-                        fprintf(err, "SQRT: Unexpected exception in Calc service\n");
-                    }
-                } else {
-                    fprintf(err, "No calc service available\n");
-                }
+static void calcCallback(void *handle, void *svc) {
+    struct calc_callback_data *data = handle;
+    calculator_service_t *calc = svc;
+    data->rc = calc->sqrt(calc->handle, data->a, &data->result);
+}
+
+bool sqrtCommand_execute(void *handle, const char *const_line, FILE *out, FILE *err) {
+    celix_bundle_context_t *context = handle;
+    bool ok = true;
+    char *line = celix_utils_strdup(const_line);
+
+
+    char *token = line;
+    strtok_r(line, " ", &token);
+    char *aStr = strtok_r(NULL, " ", &token);
+    if(aStr != NULL) {
+        bool numeric;
+        sqrtCommand_isNumeric(aStr, &numeric);
+        if (numeric) {
+            struct calc_callback_data data;
+
+            data.a = atof(aStr);
+            data.result = 0;
+            data.rc = 0;
+            bool called = celix_bundleContext_useService(context, CALCULATOR_SERVICE, &data, calcCallback);
+            if (called && data.rc == 0) {
+                fprintf(out, "CALCULATOR_SHELL: Sqrt: %f = %f\n", data.a, data.result);
+            } else if (!called) {
+                fprintf(err, "ADD: calculator service not available\n");
+                ok = false;
             } else {
-                fprintf(err, "SQRT: Requires 1 numerical parameter\n");
+                fprintf(err, "ADD: Unexpected exception in Calc service\n");
+                ok = false;
             }
         } else {
             fprintf(err, "SQRT: Requires 1 numerical parameter\n");
+            ok = false;
         }
     } else {
-        fprintf(err, "No calc service available\n");
+        fprintf(err, "SQRT: Requires 1 numerical parameter\n");
+        ok = false;
     }
 
-    //return status;
+    free(line);
+
+    return ok;
 }
 
 static celix_status_t sqrtCommand_isNumeric(char *number, bool *ret) {
diff --git a/bundles/remote_services/examples/calculator_shell/src/sqrt_command.h b/bundles/remote_services/examples/calculator_shell/src/sqrt_command.h
index 65b5e7d..317363d 100644
--- a/bundles/remote_services/examples/calculator_shell/src/sqrt_command.h
+++ b/bundles/remote_services/examples/calculator_shell/src/sqrt_command.h
@@ -16,17 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * sqrt_command.h
- *
- *  \date       Oct 13, 2011
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
+
 
 #ifndef SQRT_COMMAND_H_
 #define SQRT_COMMAND_H_
 
-void sqrtCommand_execute(celix_bundle_context_t *context, char *line, FILE *out, FILE *err);
+bool sqrtCommand_execute(void *handle, const char *line, FILE *out, FILE *err);
 
 #endif /* SQRT_COMMAND_H_ */
diff --git a/bundles/remote_services/examples/calculator_shell/src/sub_command.c b/bundles/remote_services/examples/calculator_shell/src/sub_command.c
index 9dbd5c1..9a1f89d 100644
--- a/bundles/remote_services/examples/calculator_shell/src/sub_command.c
+++ b/bundles/remote_services/examples/calculator_shell/src/sub_command.c
@@ -16,69 +16,73 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * sub_command.c
- *
- *  \date       Oct 13, 2011
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
 
 #include <stdlib.h>
 #include <ctype.h>
 #include <string.h>
 
-#include "array_list.h"
-#include "bundle_context.h"
+#include "celix_utils.h"
+#include "celix_api.h"
 #include "sub_command.h"
 #include "calculator_service.h"
 
 static celix_status_t subCommand_isNumeric(char *number, bool *ret);
 
-void subCommand_execute(celix_bundle_context_t *context, char *line, FILE *out, FILE *err) {
-    celix_status_t status = CELIX_SUCCESS;
-    service_reference_pt calculatorService = NULL;
+struct calc_callback_data {
+    double a;
+    double b;
+    double result;
+    int rc;
+};
 
-    status = bundleContext_getServiceReference(context, (char *) CALCULATOR_SERVICE, &calculatorService);
-    if (calculatorService == NULL) {
-        fprintf(err, "SUB: Cannot get reference for %s\n", CALCULATOR_SERVICE);
-    }
-    if (status == CELIX_SUCCESS) {
-        char *token = line;
-        strtok_r(line, " ", &token);
-        char *aStr = strtok_r(NULL, " ", &token);
-        char *bStr = strtok_r(NULL, " ", &token);
-        if(aStr != NULL && bStr != NULL ){
-            bool aNumeric, bNumeric;
-            subCommand_isNumeric(aStr, &aNumeric);
-            subCommand_isNumeric(bStr, &bNumeric);
-            if (aNumeric && bNumeric) {
-                calculator_service_t *calculator = NULL;
-                status = bundleContext_getService(context, calculatorService, (void *) &calculator);
-                if (status == CELIX_SUCCESS && calculator != NULL) {
-                    double a = atof(aStr);
-                    double b = atof(bStr);
-                    double result = 0;
-                    status = calculator->sub(calculator->calculator, a, b, &result);
-                    if (status == CELIX_SUCCESS) {
-                        fprintf(out, "CALCULATOR_SHELL: Sub: %f - %f = %f\n", a, b, result);
-                    } else {
-                        fprintf(err, "SUB: Unexpected exception in Calc service\n");
-                    }
-                } else {
-                    fprintf(err, "No calc service available\n");
-                }
+static void calcCallback(void *handle, void *svc) {
+    struct calc_callback_data *data = handle;
+    calculator_service_t *calc = svc;
+    data->rc = calc->sub(calc->handle, data->a, data->b, &data->result);
+}
+
+bool subCommand_execute(void *handle, const char *const_line, FILE *out, FILE *err) {
+    bool ok = true;
+    celix_bundle_context_t *context = handle;
+
+    char *line = celix_utils_strdup(const_line);
+
+    char *token = line;
+    strtok_r(line, " ", &token);
+    char *aStr = strtok_r(NULL, " ", &token);
+    char *bStr = strtok_r(NULL, " ", &token);
+    bool aNumeric, bNumeric;
+    if (aStr != NULL && bStr != NULL) {
+        subCommand_isNumeric(aStr, &aNumeric);
+        subCommand_isNumeric(bStr, &bNumeric);
+        if (aNumeric && bNumeric) {
+            struct calc_callback_data data;
+
+            data.a = atof(aStr);
+            data.b = atof(bStr);
+            data.result = 0;
+            data.rc = 0;
+            bool called = celix_bundleContext_useService(context, CALCULATOR_SERVICE, &data, calcCallback);
+            if (called && data.rc == 0) {
+                fprintf(out, "CALCULATOR_SHELL: Add: %f + %f = %f\n", data.a, data.b, data.result);
+            } else if (!called) {
+                fprintf(err, "Sub: calculator service not available\n");
+                ok = false;
             } else {
-                fprintf(err, "SUB: Requires 2 numerical parameter\n");
+                fprintf(err, "Sub: Unexpected exception in Calc service\n");
+                ok = false;
             }
         } else {
-            fprintf(err, "SUB: Requires 2 numerical parameter\n");
+            fprintf(err, "Sub: Requires 2 numerical parameter\n");
+            ok = false;
         }
     } else {
-        fprintf(err, "No calc service available\n");
+        fprintf(err, "Sub: Requires 2 numerical parameter\n");
+        ok = false;
     }
 
-    //return status;
+    free(line);
+    return ok;
 }
 
 static celix_status_t subCommand_isNumeric(char *number, bool *ret) {
diff --git a/bundles/remote_services/examples/calculator_shell/src/sub_command.h b/bundles/remote_services/examples/calculator_shell/src/sub_command.h
index 33a94c3..7673089 100644
--- a/bundles/remote_services/examples/calculator_shell/src/sub_command.h
+++ b/bundles/remote_services/examples/calculator_shell/src/sub_command.h
@@ -16,17 +16,11 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * sub_command.h
- *
- *  \date       Oct 13, 2011
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
+
 
 #ifndef SUB_COMMAND_H_
 #define SUB_COMMAND_H_
 
-void subCommand_execute(celix_bundle_context_t *context, char *line, FILE *out, FILE *err);
+bool subCommand_execute(void *handle, const char *line, FILE *out, FILE *err);
 
 #endif /* SUB_COMMAND_H_ */
diff --git a/bundles/remote_services/examples/calculator_api/CMakeLists.txt b/bundles/remote_services/examples/remote_example_api/CMakeLists.txt
similarity index 67%
copy from bundles/remote_services/examples/calculator_api/CMakeLists.txt
copy to bundles/remote_services/examples/remote_example_api/CMakeLists.txt
index a87945f..6a0db33 100644
--- a/bundles/remote_services/examples/calculator_api/CMakeLists.txt
+++ b/bundles/remote_services/examples/remote_example_api/CMakeLists.txt
@@ -15,8 +15,14 @@
 # specific language governing permissions and limitations
 # under the License.
 
-add_library(calculator_api INTERFACE)
-target_include_directories(calculator_api INTERFACE include)
-set_target_properties(calculator_api PROPERTIES
-    "INTERFACE_CALCULATOR_DESCRIPTOR"
-    "${CMAKE_CURRENT_LIST_DIR}/include/org.apache.celix.calc.api.Calculator.avpr")
+#[[
+Note use avro-tools.jar (idl command) to generate avpr from avdl
+#]]
+
+add_library(remote_example_api INTERFACE)
+target_include_directories(remote_example_api INTERFACE include)
+set_target_properties(remote_example_api PROPERTIES
+    "INTERFACE_DESCRIPTOR"
+    "${CMAKE_CURRENT_LIST_DIR}/org.apache.celix.RemoteExample.descriptor")
+
+#TODO use avpr instead of descriptor
diff --git a/bundles/remote_services/examples/remote_example_api/include/remote_example.h b/bundles/remote_services/examples/remote_example_api/include/remote_example.h
new file mode 100644
index 0000000..85a6821
--- /dev/null
+++ b/bundles/remote_services/examples/remote_example_api/include/remote_example.h
@@ -0,0 +1,66 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CELIX_REMOTE_EXAMPLE_H
+#define CELIX_REMOTE_EXAMPLE_H
+
+#include <stdint.h>
+
+enum enum_example {
+    ENUM_EXAMPLE_VAL1 = 2,
+    ENUM_EXAMPLE_VAL2 = 4,
+    ENUM_EXAMPLE_VAL3 = 8
+};
+
+
+struct complex_input_example {
+    double a;
+    double b;
+    int32_t n;
+    char *name;
+    enum enum_example e;
+};
+
+struct complex_output_example {
+    double pow;
+    int32_t fib;
+    char *name;
+    enum enum_example e;
+};
+
+#define REMOTE_EXAMPLE_NAME "org.apache.celix.RemoteExample"
+
+typedef struct remote_example {
+    void *handle;
+
+    int (*pow)(void *handle, double a, double b, double *out);
+    int (*fib)(void *handle, int32_t n, int32_t *out);
+
+    int (*setName1)(void *handle, char *n, char **out);
+    int (*setName2)(void *handle, const char *n, char **out);
+
+    int (*setEnum)(void *handle, enum enum_example e, enum enum_example *out);
+
+    int (*action)(void *handle);
+
+    int (*setComplex)(void *handle, struct complex_input_example *exmpl, struct complex_output_example **out);
+
+} remote_example_t;
+
+#endif //CELIX_REMOTE_EXAMPLE_H
diff --git a/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor b/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor
new file mode 100644
index 0000000..7c43bff
--- /dev/null
+++ b/bundles/remote_services/examples/remote_example_api/org.apache.celix.RemoteExample.descriptor
@@ -0,0 +1,18 @@
+:header
+type=interface
+name=org.apache.celix.RemoteExample
+version=1.3.0
+:annotations
+classname=org.apache.celix.RemoteExample
+:types
+enum_example=#ENUM_EXAMPLE_VAL1=2;#ENUM_EXAMPLE_VAL2=4;#ENUM_EXAMPLE_VAL3=8;E
+complex_input={DDItlenum_example; a b n name e}
+complex_output={DItlenum_example; pow fib name e}
+:methods
+pow(DD)D=pow(#am=handle;PDD#am=pre;*D)N
+fib(I)I=fib(#am=handle;PI#am=pre;*I)N
+setName1=setName1(#am=handle;Pt#am=out;*t)N
+setName2=setName2(#am=handle;P#const=true;t#am=out;*t)N
+setEnum=setEnum(#am=handle;Plenum_example;#am=pre;Lenum_example;)N
+action=action(#am=handle;P)N
+setComplex=setComplex(#am=handle;PLcomplex_input;#am=out;*Lcomplex_output;)N
diff --git a/bundles/remote_services/examples/calculator_service/CMakeLists.txt b/bundles/remote_services/examples/remote_example_service/CMakeLists.txt
similarity index 64%
copy from bundles/remote_services/examples/calculator_service/CMakeLists.txt
copy to bundles/remote_services/examples/remote_example_service/CMakeLists.txt
index b47a3ae..03a2261 100644
--- a/bundles/remote_services/examples/calculator_service/CMakeLists.txt
+++ b/bundles/remote_services/examples/remote_example_service/CMakeLists.txt
@@ -15,15 +15,15 @@
 # specific language governing permissions and limitations
 # under the License.
 
-add_celix_bundle(calculator
+add_celix_bundle(remote_example_service
     SOURCES
-        src/calculator_impl
-        src/calculator_activator
-    SYMBOLIC_NAME "apache_celix_remoting_calculator_impl"
+        src/remote_example_activator.c
+        src/remote_example_impl.c
+    SYMBOLIC_NAME "apache_celix_remote_example_service"
     VERSION 0.0.1
 )
-target_include_directories(calculator PRIVATE src)
-target_link_libraries(calculator PRIVATE Celix::rsa_spi calculator_api)
+target_include_directories(remote_example_service PRIVATE src)
+target_link_libraries(remote_example_service PRIVATE Celix::rsa_spi remote_example_api)
 
-get_target_property(DESCR calculator_api INTERFACE_CALCULATOR_DESCRIPTOR)
-celix_bundle_files(calculator ${DESCR} DESTINATION .)
+get_target_property(DESCR remote_example_api INTERFACE_DESCRIPTOR)
+celix_bundle_files(remote_example_service ${DESCR} DESTINATION .)
diff --git a/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c b/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c
new file mode 100644
index 0000000..09da9b4
--- /dev/null
+++ b/bundles/remote_services/examples/remote_example_service/src/remote_example_activator.c
@@ -0,0 +1,62 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <stdlib.h>
+
+#include <celix_api.h>
+
+#include "remote_example.h"
+#include "remote_constants.h"
+#include "remote_example_impl.h"
+
+struct activator {
+    remote_example_impl_t *impl;
+    remote_example_t service;
+    long svcId;
+};
+
+celix_status_t remoteExampleBndStart(struct activator *act, celix_bundle_context_t *ctx) {
+    act->svcId = -1L;
+    act->impl = remoteExample_create();
+    if (act->impl != NULL) {
+        act->service.handle = act->impl;
+        act->service.pow = (void*)remoteExample_pow;
+        act->service.fib = (void*)remoteExample_fib;
+        act->service.setName1 = (void*)remoteExample_setName1;
+        act->service.setName2 = (void*)remoteExample_setName2;
+        act->service.setEnum = (void*)remoteExample_setEnum;
+        act->service.action = (void*)remoteExample_action;
+        act->service.setComplex = (void*)remoteExample_setComplex;
+
+        celix_properties_t *properties = celix_properties_create();
+        celix_properties_set(properties, OSGI_RSA_SERVICE_EXPORTED_INTERFACES, REMOTE_EXAMPLE_NAME);
+        act->svcId = celix_bundleContext_registerService(ctx, &act->service, REMOTE_EXAMPLE_NAME, properties);
+    }
+    return CELIX_SUCCESS;
+}
+
+celix_status_t remoteExampleBndStop(struct activator *act, celix_bundle_context_t *ctx) {
+    celix_bundleContext_unregisterService(ctx, act->svcId);
+    if (act->impl != NULL) {
+        remoteExample_destroy(act->impl);
+    }
+    return CELIX_SUCCESS;
+}
+
+CELIX_GEN_BUNDLE_ACTIVATOR(struct activator, remoteExampleBndStart, remoteExampleBndStop);
diff --git a/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c
new file mode 100644
index 0000000..2eb3eaa
--- /dev/null
+++ b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.c
@@ -0,0 +1,129 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <string.h>
+#include <pthread.h>
+
+#include "remote_example.h"
+#include "remote_example_impl.h"
+
+struct remote_example_impl {
+    pthread_mutex_t mutex; //protects below
+    char *name;
+    enum enum_example e;
+};
+
+remote_example_impl_t* remoteExample_create(void) {
+    remote_example_impl_t* impl = calloc(1, sizeof(remote_example_impl_t));
+    impl->e = ENUM_EXAMPLE_VAL1;
+    pthread_mutex_init(&impl->mutex, NULL);
+    return impl;
+}
+void remoteExample_destroy(remote_example_impl_t* impl) {
+    if (impl != NULL) {
+        pthread_mutex_destroy(&impl->mutex);
+        free(impl->name);
+    }
+    free(impl);
+}
+
+int remoteExample_pow(remote_example_impl_t* impl, double a, double b, double *out) {
+    *out = pow(a, b);
+    return 0;
+}
+
+static int fib_int(int n)
+{
+    if (n <= 0) {
+        return 0;
+    } else if (n <= 2) {
+        return 1;
+    } else {
+        return fib_int(n-1) + fib_int(n-2);
+    }
+}
+
+int remoteExample_fib(remote_example_impl_t* impl, int32_t a, int32_t *out) {
+    int r = fib_int(a);
+    *out = r;
+    return 0;
+}
+
+int remoteExample_setName1(remote_example_impl_t* impl, char *n, char **out) {
+    pthread_mutex_lock(&impl->mutex);
+    //note taking ownership of n;
+    if (impl->name != NULL) {
+        free(impl->name);
+    }
+    impl->name = n;
+    *out = strndup(impl->name, 1024 * 1024);
+    pthread_mutex_unlock(&impl->mutex);
+    return 0;
+}
+
+int remoteExample_setName2(remote_example_impl_t* impl, const char *n, char **out) {
+    pthread_mutex_lock(&impl->mutex);
+    //note _not_ taking ownership of n;
+    if (impl->name != NULL) {
+        free(impl->name);
+    }
+    impl->name = strndup(n, 1024 * 1024);
+    *out = strndup(impl->name, 1024 * 1024);
+    pthread_mutex_unlock(&impl->mutex);
+    return 0;
+}
+
+int remoteExample_setEnum(remote_example_impl_t* impl, enum enum_example e, enum enum_example *out) {
+    pthread_mutex_lock(&impl->mutex);
+    impl->e = e;
+    *out = e;
+    pthread_mutex_unlock(&impl->mutex);
+    return 0;
+}
+
+int remoteExample_action(remote_example_impl_t* impl) {
+    pthread_mutex_lock(&impl->mutex);
+    const char *n = impl->name;
+    printf("action called, name is %s\n", n);
+    pthread_mutex_unlock(&impl->mutex);
+    return 0;
+}
+
+int remoteExample_setComplex(remote_example_impl_t *impl, struct complex_input_example *exmpl, struct complex_output_example **out) {
+    struct complex_output_example *result = calloc(1, sizeof(*result));
+    int rc = remoteExample_pow(impl, exmpl->a, exmpl->b, &result->pow);
+    if (rc == 0) {
+        rc = remoteExample_fib(impl, exmpl->n, &result->fib);
+    }
+    if (rc == 0) {
+        rc = remoteExample_setName2(impl, exmpl->name, &result->name);
+    }
+    if (rc == 0) {
+        rc = remoteExample_setEnum(impl, exmpl->e, &result->e);
+    }
+    if (rc == 0 && out != NULL) {
+        *out = result;
+    } else {
+        free(result);
+    }
+
+    return rc;
+}
\ No newline at end of file
diff --git a/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.h b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.h
new file mode 100644
index 0000000..fe23f73
--- /dev/null
+++ b/bundles/remote_services/examples/remote_example_service/src/remote_example_impl.h
@@ -0,0 +1,40 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CELIX_REMOTE_EXAMPLE_IMPL_H
+#define CELIX_REMOTE_EXAMPLE_IMPL_H
+
+#include <stdlib.h>
+
+typedef struct remote_example_impl remote_example_impl_t;
+
+
+remote_example_impl_t* remoteExample_create(void);
+void remoteExample_destroy(remote_example_impl_t* impl);
+
+int remoteExample_pow(remote_example_impl_t* impl, double a, double b, double *out);
+int remoteExample_fib(remote_example_impl_t* impl, int32_t a, int32_t *out);
+int remoteExample_setEnum(remote_example_impl_t* impl, enum enum_example e, enum enum_example *out);
+int remoteExample_setName1(remote_example_impl_t* impl, char *n, char **out);
+int remoteExample_setName2(remote_example_impl_t* impl, const char *n, char **out);
+int remoteExample_action(remote_example_impl_t* impl);
+int remoteExample_setComplex(remote_example_impl_t *impl, struct complex_input_example *exmpl, struct complex_output_example **out);
+
+//TODO complex
+#endif //CELIX_REMOTE_EXAMPLE_IMPL_H
diff --git a/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c b/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
index fc01587..55a3810 100644
--- a/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
+++ b/bundles/remote_services/remote_service_admin_dfi/src/import_registration_dfi.c
@@ -340,7 +340,7 @@ static void importRegistration_proxyFunc(void *userData, void *args[], void *ret
         celixThreadMutex_unlock(&import->mutex);
         //printf("request sended. got reply '%s' with status %i\n", reply, rc);
 
-        if (rc == 0) {
+        if (rc == 0 && dynFunction_hasReturn(entry->dynFunc)) {
             //fjprintf("Handling reply '%s'\n", reply);
             status = jsonRpc_handleReply(entry->dynFunc, reply, args);
         }
diff --git a/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c b/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c
index 0ba4574..eb45cf8 100644
--- a/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c
+++ b/bundles/remote_services/remote_service_admin_dfi/src/remote_service_admin_dfi.c
@@ -60,7 +60,7 @@ struct remote_service_admin {
     celix_bundle_context_t *context;
     log_helper_t *loghelper;
 
-    celix_thread_mutex_t exportedServicesLock;
+    celix_thread_rwlock_t exportedServicesLock;
     hash_map_pt exportedServices;
 
     celix_thread_mutex_t importedServicesLock;
@@ -118,8 +118,8 @@ celix_status_t remoteServiceAdmin_create(celix_bundle_context_t *context, remote
         (*admin)->exportedServices = hashMap_create(NULL, NULL, NULL, NULL);
          arrayList_create(&(*admin)->importedServices);
 
-        celixThreadMutex_create(&(*admin)->exportedServicesLock, NULL);
-        celixThreadMutex_create(&(*admin)->importedServicesLock, NULL);
+         celixThreadRwlock_create(&(*admin)->exportedServicesLock, NULL);
+         celixThreadMutex_create(&(*admin)->importedServicesLock, NULL);
 
         if (logHelper_create(context, &(*admin)->loghelper) == CELIX_SUCCESS) {
             logHelper_start((*admin)->loghelper);
@@ -217,7 +217,7 @@ celix_status_t remoteServiceAdmin_destroy(remote_service_admin_t **admin)
 celix_status_t remoteServiceAdmin_stop(remote_service_admin_t *admin) {
     celix_status_t status = CELIX_SUCCESS;
 
-    celixThreadMutex_lock(&admin->exportedServicesLock);
+    celixThreadRwlock_writeLock(&admin->exportedServicesLock);
 
     hash_map_iterator_pt iter = hashMapIterator_create(admin->exportedServices);
     while (hashMapIterator_hasNext(iter)) {
@@ -233,7 +233,7 @@ celix_status_t remoteServiceAdmin_stop(remote_service_admin_t *admin) {
         arrayList_destroy(exports);
     }
     hashMapIterator_destroy(iter);
-    celixThreadMutex_unlock(&admin->exportedServicesLock);
+    celixThreadRwlock_unlock(&admin->exportedServicesLock);
 
     celixThreadMutex_lock(&admin->importedServicesLock);
     int i;
@@ -291,7 +291,7 @@ static int remoteServiceAdmin_callback(struct mg_connection *conn) {
             service[pos] = '\0';
             unsigned long serviceId = strtoul(service,NULL,10);
 
-            celixThreadMutex_lock(&rsa->exportedServicesLock);
+            celixThreadRwlock_readLock(&rsa->exportedServicesLock);
 
             //find endpoint
             export_registration_t *export = NULL;
@@ -345,7 +345,7 @@ static int remoteServiceAdmin_callback(struct mg_connection *conn) {
                 RSA_LOG_WARNING(rsa, "No export registration found for service id %lu", serviceId);
             }
 
-            celixThreadMutex_unlock(&rsa->exportedServicesLock);
+            celixThreadRwlock_unlock(&rsa->exportedServicesLock);
 
         }
     }
@@ -442,9 +442,9 @@ celix_status_t remoteServiceAdmin_exportService(remote_service_admin_t *admin, c
 
 
         if (status == CELIX_SUCCESS) {
-            celixThreadMutex_lock(&admin->exportedServicesLock);
+            celixThreadRwlock_writeLock(&admin->exportedServicesLock);
             hashMap_put(admin->exportedServices, reference, *registrations);
-            celixThreadMutex_unlock(&admin->exportedServicesLock);
+            celixThreadRwlock_unlock(&admin->exportedServicesLock);
         } else {
             arrayList_destroy(*registrations);
             *registrations = NULL;
@@ -464,7 +464,7 @@ celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_t *
 
     if (status == CELIX_SUCCESS && ref != NULL) {
         service_reference_pt servRef;
-        celixThreadMutex_lock(&admin->exportedServicesLock);
+        celixThreadRwlock_writeLock(&admin->exportedServicesLock);
         exportReference_getExportedService(ref, &servRef);
 
         array_list_pt exports = (array_list_pt)hashMap_remove(admin->exportedServices, servRef);
@@ -475,7 +475,7 @@ celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_t *
         exportRegistration_close(registration);
         exportRegistration_destroy(registration);
 
-        celixThreadMutex_unlock(&admin->exportedServicesLock);
+        celixThreadRwlock_unlock(&admin->exportedServicesLock);
 
         free(ref);
 
@@ -748,7 +748,7 @@ static celix_status_t remoteServiceAdmin_send(void *handle, endpoint_description
         curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, remoteServiceAdmin_write);
         curl_easy_setopt(curl, CURLOPT_WRITEDATA, (void *)&get);
         curl_easy_setopt(curl, CURLOPT_POSTFIELDSIZE, (curl_off_t)post.size);
-        logHelper_log(rsa->loghelper, OSGI_LOGSERVICE_DEBUG, "RSA: Performing curl post\n");
+        //logHelper_log(rsa->loghelper, OSGI_LOGSERVICE_DEBUG, "RSA: Performing curl post\n");
         res = curl_easy_perform(curl);
 
         *reply = get.writeptr;
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/CMakeLists.txt b/bundles/remote_services/remote_service_admin_dfi/test/CMakeLists.txt
index 20efa08..dddd0a5 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/CMakeLists.txt
+++ b/bundles/remote_services/remote_service_admin_dfi/test/CMakeLists.txt
@@ -23,9 +23,16 @@ add_celix_bundle(rsa_dfi_tst_bundle
     SOURCES
         src/tst_activator.c
 )
-get_target_property(DESCR calculator_api INTERFACE_CALCULATOR_DESCRIPTOR)
+
+#add calculator avpr
+get_target_property(DESCR calculator_api INTERFACE_DESCRIPTOR)
+celix_bundle_files(rsa_dfi_tst_bundle ${DESCR} DESTINATION .)
+
+#add remote example avpr
+get_target_property(DESCR remote_example_api INTERFACE_DESCRIPTOR)
 celix_bundle_files(rsa_dfi_tst_bundle ${DESCR} DESTINATION .)
-target_link_libraries(rsa_dfi_tst_bundle PRIVATE ${CPPUTEST_LIBRARY} calculator_api)
+
+target_link_libraries(rsa_dfi_tst_bundle PRIVATE ${CPPUTEST_LIBRARY} calculator_api remote_example_api)
 target_include_directories(rsa_dfi_tst_bundle PRIVATE src)
 
 add_executable(test_rsa_dfi
@@ -37,7 +44,8 @@ target_include_directories(test_rsa_dfi PRIVATE src)
 target_link_libraries(test_rsa_dfi PRIVATE CURL::libcurl ${CPPUTEST_LIBRARY}
         Celix::framework
         Celix::rsa_common
-        calculator_api)
+        calculator_api
+)
 
 get_property(rsa_bundle_file TARGET rsa_dfi PROPERTY BUNDLE_FILE)
 get_property(calc_bundle_file TARGET calculator PROPERTY BUNDLE_FILE)
@@ -45,6 +53,7 @@ get_property(calculator_shell_bundle_file TARGET calculator_shell PROPERTY BUNDL
 get_property(discovery_configured_bundle_file TARGET rsa_discovery_configured PROPERTY BUNDLE_FILE)
 get_property(topology_manager_bundle_file TARGET Celix::rsa_topology_manager PROPERTY BUNDLE_FILE)
 get_property(tst_bundle_file TARGET rsa_dfi_tst_bundle PROPERTY BUNDLE_FILE)
+get_property(remote_example_bundle_file TARGET remote_example_service PROPERTY BUNDLE_FILE)
 
 configure_file(config.properties.in config.properties)
 configure_file(client.properties.in client.properties)
@@ -53,6 +62,7 @@ configure_file(server.properties.in server.properties)
 add_dependencies(test_rsa_dfi
         rsa_dfi_bundle #note depend on the target creating the bundle zip not the lib target
         calculator_bundle
+        remote_example_service_bundle
 )
 
 add_test(NAME run_test_rsa_dfi COMMAND test_rsa_dfi)
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/server.properties.in b/bundles/remote_services/remote_service_admin_dfi/test/server.properties.in
index 92e3407..5a1fa7d 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/server.properties.in
+++ b/bundles/remote_services/remote_service_admin_dfi/test/server.properties.in
@@ -14,7 +14,7 @@
 # KIND, either express or implied.  See the License for the
 # specific language governing permissions and limitations
 # under the License.
-cosgi.auto.start.1=@rsa_bundle_file@ @calc_bundle_file@ @discovery_configured_bundle_file@ @topology_manager_bundle_file@
+cosgi.auto.start.1=@rsa_bundle_file@ @calc_bundle_file@ @remote_example_bundle_file@ @discovery_configured_bundle_file@ @topology_manager_bundle_file@
 LOGHELPER_ENABLE_STDOUT_FALLBACK=true
 org.osgi.framework.storage.clean=onFirstInit
 org.osgi.framework.storage=.cacheServer
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp b/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp
index 05935a6..3622235 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp
+++ b/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_client_server_tests.cpp
@@ -17,12 +17,13 @@
  * under the License.
  */
 
-#include <CppUTest/TestHarness.h>
+
 #include <remote_constants.h>
-#include "celix_constants.h"
 #include <tst_service.h>
-#include "CppUTest/CommandLineTestRunner.h"
-#include "calculator_service.h"
+#include "celix_api.h"
+
+#include <CppUTest/CommandLineTestRunner.h>
+#include <CppUTest/TestHarness.h>
 
 extern "C" {
 
@@ -36,7 +37,6 @@ extern "C" {
 #include "celix_launcher.h"
 #include "framework.h"
 #include "remote_service_admin.h"
-#include "calculator_service.h"
 
     static celix_framework_t *serverFramework = NULL;
     static celix_bundle_context_t *serverContext = NULL;
@@ -45,74 +45,69 @@ extern "C" {
     static celix_bundle_context_t *clientContext = NULL;
 
     static void setupFm(void) {
-        int rc = 0;
-        celix_bundle_t *bundle = NULL;
-
         //server
-        rc = celixLauncher_launch("server.properties", &serverFramework);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        bundle = NULL;
-        rc = framework_getFrameworkBundle(serverFramework, &bundle);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundle_getContext(bundle, &serverContext);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
+        celix_properties_t *serverProps = celix_properties_load("server.properties");
+        CHECK_TRUE(serverProps != NULL);
+        serverFramework = celix_frameworkFactory_createFramework(serverProps);
+        CHECK_TRUE(serverFramework != NULL);
+        serverContext = celix_framework_getFrameworkContext(serverFramework);
+        CHECK_TRUE(serverContext != NULL);
 
         //client
-        rc = celixLauncher_launch("client.properties", &clientFramework);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        bundle = NULL;
-        rc = framework_getFrameworkBundle(clientFramework, &bundle);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundle_getContext(bundle, &clientContext);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        celix_properties_t *clientProperties = celix_properties_load("client.properties");
+        CHECK_TRUE(clientProperties != NULL);
+        clientFramework = celix_frameworkFactory_createFramework(clientProperties);
+        CHECK_TRUE(clientFramework != NULL);
+        clientContext = celix_framework_getFrameworkContext(clientFramework);
+        CHECK_TRUE(clientContext != NULL);
     }
 
     static void teardownFm(void) {
-        celixLauncher_stop(serverFramework);
-        celixLauncher_waitForShutdown(serverFramework);
-        celixLauncher_destroy(serverFramework);
-
-        celixLauncher_stop(clientFramework);
-        celixLauncher_waitForShutdown(clientFramework);
-        celixLauncher_destroy(clientFramework);
-
-        serverContext = NULL;
-        serverFramework = NULL;
-        clientContext = NULL;
-        clientFramework = NULL;
+        celix_frameworkFactory_destroyFramework(serverFramework);
+        celix_frameworkFactory_destroyFramework(clientFramework);
     }
 
-    static void test1(void) {
-        celix_status_t rc;
-        service_reference_pt ref = NULL;
-        tst_service_t *tst = NULL;
-        int retries = 4;
-
-        while (ref == NULL && retries > 0) {
-            printf("Waiting for service .. %d\n", retries);
-            rc = bundleContext_getServiceReference(clientContext, (char *) TST_SERVICE_NAME, &ref);
-            usleep(1000000);
-            --retries;
-        }
-
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(ref != NULL);
-
-        rc = bundleContext_getService(clientContext, ref, (void **)&tst);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(tst != NULL);
-
-        rc = tst->test(tst->handle);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        bool result;
-        bundleContext_ungetService(clientContext, ref, &result);
-        bundleContext_ungetServiceReference(clientContext, ref);
+    static void testCallback(void *handle __attribute__((unused)), void *svc) {
+        auto *tst = static_cast<tst_service_t *>(svc);
+
+        bool ok;
+
+        bool discovered = tst->isCalcDiscovered(tst->handle);
+        CHECK_TRUE(discovered);
+
+//        ok = tst->testCalculator(tst->handle);
+//        CHECK_TRUE(ok);
+
+        discovered = tst->isRemoteExampleDiscovered(tst->handle);
+        CHECK_TRUE(discovered);
+
+//        ok = tst->testRemoteString(tst->handle);
+//        CHECK_TRUE(ok);
+//
+//        ok = tst->testRemoteConstString(tst->handle);
+//        CHECK_TRUE(ok);
+
+        ok = tst->testRemoteNumbers(tst->handle);
+        CHECK_TRUE(ok);
+
+//        ok = tst->testRemoteEnum(tst->handle);
+//        CHECK_TRUE(ok);
+//
+//        ok = tst->testRemoteAction(tst->handle);
+//        CHECK_TRUE(ok);
+//
+//        ok = tst->testRemoteComplex(tst->handle);
+//        CHECK_TRUE(ok);
+    };
+
+    static void test(void) {
+        celix_service_use_options_t opts{};
+        opts.filter.serviceName = TST_SERVICE_NAME;
+        opts.use = testCallback;
+        opts.filter.ignoreServiceLanguage = true;
+        opts.waitTimeoutInSeconds = 2;
+        bool called = celix_bundleContext_useServiceWithOptions(clientContext, &opts);
+        CHECK_TRUE(called);
     }
 
 }
@@ -129,5 +124,5 @@ TEST_GROUP(RsaDfiClientServerTests) {
 };
 
 TEST(RsaDfiClientServerTests, Test1) {
-    test1();
+    test();
 }
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp b/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp
index fe25fa0..cc7d09f 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp
+++ b/bundles/remote_services/remote_service_admin_dfi/test/src/rsa_tests.cpp
@@ -17,133 +17,100 @@
  * under the License.
  */
 
-#include <CppUTest/TestHarness.h>
 #include <remote_constants.h>
-#include "celix_constants.h"
-#include "CppUTest/CommandLineTestRunner.h"
+#include "celix_api.h"
 #include "calculator_service.h"
 
-extern "C" {
 
-#include <stdio.h>
-#include <stdint.h>
-#include <stdlib.h>
-#include <string.h>
-#include <ctype.h>
+#include <CppUTest/TestHarness.h>
+#include <CppUTest/CommandLineTestRunner.h>
+
+extern "C" {
 
-#include "celix_launcher.h"
-#include "framework.h"
 #include "remote_service_admin.h"
 #include "calculator_service.h"
 
 #define TST_CONFIGURATION_TYPE "org.amdatu.remote.admin.http"
 
-    static framework_pt framework = NULL;
+    static celix_framework_t *framework = NULL;
     static celix_bundle_context_t *context = NULL;
 
-    static service_reference_pt rsaRef = NULL;
-    static remote_service_admin_service_t *rsa = NULL;
-
-    static service_reference_pt calcRef = NULL;
-    static calculator_service_t *calc = NULL;
+    long calcSvcId = -1L;
 
     static void setupFm(void) {
-        int rc = 0;
-
-        rc = celixLauncher_launch("config.properties", &framework);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        celix_properties_t *fwProperties = celix_properties_load("config.properties");
+        CHECK_TRUE(fwProperties != NULL);
+        framework = celix_frameworkFactory_createFramework(fwProperties);
+        CHECK_TRUE(framework != NULL);
+        context = celix_framework_getFrameworkContext(framework);
+        CHECK_TRUE(context != NULL);
 
-        celix_bundle_t *bundle = NULL;
-        rc = framework_getFrameworkBundle(framework, &bundle);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundle_getContext(bundle, &context);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
 
-        rc = bundleContext_getServiceReference(context, (char *)OSGI_RSA_REMOTE_SERVICE_ADMIN, &rsaRef);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(rsaRef != NULL);
-
-        rc = bundleContext_getService(context, rsaRef, (void **)&rsa);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundleContext_getServiceReference(context, (char *)CALCULATOR_SERVICE, &calcRef);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK(calcRef != NULL);
-
-        rc = bundleContext_getService(context, calcRef, (void **)&calc);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        calcSvcId = celix_bundleContext_findService(context, CALCULATOR_SERVICE);
+        CHECK_TRUE(calcSvcId >= 0L);
     }
 
     static void teardownFm(void) {
-        int rc = 0;
-        rc = bundleContext_ungetService(context, rsaRef, NULL);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundleContext_ungetServiceReference(context, rsaRef);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundleContext_ungetService(context, calcRef, NULL);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        rc = bundleContext_ungetServiceReference(context, calcRef);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-
-        celixLauncher_stop(framework);
-        celixLauncher_waitForShutdown(framework);
-        celixLauncher_destroy(framework);
-
-        rsaRef = NULL;
-        rsa = NULL;
-        calcRef = NULL;
-        calc = NULL;
-        context = NULL;
-        framework = NULL;
+        celix_frameworkFactory_destroyFramework(framework);
     }
 
-    static void testServices(void) {
-        int rc = 0;
-        array_list_pt exported = NULL;
-        array_list_pt imported = NULL;
-        arrayList_create(&exported);
-        arrayList_create(&imported);
+    static void testServicesCallback(void *handle __attribute__((unused)), void *svc) {
+        auto* rsa = static_cast<remote_service_admin_service_t*>(svc);
+        celix_array_list_t *exported = celix_arrayList_create();
+        celix_array_list_t *imported = celix_arrayList_create();
 
-        rc = rsa->getExportedServices(rsa->admin, &exported);
+        int rc = rsa->getExportedServices(rsa->admin, &exported);
         CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK_EQUAL(0, arrayList_size(exported));
+        CHECK_EQUAL(0, celix_arrayList_size(exported));
 
         rc = rsa->getImportedEndpoints(rsa->admin, &imported);
         CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK_EQUAL(0, arrayList_size(imported));
+        CHECK_EQUAL(0, celix_arrayList_size(imported));
 
-        double result = 0;
-        rc = calc->add(calc->calculator, 2.0, 5.0, &result);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
-        CHECK_EQUAL(7.0, result);
+        celix_arrayList_destroy(imported);
+        celix_arrayList_destroy(exported);
+    }
 
-        arrayList_destroy(imported);
-        arrayList_destroy(exported);
+    static void testServices(void) {
+        celix_service_use_options_t opts{};
+        opts.filter.serviceName = OSGI_RSA_REMOTE_SERVICE_ADMIN;
+        opts.use = testServicesCallback;
+        opts.filter.ignoreServiceLanguage = true;
+        opts.waitTimeoutInSeconds = 0.25;
+        bool called = celix_bundleContext_useServiceWithOptions(context, &opts);
+        CHECK_TRUE(called);
     }
 
-    static void testExportService(void) {
-        int rc = 0;
-        const char *calcId = NULL;
-        array_list_pt regs = NULL;
+    static void testExportServiceCallback(void *handle __attribute__((unused)), void *svc) {
+        auto* rsa = static_cast<remote_service_admin_service_t*>(svc);
 
-        rc = serviceReference_getProperty(calcRef, (char *)"service.id", &calcId);
-        CHECK_EQUAL(CELIX_SUCCESS, rc);
+        char strSvcId[64];
+        snprintf(strSvcId, 64, "%li", calcSvcId);
 
-        rc = rsa->exportService(rsa->admin, (char*)calcId, NULL, &regs);
+        celix_array_list_t *svcRegistration = NULL;
+        int rc = rsa->exportService(rsa->admin, strSvcId, NULL, &svcRegistration);
         CHECK_EQUAL(CELIX_SUCCESS, rc);
 
-        CHECK_EQUAL(1, arrayList_size(regs));
+        CHECK_EQUAL(1, celix_arrayList_size(svcRegistration));
 
-        rc = rsa->exportRegistration_close(rsa->admin,(export_registration_t *)(arrayList_get(regs,0)));
+        rc = rsa->exportRegistration_close(rsa->admin,(export_registration_t *)(arrayList_get(svcRegistration,0)));
         CHECK_EQUAL(CELIX_SUCCESS, rc);
+    }
+
 
+    static void testExportService(void) {
+        celix_service_use_options_t opts{};
+        opts.filter.serviceName = OSGI_RSA_REMOTE_SERVICE_ADMIN;
+        opts.use = testExportServiceCallback;
+        opts.filter.ignoreServiceLanguage = true;
+        opts.waitTimeoutInSeconds = 0.25;
+        bool called = celix_bundleContext_useServiceWithOptions(context, &opts);
+        CHECK_TRUE(called);
     }
 
-    static void testImportService(void) {
+    static void testImportServiceCallback(void *handle __attribute__((unused)), void *svc) {
+        auto *rsa = static_cast<remote_service_admin_service_t *>(svc);
+
         int rc = 0;
         import_registration_t *reg = NULL;
         endpoint_description_t *endpoint = NULL;
@@ -181,6 +148,16 @@ extern "C" {
          */
     }
 
+    static void testImportService(void) {
+        celix_service_use_options_t opts{};
+        opts.filter.serviceName = OSGI_RSA_REMOTE_SERVICE_ADMIN;
+        opts.use = testImportServiceCallback;
+        opts.filter.ignoreServiceLanguage = true;
+        opts.waitTimeoutInSeconds = 0.25;
+        bool called = celix_bundleContext_useServiceWithOptions(context, &opts);
+        CHECK_TRUE(called);
+    }
+
     static void testBundles(void) {
         array_list_pt bundles = NULL;
 
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp b/bundles/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp
index c0d52be..efaee82 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp
+++ b/bundles/remote_services/remote_service_admin_dfi/test/src/run_tests.cpp
@@ -21,5 +21,6 @@
 #include "CppUTest/CommandLineTestRunner.h"
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
\ No newline at end of file
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/src/tst_activator.c b/bundles/remote_services/remote_service_admin_dfi/test/src/tst_activator.c
index 98612e2..5894c73 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/src/tst_activator.c
+++ b/bundles/remote_services/remote_service_admin_dfi/test/src/tst_activator.c
@@ -24,16 +24,19 @@
 
 #include "tst_service.h"
 #include "calculator_service.h"
+#include "remote_example.h"
 #include <unistd.h>
 
 struct activator {
     long svcId;
     struct tst_service testSvc;
 
-    long trackerId;
+    long trackerId1;
+    long trackerId2;
 
     pthread_mutex_t mutex; //protects below
     calculator_service_t *calc;
+    remote_example_t *remoteExample;
 };
 
 static void bndSetCalc(void* handle, void* svc) {
@@ -43,11 +46,15 @@ static void bndSetCalc(void* handle, void* svc) {
     pthread_mutex_unlock(&act->mutex);
 }
 
-static int bndTest(void *handle) {
-    int status = 0;
-    struct activator *act = handle;
+static void bndSetRemoteExample(void* handle, void* svc) {
+    struct activator * act = handle;
+    pthread_mutex_lock(&act->mutex);
+    act->remoteExample = svc;
+    pthread_mutex_unlock(&act->mutex);
+}
 
-    double result = -1.0;
+static bool bndIsCalculatorDiscovered(void *handle) {
+    struct activator *act = handle;
 
     int retries = 40;
 
@@ -64,28 +71,199 @@ static int bndTest(void *handle) {
         pthread_mutex_unlock(&act->mutex);
     }
 
+    bool discovered = local != NULL;
+    return discovered;
+}
+
+static bool bndIsRemoteExampleDiscovered(void *handle) {
+    struct activator *act = handle;
+
+    int retries = 40;
+
+    pthread_mutex_lock(&act->mutex);
+    remote_example_t *local = act->remoteExample;
+    pthread_mutex_unlock(&act->mutex);
+
+    while (local == NULL && retries > 0) {
+        printf("Waiting for remote example service .. %d\n", retries);
+        usleep(100000);
+        --retries;
+        pthread_mutex_lock(&act->mutex);
+        local = act->remoteExample;
+        pthread_mutex_unlock(&act->mutex);
+    }
+
+    bool discovered = local != NULL;
+    return discovered;
+}
+
+static bool bndTestCalculator(void *handle) {
+    struct activator *act = handle;
+
+    double result = -1.0;
 
     pthread_mutex_lock(&act->mutex);
     int rc = 1;
     if (act->calc != NULL) {
-        rc = act->calc->sqrt(act->calc->calculator, 4, &result);
+        rc = act->calc->sqrt(act->calc->handle, 4, &result);
         printf("calc result is %f\n", result);
     } else {
         printf("calc not ready\n");
     }
     pthread_mutex_unlock(&act->mutex);
 
+    return rc == 0 && result == 2.0;
+}
+
+static bool bndTestRemoteString(void *handle) {
+    bool ok;
+    struct activator *act = handle;
+
+    pthread_mutex_lock(&act->mutex);
+    if (act->remoteExample != NULL) {
+        //test string call with taking ownership
+        char *tmp = strndup("test1", 1024);
+        char *result = NULL;
+        act->remoteExample->setName1(act->remoteExample->handle, tmp, &result);
+        //note setName1 should take ownership of tmp, so no free(tmp) needed.
+        ok = strncmp("test1", result, 1024) == 0;
+        free(result);
+    } else {
+        fprintf(stderr, "remote example service not available");
+        ok = false;
+    }
+    pthread_mutex_unlock(&act->mutex);
+
+    return ok;
+}
+
+static bool bndTestRemoteConstString(void *handle) {
+    bool ok;
+    struct activator *act = handle;
+
+    pthread_mutex_lock(&act->mutex);
+    if (act->remoteExample != NULL) {
+        //test pow
+        const char *name = "name2";
+        char *result = NULL;
+        act->remoteExample->setName2(act->remoteExample->handle, name, &result);
+        ok = strncmp(result, "name2", 1024) == 0;
+        free(result);
+    } else {
+        fprintf(stderr, "remote example service not available");
+        ok = false;
+    }
+    pthread_mutex_unlock(&act->mutex);
+
+    return ok;
+}
+
+static bool bndTestRemoteNumbers(void *handle) {
+    bool ok = true;
+    struct activator *act = handle;
+
+    pthread_mutex_lock(&act->mutex);
+    if (act->remoteExample != NULL) {
+
+        if (ok) {
+            //test pow
+            double p;
+            act->remoteExample->pow(act->remoteExample->handle, 2, 2, &p);
+            ok = (p == 4.0);
+        }
+
+        if (ok) {
+            //test fib
+            int32_t f;
+            act->remoteExample->fib(act->remoteExample->handle, 4, &f);
+            ok = (f == 3);
+        }
+    } else {
+        fprintf(stderr, "remote example service not available");
+        ok  = false;
+    }
+    pthread_mutex_unlock(&act->mutex);
+
+    return ok;
+}
+
+static bool bndTestRemoteEnum(void *handle) {
+    bool ok;
+    struct activator *act = handle;
+
+    pthread_mutex_lock(&act->mutex);
+    if (act->remoteExample != NULL) {
+        enum enum_example e = ENUM_EXAMPLE_VAL2;
+        enum enum_example result = ENUM_EXAMPLE_VAL3;
+        int rc = act->remoteExample->setEnum(act->remoteExample->handle, e, &result);
+        ok = rc == 0 && result == ENUM_EXAMPLE_VAL2;
+    } else {
+        fprintf(stderr, "remote example service not available");
+        ok = false;
+    }
+    pthread_mutex_unlock(&act->mutex);
+
+    return ok;
+}
+
+static bool bndTestRemoteAction(void *handle) {
+    bool ok;
+    struct activator *act = handle;
+
+    pthread_mutex_lock(&act->mutex);
+    if (act->remoteExample != NULL) {
+        int rc = act->remoteExample->action(act->remoteExample->handle);
+        ok = rc == 0;
+    } else {
+        fprintf(stderr, "remote example service not available");
+        ok = false;
+    }
+    pthread_mutex_unlock(&act->mutex);
+
+    return ok;
+}
+
+static bool bndTestRemoteComplex(void *handle) {
+    bool ok;
+    struct activator *act = handle;
 
-    if (rc != 0 || result != 2.0) {
-        status = 1;
+    pthread_mutex_lock(&act->mutex);
+    if (act->remoteExample != NULL) {
+       struct complex_input_example exmpl;
+       exmpl.a = 2;
+       exmpl.b = 3;
+       exmpl.n = 5;
+       exmpl.name = "name";
+       exmpl.e = ENUM_EXAMPLE_VAL3;
+       struct complex_output_example* result = NULL;
+       int rc = act->remoteExample->setComplex(act->remoteExample->handle, &exmpl, &result);
+       ok = rc == 0 && result->pow == 8 && result->fib == 5 && strncmp("name", result->name, 64) == 0;
+       if (rc == 0) {
+           free(result->name);
+           free(result);
+       }
+    } else {
+        fprintf(stderr, "remote example service not available");
+        ok = false;
     }
-    return status;
+    pthread_mutex_unlock(&act->mutex);
+
+    return ok;
 }
 
 static celix_status_t bndStart(struct activator *act, celix_bundle_context_t* ctx) {
     //initialize service struct
     act->testSvc.handle = act;
-    act->testSvc.test = bndTest;
+    act->testSvc.isCalcDiscovered = bndIsCalculatorDiscovered;
+    act->testSvc.isRemoteExampleDiscovered = bndIsRemoteExampleDiscovered;
+    act->testSvc.testCalculator = bndTestCalculator;
+    act->testSvc.testRemoteString = bndTestRemoteString;
+    act->testSvc.testRemoteConstString = bndTestRemoteConstString;
+    act->testSvc.testRemoteNumbers = bndTestRemoteNumbers;
+    act->testSvc.testRemoteEnum = bndTestRemoteEnum;
+    act->testSvc.testRemoteAction = bndTestRemoteAction;
+    act->testSvc.testRemoteComplex = bndTestRemoteComplex;
+
 
     //create mutex
     pthread_mutex_init(&act->mutex, NULL);
@@ -97,7 +275,15 @@ static celix_status_t bndStart(struct activator *act, celix_bundle_context_t* ct
         opts.callbackHandle = act;
         opts.filter.serviceName = CALCULATOR_SERVICE;
         opts.filter.ignoreServiceLanguage = true;
-        act->trackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
+        act->trackerId1 = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
+    }
+    {
+        celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
+        opts.set = bndSetRemoteExample;
+        opts.callbackHandle = act;
+        opts.filter.serviceName = REMOTE_EXAMPLE_NAME;
+        opts.filter.ignoreServiceLanguage = true;
+        act->trackerId2 = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
     }
 
     //register test service
@@ -107,7 +293,8 @@ static celix_status_t bndStart(struct activator *act, celix_bundle_context_t* ct
 
 static celix_status_t bndStop(struct activator *act, celix_bundle_context_t* ctx) {
     celix_bundleContext_unregisterService(ctx, act->svcId);
-    celix_bundleContext_stopTracker(ctx, act->trackerId);
+    celix_bundleContext_stopTracker(ctx, act->trackerId1);
+    celix_bundleContext_stopTracker(ctx, act->trackerId2);
     pthread_mutex_destroy(&act->mutex);
     return CELIX_SUCCESS;
 }
diff --git a/bundles/remote_services/remote_service_admin_dfi/test/src/tst_service.h b/bundles/remote_services/remote_service_admin_dfi/test/src/tst_service.h
index 0724794..596ab63 100644
--- a/bundles/remote_services/remote_service_admin_dfi/test/src/tst_service.h
+++ b/bundles/remote_services/remote_service_admin_dfi/test/src/tst_service.h
@@ -24,7 +24,15 @@
 
 struct tst_service {
     void *handle;
-    int (*test)(void *handle);
+    bool (*isCalcDiscovered)(void *handle);
+    bool (*isRemoteExampleDiscovered)(void *handle);
+    bool (*testCalculator)(void *handle);
+    bool (*testRemoteString)(void *handle);
+    bool (*testRemoteConstString)(void *handle);
+    bool (*testRemoteNumbers)(void *handle);
+    bool (*testRemoteEnum)(void *handle);
+    bool (*testRemoteAction)(void *handle);
+    bool (*testRemoteComplex)(void *handle);
 };
 
 typedef struct tst_service tst_service_t;
diff --git a/bundles/shell/shell/CMakeLists.txt b/bundles/shell/shell/CMakeLists.txt
index 1331823..ad65293 100644
--- a/bundles/shell/shell/CMakeLists.txt
+++ b/bundles/shell/shell/CMakeLists.txt
@@ -26,7 +26,7 @@ if (SHELL)
 	install(TARGETS shell_api EXPORT celix COMPONENT shell)
 	install(DIRECTORY api/ DESTINATION include/celix/shell COMPONENT shell)
 
-	if (CELIX_ADD_DEPRECATED_API)
+	if (CELIX_INSTALL_DEPRECATED_API)
 		target_include_directories(shell_api INTERFACE $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/deprecated_api>)
 		install(DIRECTORY deprecated_api/ DESTINATION include/celix/shell COMPONENT shell)
 	endif ()
@@ -54,8 +54,8 @@ if (SHELL)
 	target_include_directories(shell PRIVATE src)
 	target_link_libraries(shell PRIVATE Celix::shell_api CURL::libcurl Celix::log_service_api Celix::log_helper)
 	target_compile_options(shell PRIVATE -Wno-deprecated-declarations)
-	if (CELIX_ADD_DEPRECATED_API)
-		target_compile_definitions(shell PRIVATE CELIX_ADD_DEPRECATED_API)
+	if (CELIX_INSTALL_DEPRECATED_API)
+		target_compile_definitions(shell PRIVATE CELIX_INSTALL_DEPRECATED_API)
 	endif ()
 
 	install_celix_bundle(shell EXPORT celix COMPONENT shell)
diff --git a/bundles/shell/shell/deprecated_api/command.h b/bundles/shell/shell/deprecated_api/command.h
index a65b3e3..0e63e63 100644
--- a/bundles/shell/shell/deprecated_api/command.h
+++ b/bundles/shell/shell/deprecated_api/command.h
@@ -33,6 +33,12 @@
 typedef struct commandService command_service_t;
 typedef command_service_t * command_service_pt;
 
+#ifdef CELIX_ADD_DEPRECATED_ATTRIBUTES
+#define DEP_ATTRIBUTE __attribute__((deprecated("command_service_t is replaced by celix_shell_command_t in celix_shell_command.h")))
+#else
+#define DEP_ATTRIBUTE
+#endif
+
 /**
  * The command service can be used to register additional shell commands.
  * The service should be register with the following properties:
@@ -45,8 +51,7 @@ typedef command_service_t * command_service_pt;
 struct commandService {
     void *handle;
 
-    celix_status_t (*executeCommand)(void *handle, char * commandLine, FILE *outStream, FILE *errorStream)
-        __attribute__((deprecated("command_service_t is replaced by celix_shell_command_t in celix_shell_command.h")));
+    celix_status_t (*executeCommand)(void *handle, char * commandLine, FILE *outStream, FILE *errorStream) DEP_ATTRIBUTE;
 };
 
 
diff --git a/bundles/shell/shell/src/activator.c b/bundles/shell/shell/src/activator.c
index 6e0d80c..34a531f 100644
--- a/bundles/shell/shell/src/activator.c
+++ b/bundles/shell/shell/src/activator.c
@@ -234,7 +234,7 @@ celix_status_t bundleActivator_start(void *activatorData, celix_bundle_context_t
     }
 
     activator->legacyTrackerId = -1L;
-#ifdef CELIX_ADD_DEPRECATED_API
+#ifdef CELIX_INSTALL_DEPRECATED_API
     if (status == CELIX_SUCCESS) {
         celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
         opts.callbackHandle = activator->shell;
diff --git a/bundles/shell/shell/src/help_command.c b/bundles/shell/shell/src/help_command.c
index accf620..fa124bb 100644
--- a/bundles/shell/shell/src/help_command.c
+++ b/bundles/shell/shell/src/help_command.c
@@ -92,6 +92,11 @@ static void printHelp(void *handle, void *svc) {
             free(name);
         }
         celix_arrayList_destroy(commands);
+
+        if (!cmdFound) {
+            fprintf(out, "Command '%s' not found. Type 'help' to get an overview of the available commands\n", sub);
+        }
+
         p->callSucceeded = cmdFound;
     }
 }
diff --git a/bundles/shell/shell/src/shell.c b/bundles/shell/shell/src/shell.c
index 1c2375b..d25cf3a 100644
--- a/bundles/shell/shell/src/shell.c
+++ b/bundles/shell/shell/src/shell.c
@@ -114,7 +114,7 @@ celix_status_t shell_removeCommand(shell_t *shell, celix_shell_command_t *svc, c
     return status;
 }
 
-#ifdef CELIX_ADD_DEPRECATED_API
+#ifdef CELIX_INSTALL_DEPRECATED_API
 celix_status_t shell_addLegacyCommand(shell_t *shell, command_service_t *svc, const celix_properties_t *props) {
     celix_status_t status = CELIX_SUCCESS;
     const char *name = celix_properties_get(props, OSGI_SHELL_COMMAND_NAME, NULL);
@@ -141,7 +141,7 @@ celix_status_t shell_addLegacyCommand(shell_t *shell, command_service_t *svc, co
 }
 #endif
 
-#ifdef CELIX_ADD_DEPRECATED_API
+#ifdef CELIX_INSTALL_DEPRECATED_API
 celix_status_t shell_removeLegacyCommand(shell_t *shell, command_service_t *svc, const celix_properties_t *props) {
     celix_status_t status = CELIX_SUCCESS;
     const char *name = celix_properties_get(props, OSGI_SHELL_COMMAND_NAME, NULL);
diff --git a/bundles/shell/shell/src/shell_private.h b/bundles/shell/shell/src/shell_private.h
index 3b35c52..a185b05 100644
--- a/bundles/shell/shell/src/shell_private.h
+++ b/bundles/shell/shell/src/shell_private.h
@@ -26,7 +26,7 @@
 #include "celix_shell_command.h"
 #include "log_helper.h"
 
-#ifdef CELIX_ADD_DEPRECATED_API
+#ifdef CELIX_INSTALL_DEPRECATED_API
 #include "command.h"
 #endif
 
@@ -39,7 +39,7 @@ typedef struct celix_shell_command_entry {
 } celix_shell_command_entry_t;
 
 
-#ifdef CELIX_ADD_DEPRECATED_API
+#ifdef CELIX_INSTALL_DEPRECATED_API
 typedef struct celix_legacy_command_entry {
     long svcId;
     command_service_t *svc;
@@ -80,7 +80,7 @@ celix_status_t shell_getCommands(shell_t *shell, celix_array_list_t **commands);
 celix_status_t shell_getCommandUsage(shell_t *shell, const char *commandName, char **outUsage);
 celix_status_t shell_getCommandDescription(shell_t *shell, const char *commandName, char **outDescription);
 
-#ifdef CELIX_ADD_DEPRECATED_API
+#ifdef CELIX_INSTALL_DEPRECATED_API
 celix_status_t shell_addLegacyCommand(shell_t *shell, command_service_t *svc, const celix_properties_t *props);
 celix_status_t shell_removeLegacyCommand(shell_t *shell, command_service_t *svc, const celix_properties_t *props);
 #endif
diff --git a/bundles/shell/shell/test/CMakeLists.txt b/bundles/shell/shell/test/CMakeLists.txt
index 868b05e..6df4b32 100644
--- a/bundles/shell/shell/test/CMakeLists.txt
+++ b/bundles/shell/shell/test/CMakeLists.txt
@@ -27,8 +27,8 @@ target_include_directories(test_shell PRIVATE ${CPPUTEST_INCLUDE_DIRS})
 add_dependencies(test_shell shell_bundle)
 target_compile_definitions(test_shell PRIVATE -DSHELL_BUNDLE_LOCATION=\"$<TARGET_PROPERTY:shell,BUNDLE_FILE>\")
 target_compile_options(test_shell PRIVATE -Wno-deprecated-declarations)
-if (CELIX_ADD_DEPRECATED_API)
-    target_compile_definitions(test_shell PRIVATE CELIX_ADD_DEPRECATED_API)
+if (CELIX_INSTALL_DEPRECATED_API)
+    target_compile_definitions(test_shell PRIVATE CELIX_INSTALL_DEPRECATED_API)
 endif ()
 
 add_test(NAME test_shell COMMAND test_shell)
diff --git a/bundles/shell/shell/test/src/shell_tests.cpp b/bundles/shell/shell/test/src/shell_tests.cpp
index 8074555..c0e09f4 100644
--- a/bundles/shell/shell/test/src/shell_tests.cpp
+++ b/bundles/shell/shell/test/src/shell_tests.cpp
@@ -174,7 +174,7 @@ TEST(CelixShellTests, localNameClashTest) {
 
 }
 
-#ifdef CELIX_ADD_DEPRECATED_API
+#ifdef CELIX_INSTALL_DEPRECATED_API
 #include "command.h"
 TEST(CelixShellTests, legacyCommandTest) {
     command_service_t cmdService;
diff --git a/libs/dfi/include/dyn_function.h b/libs/dfi/include/dyn_function.h
index 6a54622..4b92456 100644
--- a/libs/dfi/include/dyn_function.h
+++ b/libs/dfi/include/dyn_function.h
@@ -31,6 +31,11 @@
  * am=handle #void pointer for the handle
  * am=pre #output pointer with memory pre-allocated
  * am=out #output pointer
+ *
+ * text argument (t) can also be annotated to be considered const string.
+ * Normally a text argument will be handled as char*, meaning that the callee is expected to take of ownership.
+ * If a const=true annotation is used the text argument will be handled as a const char*, meaning that the caller
+ * keeps ownership of the string.
  */
 
 typedef struct _dyn_function_type dyn_function_type;
@@ -59,8 +64,16 @@ int dynFunction_call(dyn_function_type *dynFunc, void(*fn)(void), void *returnVa
 int dynFunction_createClosure(dyn_function_type *func, void (*bind)(void *, void **, void*), void *userData, void(**fn)(void));
 int dynFunction_getFnPointer(dyn_function_type *func, void (**fn)(void));
 
+/**
+ * Returns whether the function has a return type.
+ * Will return false if return is void.
+ */
+bool dynFunction_hasReturn(dyn_function_type *dynFunction);
+
 // Avpr parsing
 dyn_function_type * dynFunction_parseAvprWithStr(const char * avpr, const char * fqn);
 dyn_function_type * dynFunction_parseAvpr(FILE * avprStream, const char * fqn);
 
+
+
 #endif
diff --git a/libs/dfi/include/dyn_type.h b/libs/dfi/include/dyn_type.h
index 500764b..1dff59e 100644
--- a/libs/dfi/include/dyn_type.h
+++ b/libs/dfi/include/dyn_type.h
@@ -89,7 +89,7 @@
  * TypedPointer
  * *(Type)
  *
- * MetaInfo TODO
+ * MetaInfo
  * #Name=Value;
  *
  *
diff --git a/libs/dfi/src/avrobin_serializer.c b/libs/dfi/src/avrobin_serializer.c
index 838a204..a7ed37c 100644
--- a/libs/dfi/src/avrobin_serializer.c
+++ b/libs/dfi/src/avrobin_serializer.c
@@ -380,6 +380,9 @@ static int avrobinSerializer_parseAny(dyn_type *type, void *loc, FILE *stream) {
                 status = avrobinSerializer_parseEnum(type, loc, stream);
             }
             break;
+        case 'l':
+            status = avrobinSerializer_parseAny(type->ref.ref, loc, stream);
+            break;
         case 'P' :
             status = ERROR;
             LOG_WARNING("Untyped pointers are not supported for serialization.");
@@ -637,6 +640,9 @@ static int avrobinSerializer_writeAny(dyn_type *type, void *loc, FILE *stream) {
         case 'E' :
             status = avrobinSerializer_writeEnum(type, loc, stream);
             break;
+        case 'l':
+            status = avrobinSerializer_writeAny(type->ref.ref, loc, stream);
+            break;
         case 'P' :
             status = ERROR;
             LOG_WARNING("Untyped pointers are not supported for serialization.");
diff --git a/libs/dfi/src/dyn_function.c b/libs/dfi/src/dyn_function.c
index 802a8d4..56da893 100644
--- a/libs/dfi/src/dyn_function.c
+++ b/libs/dfi/src/dyn_function.c
@@ -23,6 +23,7 @@
 #include <strings.h>
 #include <stdlib.h>
 #include <ffi.h>
+#include <dyn_type_common.h>
 
 static const int OK = 0;
 static const int MEM_ERROR = 1;
@@ -305,3 +306,7 @@ dyn_type * dynFunction_returnType(dyn_function_type *dynFunction) {
     return dynFunction->funcReturn;
 }
 
+bool dynFunction_hasReturn(dyn_function_type *dynFunction) {
+    dyn_type *t = dynFunction_returnType(dynFunction);
+    return t->descriptor != 'V';
+}
\ No newline at end of file
diff --git a/libs/dfi/src/dyn_type.c b/libs/dfi/src/dyn_type.c
index 89a1fa9..09cca39 100644
--- a/libs/dfi/src/dyn_type.c
+++ b/libs/dfi/src/dyn_type.c
@@ -571,27 +571,18 @@ static void dynType_clearTypedPointer(dyn_type *type) {
 }
 
 int dynType_alloc(dyn_type *type, void **bufLoc) {
-    assert(type->type != DYN_TYPE_REF);
-    assert(type->ffiType->size != 0);
     int status = OK;
 
-    void *inst = calloc(1, type->ffiType->size);
-    if (inst != NULL) {
-        if (type->type == DYN_TYPE_TYPED_POINTER) {
-            void *ptr = NULL;
-            dyn_type *sub = NULL;
-            status = dynType_typedPointer_getTypedType(type, &sub);
-            if (status == OK) {
-                status = dynType_alloc(sub, &ptr);
-                if (status == OK) {
-                    *(void **)inst = ptr;
-                }
-            }
-        }
-        *bufLoc = inst;
+    if (type->type == DYN_TYPE_REF) {
+        status = dynType_alloc(type->ref.ref, bufLoc);
     } else {
-        status = MEM_ERROR;
-        LOG_ERROR("Error allocating memory for type '%c'", type->descriptor);
+        void *inst = calloc(1, type->ffiType->size);
+        if (inst != NULL) {
+            *bufLoc = inst;
+        } else {
+            status = MEM_ERROR;
+            LOG_ERROR("Error allocating memory for type '%c'", type->descriptor);
+        }
     }
 
     return status;
@@ -687,6 +678,9 @@ void dynType_deepFree(dyn_type *type, void *loc, bool alsoDeleteSelf) {
         dyn_type *subType = NULL;
         char *text = NULL;
         switch (type->type) {
+            case DYN_TYPE_REF:
+                dynType_deepFree(type->ref.ref, loc, alsoDeleteSelf);
+                break;
             case DYN_TYPE_COMPLEX :
                 dynType_freeComplexType(type, loc);
                 break;
@@ -695,12 +689,19 @@ void dynType_deepFree(dyn_type *type, void *loc, bool alsoDeleteSelf) {
                 break;
             case DYN_TYPE_TYPED_POINTER:
                 dynType_typedPointer_getTypedType(type, &subType);
-                dynType_deepFree(subType, *(void **)loc, true);
+                void *ptrToType = *(void**)loc;
+                dynType_deepFree(subType, ptrToType, true);
                 break;
             case DYN_TYPE_TEXT :
                 text = *(char **)loc;
                 free(text);
                 break;
+            case DYN_TYPE_SIMPLE:
+                //nop
+                break;
+            default:
+                LOG_ERROR("Unexpected switch case. cannot free dyn type %c\n", type->descriptor);
+                break;
         }
 
         if (alsoDeleteSelf) {
diff --git a/libs/dfi/src/json_rpc.c b/libs/dfi/src/json_rpc.c
index 6ff8367..7e62a7c 100644
--- a/libs/dfi/src/json_rpc.c
+++ b/libs/dfi/src/json_rpc.c
@@ -26,6 +26,7 @@
 #include <stdint.h>
 #include <string.h>
 #include <ffi.h>
+#include <dyn_type_common.h>
 
 static int OK = 0;
 static int ERROR = 1;
@@ -106,14 +107,23 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c
 	void *ptr = NULL;
 	void *ptrToPtr = &ptr;
 
-	for (i = 0; i < nrOfArgs; i += 1) {
+	//setup and deserialize input
+	for (i = 0; i < nrOfArgs; ++i) {
 		dyn_type *argType = dynFunction_argumentTypeForIndex(func, i);
 		enum dyn_function_argument_meta  meta = dynFunction_argumentMetaForIndex(func, i);
 		if (meta == DYN_FUNCTION_ARGUMENT_META__STD) {
 			value = json_array_get(arguments, index++);
-			status = jsonSerializer_deserializeJson(argType, value, &(args[i]));
+			void *outPtr = NULL;
+            status = jsonSerializer_deserializeJson(argType, value, &outPtr);
+            args[i] = outPtr;
 		} else if (meta == DYN_FUNCTION_ARGUMENT_META__PRE_ALLOCATED_OUTPUT) {
-			dynType_alloc(argType, &args[i]);
+		    void **instPtr = calloc(1, sizeof(void*));
+		    void *inst = NULL;
+		    dyn_type *subType = NULL;
+		    dynType_typedPointer_getTypedType(argType, &subType);
+            dynType_alloc(subType, &inst);
+            *instPtr = inst;
+            args[i] = instPtr;
 		} else if (meta == DYN_FUNCTION_ARGUMENT_META__OUTPUT) {
 			args[i] = &ptrToPtr;
 		} else if (meta == DYN_FUNCTION_ARGUMENT_META__HANDLE) {
@@ -145,15 +155,28 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c
 		LOG_WARNING("Error calling remote endpoint function, got error code %i", funcCallStatus);
 	}
 
+    //free input args
 	json_t *jsonResult = NULL;
-	for(i = 0; i < nrOfArgs; i += 1) {
+	for(i = 0; i < nrOfArgs; ++i) {
 		dyn_type *argType = dynFunction_argumentTypeForIndex(func, i);
-		enum dyn_function_argument_meta  meta = dynFunction_argumentMetaForIndex(func, i);
+		enum dyn_function_argument_meta meta = dynFunction_argumentMetaForIndex(func, i);
 		if (meta == DYN_FUNCTION_ARGUMENT_META__STD) {
-			dynType_free(argType, args[i]);
+		    if (dynType_descriptorType(argType) == 't') {
+		        const char* isConst = dynType_getMetaInfo(argType, "const");
+		        if (isConst != NULL && strncmp("true", isConst, 5) == 0) {
+		            dynType_free(argType, args[i]);
+		        } else {
+                    //char* -> callee is now owner, no free for char seq needed
+                    //will free the actual pointer
+                    free(args[i]);
+		        }
+		    } else {
+                dynType_free(argType, args[i]);
+            }
 		}
 	}
 
+	//serialize and free output
 	if (funcCallStatus == 0 && status == OK) {
 		for (i = 0; i < nrOfArgs; i += 1) {
 			dyn_type *argType = dynFunction_argumentTypeForIndex(func, i);
@@ -162,7 +185,11 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c
 				if (status == OK) {
 					status = jsonSerializer_serializeJson(argType, args[i], &jsonResult);
 				}
-				dynType_free(argType, args[i]);
+				dyn_type *subType = NULL;
+				dynType_typedPointer_getTypedType(argType, &subType);
+				void **ptrToInst = (void**)args[i];
+				dynType_free(subType, *ptrToInst);
+				free(ptrToInst);
 			} else if (meta == DYN_FUNCTION_ARGUMENT_META__OUTPUT) {
 				if (ptr != NULL) {
 					dyn_type *typedType = NULL;
@@ -183,7 +210,7 @@ int jsonRpc_call(dyn_interface_type *intf, void *service, const char *request, c
 						}
 
 						if (status == OK) {
-							dynType_free(typedTypedType, ptr);
+                            dynType_free(typedTypedType, ptr);
 						}
 					}
 
@@ -247,6 +274,17 @@ int jsonRpc_prepareInvokeRequest(dyn_function_type *func, const char *id, void *
 			json_t *val = NULL;
 
 			int rc = jsonSerializer_serializeJson(type, args[i], &val);
+
+            if (dynType_descriptorType(type) == 't') {
+                const char *metaArgument = dynType_getMetaInfo(type, "const");
+                if (metaArgument != NULL && strncmp("true", metaArgument, 5) == 0) {
+                    //const char * as input -> nop
+                } else {
+                    char **str = args[i];
+                    free(*str); //char * as input -> got ownership -> free it.
+                }
+            }
+
 			if (rc == 0) {
 				json_array_append_new(arguments, val);
 			} else {
@@ -279,14 +317,15 @@ int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]
 	}
 
 	json_t *result = NULL;
+	bool replyHasResult = false;
 	if (status == OK) {
-		result = json_object_get(replyJson, "r"); //TODO check
-		if (result == NULL) {
-			status = ERROR;
-			LOG_ERROR("Cannot find r entry in json reply '%s'", reply);
+		result = json_object_get(replyJson, "r");
+		if (result != NULL) {
+		    replyHasResult = true;
 		}
 	}
 
+	bool replyHandled = false;
 	if (status == OK) {
 		int nrOfArgs = dynFunction_nrOfArguments(func);
 		int i;
@@ -299,19 +338,23 @@ int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]
 
 				size_t size = 0;
 
-				if (dynType_descriptorType(argType) == 't') {
+				if (result == NULL) {
+                    LOG_WARNING("Expected result in reply. got '%s'", reply);
+				} else if (dynType_descriptorType(argType) == 't') {
 					status = jsonSerializer_deserializeJson(argType, result, &tmp);
-					if(tmp!=NULL){
+					if (tmp != NULL) {
 						size = strnlen(((char *) *(char**) tmp), 1024 * 1024);
 						memcpy(*out, *(void**) tmp, size);
 					}
+                    replyHandled = true;
 				} else {
 					dynType_typedPointer_getTypedType(argType, &argType);
 					status = jsonSerializer_deserializeJson(argType, result, &tmp);
-					if(tmp!=NULL){
+					if (tmp != NULL) {
 						size = dynType_size(argType);
 						memcpy(*out, tmp, size);
 					}
+                    replyHandled = true;
 				}
 
 				dynType_free(argType, tmp);
@@ -320,14 +363,22 @@ int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]
 
 				dynType_typedPointer_getTypedType(argType, &subType);
 
-				if (dynType_descriptorType(subType) == 't') {
-					void ***out = (void ***) args[i];
-					status = jsonSerializer_deserializeJson(subType, result, *out);
-				} else {
+                if (result == NULL) {
+                    LOG_WARNING("Expected result in reply. got '%s'", reply);
+                } else if (dynType_descriptorType(subType) == 't') {
+				    char ***out = (char ***) args[i];
+                    char **ptrToString = NULL;
+                    status = jsonSerializer_deserializeJson(subType, result, (void**)&ptrToString);
+                    char *s __attribute__((unused)) = *ptrToString; //note for debug
+                    free(ptrToString);
+                    **out = (void*)s;
+                    replyHandled = true;
+                } else {
 					dyn_type *subSubType = NULL;
 					dynType_typedPointer_getTypedType(subType, &subSubType);
 					void ***out = (void ***) args[i];
 					status = jsonSerializer_deserializeJson(subSubType, result, *out);
+                    replyHandled = true;
 				}
 			} else {
 				//skip
@@ -335,6 +386,10 @@ int jsonRpc_handleReply(dyn_function_type *func, const char *reply, void *args[]
 		}
 	}
 
+	if (replyHasResult && !replyHandled) {
+	    LOG_WARNING("Reply has a result output, but this is not handled by the remote function!. Reply: '%s'", reply);
+	}
+
 	json_decref(replyJson);
 
 	return status;
diff --git a/libs/dfi/src/json_serializer.c b/libs/dfi/src/json_serializer.c
index b09635f..4af5523 100644
--- a/libs/dfi/src/json_serializer.c
+++ b/libs/dfi/src/json_serializer.c
@@ -77,7 +77,11 @@ static int jsonSerializer_createType(dyn_type *type, json_t *val, void **result)
 
     if (dynType_descriptorType(type) == 't') {
         if (json_typeof(val) == JSON_STRING) {
-            inst = strdup(json_string_value(val));
+            //note a deserialized C string is a sequence of memory for the actual string and a
+            //pointer to that sequence. That pointer also needs to reside in the memory (heap).
+            const char *s = json_string_value(val);
+            inst = calloc(1, sizeof(char*));
+            *((char**)inst) = strdup(s);
         } else {
             status = ERROR;
             LOG_ERROR("Expected json_string type got %i\n", json_typeof(val));
@@ -93,8 +97,8 @@ static int jsonSerializer_createType(dyn_type *type, json_t *val, void **result)
 
     if (status == OK) {
         *result = inst;
-    }
-    else{
+    } else {
+        *result = NULL;
     	dynType_free(type, inst);
     }
 
@@ -262,6 +266,9 @@ static int jsonSerializer_parseAny(dyn_type *type, void *loc, json_t *val) {
             status = ERROR;
             LOG_WARNING("Untyped pointer are not supported for serialization");
             break;
+        case 'l':
+            status = jsonSerializer_parseAny(type->ref.ref, loc, val);
+            break;
         default :
             status = ERROR;
             LOG_ERROR("Error provided type '%c' not supported for JSON\n", dynType_descriptorType(type));
@@ -424,6 +431,9 @@ static int jsonSerializer_writeAny(dyn_type *type, void* input, json_t **out) {
         case 'P' :
             LOG_WARNING("Untyped pointer not supported for serialization. ignoring");
             break;
+        case 'l':
+            status = jsonSerializer_writeAny(type->ref.ref, input, out);
+            break;
         default :
             LOG_ERROR("Unsupported descriptor '%c'", descriptor);
             status = ERROR;
diff --git a/libs/dfi/test/dyn_avpr_function_tests.cpp b/libs/dfi/test/dyn_avpr_function_tests.cpp
index 6d8cb94..30fbf79 100644
--- a/libs/dfi/test/dyn_avpr_function_tests.cpp
+++ b/libs/dfi/test/dyn_avpr_function_tests.cpp
@@ -18,6 +18,7 @@
  */
 
 #include <CppUTest/TestHarness.h>
+#include <celix_utils.h>
 #include "CppUTest/CommandLineTestRunner.h"
 
 extern "C" {
@@ -207,9 +208,16 @@ const char* theAvprFile = "{ \
                     \"structStringOutFunc\" : {\
                         \"request\" : [ ],\
                         \"response\" : \"StructString\" \
-                    } \
+                    }, \
+                    \"stringInFunc\" : {\
+                        \"request\" : [{\
+                            \"name\" : \"arg1\",\
+                            \"type\" : \"string\" \
+                        } ],\
+                        \"response\" : \"Void\"\
+                    }\
                 }\
-                }";
+            }";
 
 TEST_GROUP(DynAvprFunctionTests) {
     void setup() override {
@@ -618,3 +626,35 @@ TEST(DynAvprFunctionTests, Example10) {
     free(out.name);
     dynFunction_destroy(dynFunc);
 }
+
+#ifndef __APPLE__
+static int avpr_example11(void *handle __attribute__((unused)), char *arg1) {
+    STRCMP_EQUAL("input string test", arg1);
+    return 0;
+}
+
+//FIXME does not work in OSX. Also has issues in linux if input is not dynamically allocated.
+TEST(DynAvprFunctionTests, Example11) {
+    auto fp = (void(*)()) avpr_example11;
+    dyn_function_type * dynFunc = dynFunction_parseAvprWithStr(theAvprFile, "test.dt.stringInFunc");
+    CHECK(dynFunc != nullptr);
+
+    int handle = 0;
+    int* handle_ptr = &handle;
+
+    char *input = celix_utils_strdup("input string test");
+
+    void *args[2];
+    args[0] = &handle_ptr;
+    args[1]= &input;
+    int rVal = 1;
+
+    int rc = dynFunction_call(dynFunc, fp, &rVal, args);
+    CHECK_EQUAL(0, rc);
+    CHECK_EQUAL(0, rVal);
+
+    free(input);
+
+    dynFunction_destroy(dynFunc);
+}
+#endif
diff --git a/libs/dfi/test/dyn_function_tests.cpp b/libs/dfi/test/dyn_function_tests.cpp
index b5efd15..3073a98 100644
--- a/libs/dfi/test/dyn_function_tests.cpp
+++ b/libs/dfi/test/dyn_function_tests.cpp
@@ -223,6 +223,34 @@ extern "C" {
         dynFunction_destroy(dynFunc);
     }
 
+    #define EXAMPLE5_DESCRIPTOR "example(#const=true;tt)V"
+
+    static void example5Func(const char *s1, char *s2) {
+        STRCMP_EQUAL("s1", s1);
+        STRCMP_EQUAL("s2", s2);
+    }
+
+    static void test_example5(void) {
+        dyn_function_type *dynFunc = NULL;
+        void (*fp)(void) = (void(*)(void)) example5Func;
+        int rc;
+
+        rc = dynFunction_parseWithStr(EXAMPLE5_DESCRIPTOR, NULL, &dynFunc);
+        CHECK_EQUAL(0, rc);
+
+        const char *a1 = "s1";
+        char *a2 = strdup("s2");
+        void *args[2];
+        args[0] = &a1;
+        args[1] = &a2;
+
+        rc = dynFunction_call(dynFunc, fp, NULL, args);
+        CHECK_EQUAL(0, rc);
+
+        dynFunction_destroy(dynFunc);
+    }
+
+
     #define INVALID_FUNC_DESCRIPTOR "example$[D)V"//$ is an invalid symbol, missing (
 
     static void test_invalidDynFunc(void) {
@@ -269,6 +297,10 @@ TEST(DynFunctionTests, DynFuncTest4) {
     test_example4();
 }
 
+TEST(DynFunctionTests, DynFuncTest5) {
+    test_example5();
+}
+
 TEST(DynFunctionTests, InvalidDynFuncTest) {
     test_invalidDynFunc();
     test_invalidDynFuncType();
diff --git a/libs/etcdlib/api/etcd.h b/libs/etcdlib/api/etcd.h
index e75e103..69456af 100644
--- a/libs/etcdlib/api/etcd.h
+++ b/libs/etcdlib/api/etcd.h
@@ -27,6 +27,12 @@ extern "C"
 
 #include "etcdlib.h"
 
+#ifdef CELIX_ADD_DEPRECATED_ATTRIBUTES
+#define DEP_ATTRIBUTE __attribute__((deprecated("etcd_ call are placed by etcdlib_ calls, use etcdlib.h instead of etcd.h")))
+#else
+#define DEP_ATTRIBUTE
+#endif
+
 /**
  * @desc Initialize the ETCD-LIB  with the server/port where Etcd can be reached.
  * @param const char* server. String containing the IP-number of the server.
@@ -34,8 +40,7 @@ extern "C"
  * @param int flags. bitwise flags to control etcdlib initialization. 
  * @return 0 on success, non zero otherwise.
  */
-//__attribute__((deprecated("use etcdlib_create instead")))
-int etcd_init(const char* server, int port, int flags);
+int etcd_init(const char* server, int port, int flags) DEP_ATTRIBUTE;
 
 /**
  * @desc Retrieve a single value from Etcd.
@@ -44,8 +49,7 @@ int etcd_init(const char* server, int port, int flags);
  * @param int* modifiedIndex. If not NULL the Etcd-index of the last modified value.
  * @return 0 on success, non zero otherwise
  */
-//__attribute__((deprecated("use etcdlib_get instead")))
-int etcd_get(const char* key, char** value, int* modifiedIndex);
+int etcd_get(const char* key, char** value, int* modifiedIndex) DEP_ATTRIBUTE;
 
 /**
  * @desc Retrieve the contents of a directory. For every found key/value pair the given callback function is called.
@@ -55,8 +59,7 @@ int etcd_get(const char* key, char** value, int* modifiedIndex);
  * @param int* modifiedIndex. If not NULL the Etcd-index of the last modified value.
  * @return 0 on success, non zero otherwise
  */
-//__attribute__((deprecated("use etcdlib_get_directory instead")))
-int etcd_get_directory(const char* directory, etcdlib_key_value_callback callback, void *arg, long long* modifiedIndex);
+int etcd_get_directory(const char* directory, etcdlib_key_value_callback callback, void *arg, long long* modifiedIndex) DEP_ATTRIBUTE;
 
 /**
  * @desc Setting an Etcd-key/value
@@ -66,8 +69,7 @@ int etcd_get_directory(const char* directory, etcdlib_key_value_callback callbac
  * @param bool prevExist. If true the value is only set when the key already exists, if false it is always set
  * @return 0 on success, non zero otherwise
  */
-//__attribute__((deprecated("use etcdlib_set instead")))
-int etcd_set(const char* key, const char* value, int ttl, bool prevExist);
+int etcd_set(const char* key, const char* value, int ttl, bool prevExist) DEP_ATTRIBUTE;
 
 /**
  * @desc Refresh the ttl of an existing key.
@@ -75,8 +77,7 @@ int etcd_set(const char* key, const char* value, int ttl, bool prevExist);
  * @param ttl the ttl value to use.
  * @return 0 on success, non zero otherwise.
  */
-//__attribute__((deprecated("use etcdlib_refesh instead")))
-int etcd_refresh(const char *key, int ttl);
+int etcd_refresh(const char *key, int ttl) DEP_ATTRIBUTE;
 
 /**
  * @desc Setting an Etcd-key/value and checks if there is a different previous value
@@ -86,16 +87,14 @@ int etcd_refresh(const char *key, int ttl);
  * @param bool always_write. If true the value is written, if false only when the given value is equal to the value in etcd.
  * @return 0 on success, non zero otherwise
  */
-//__attribute__((deprecated("use etcdlib_set_with_check instead")))
-int etcd_set_with_check(const char* key, const char* value, int ttl, bool always_write);
+int etcd_set_with_check(const char* key, const char* value, int ttl, bool always_write) DEP_ATTRIBUTE;
 
 /**
  * @desc Deleting an Etcd-key
  * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
  * @return 0 on success, non zero otherwise
  */
-//__attribute__((deprecated("use etcdlib_del instead")))
-int etcd_del(const char* key);
+int etcd_del(const char* key) DEP_ATTRIBUTE;
 
 /**
  * @desc Watching an etcd directory for changes
@@ -108,8 +107,7 @@ int etcd_del(const char* key);
  * @param long long* modifiedIndex. If not NULL, the index of the modification is written.
  * @return ETCDLIB_RC_OK (0) on success, non zero otherwise. Note that a timeout is signified by a ETCDLIB_RC_TIMEOUT return code.
  */
-//__attribute__((deprecated("use etcdlib_watch instead")))
-int etcd_watch(const char* key, long long index, char** action, char** prevValue, char** value, char** rkey, long long* modifiedIndex);
+int etcd_watch(const char* key, long long index, char** action, char** prevValue, char** value, char** rkey, long long* modifiedIndex) DEP_ATTRIBUTE;
 
 #ifdef __cplusplus
 }
diff --git a/libs/framework/src/celix_framework_factory.c b/libs/framework/src/celix_framework_factory.c
index ce004e5..098f80e 100644
--- a/libs/framework/src/celix_framework_factory.c
+++ b/libs/framework/src/celix_framework_factory.c
@@ -19,7 +19,7 @@
 
 #include "celix_framework_factory.h"
 
-framework_t* celix_frameworkFactory_createFramework(properties_t *config) {
+framework_t* celix_frameworkFactory_createFramework(celix_properties_t *config) {
     framework_t* fw = NULL;
 
     if (config == NULL) {