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

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


The following commit(s) were added to refs/heads/feature/cxx_rsa_update by this 
push:
     new 9cbbdc5  Adds initial integration gtest for remote services
9cbbdc5 is described below

commit 9cbbdc5b85741ff147b6d6e077ce818bc4f2d4bc
Author: Pepijn Noltes <[email protected]>
AuthorDate: Tue May 11 19:37:27 2021 +0200

    Adds initial integration gtest for remote services
---
 bundles/cxx_remote_services/CMakeLists.txt         |   4 +-
 .../admin/include/RemoteServiceAdmin.h             |  10 +-
 .../admin/src/RemoteServiceAdmin.cc                |   2 +
 bundles/cxx_remote_services/common/CMakeLists.txt  |  32 ---
 .../common/include/ExportedServiceFactory.h        | 105 ---------
 .../common/include/IExportedService.h              |  25 ---
 .../common/include/ImportedServiceFactory.h        |  98 ---------
 bundles/cxx_remote_services/common/src/common.cc   |   2 -
 .../discovery_configured/CMakeLists.txt            |   1 +
 .../cxx_remote_services/examples/CMakeLists.txt    | 108 ----------
 .../examples/HardcodedExampleProvider.cc           | 142 ------------
 .../examples/HardcodedExampleSerializer.cc         | 239 ---------------------
 .../examples/HardcodedExampleSerializer.h          |  91 --------
 .../examples/HardcodedExampleSubscriber.cc         | 207 ------------------
 .../examples/IHardcodedService.h                   |  34 ---
 .../examples/discovery/endpoint.json               |  26 ---
 .../pubsub_properties/IHardcodedService.properties |  27 ---
 .../cxx_remote_services/integration/CMakeLists.txt |   9 +-
 .../integration/gtest/CMakeLists.txt               |  67 ++++++
 .../src/RemoteServicesIntegrationTestSuite.cc      |  78 +++++++
 .../integration/src/CalculatorConsumer.cc          |  58 ++---
 .../logging/log_helper/include/celix/LogHelper.h   |   2 +
 cmake/cmake_celix/Generic.cmake                    |  25 +++
 libs/framework/include/celix/Bundle.h              |   3 +-
 libs/framework/include/celix/Constants.h           |   8 +
 25 files changed, 225 insertions(+), 1178 deletions(-)

diff --git a/bundles/cxx_remote_services/CMakeLists.txt 
b/bundles/cxx_remote_services/CMakeLists.txt
index 06bbd6b..30f3d3c 100644
--- a/bundles/cxx_remote_services/CMakeLists.txt
+++ b/bundles/cxx_remote_services/CMakeLists.txt
@@ -18,7 +18,6 @@
 celix_subproject(REMOTE_SERVICE_ADMIN "Option to enable building the C++17 
Remote Service Admin Service bundles" OFF)
 if (REMOTE_SERVICE_ADMIN)
     message(WARNING "The C++ Remote Service Admin is still experimental; The 
API, SPI and implementation is not stable and will change")
-    #add_subdirectory(common)
     add_subdirectory(rsa_spi)
     add_subdirectory(admin)
     add_subdirectory(discovery_configured)
@@ -28,7 +27,6 @@ if (REMOTE_SERVICE_ADMIN)
     endif()
 
 
-    #NOTE the toplogy manager is not yet used. The discovery and RSA need to 
be refactor for this
+    #NOTE the topology manager is not yet used. The discovery and RSA need to 
be refactor for this
     #add_subdirectory(topology_manager)
-    #add_subdirectory(examples)
 endif()
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h 
b/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
index 454ff90..969a095 100644
--- a/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
+++ b/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
@@ -17,10 +17,13 @@
  * under the License.
  */
 
-#include "celix/rsa/EndpointDescription.h"
-#include <celix_api.h>
+
 #include <mutex>
+
 #include "celix/LogHelper.h"
+#include "celix/rsa/EndpointDescription.h"
+#include <celix/rsa/IImportServiceFactory.h>
+#include <celix/rsa/IExportServiceFactory.h>
 
 #if defined(__has_include) && __has_include(<version>)
 #include <version>
@@ -28,9 +31,6 @@
 
 #if __cpp_lib_memory_resource
 #include <memory_resource>
-#include <celix/rsa/IImportServiceFactory.h>
-#include <celix/rsa/IExportServiceFactory.h>
-
 #endif
 
 namespace celix::rsa {
diff --git a/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc 
b/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
index 9a1e09e..207feec 100644
--- a/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
+++ b/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
@@ -18,6 +18,8 @@
  */
 
 #include "RemoteServiceAdmin.h"
+#include "celix/BundleContext.h"
+#include "celix/BundleActivator.h"
 #include "celix/rsa/RemoteConstants.h"
 #include "celix/rsa/IImportServiceFactory.h"
 #include "celix/rsa/IExportServiceFactory.h"
diff --git a/bundles/cxx_remote_services/common/CMakeLists.txt 
b/bundles/cxx_remote_services/common/CMakeLists.txt
deleted file mode 100644
index 42888bd..0000000
--- a/bundles/cxx_remote_services/common/CMakeLists.txt
+++ /dev/null
@@ -1,32 +0,0 @@
-# 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.
-
-add_library(async_rsa_common INTERFACE)
-target_include_directories(async_rsa_common INTERFACE
-        $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
-        $<INSTALL_INTERFACE:include/celix/async_rsa_common>
-        )
-target_compile_options(async_rsa_common INTERFACE -std=c++17)
-target_link_libraries(async_rsa_common INTERFACE Celix::pubsub_spi 
Celix::pubsub_api Celix::rsa_spi)
-#set_target_properties(async_rsa_common PROPERTIES OUTPUT_NAME 
"celix_async_rsa_common")
-#target_include_directories(async_rsa_common PRIVATE src)
-#target_link_libraries(async_rsa_common INTERFACE Celix::framework)
-
-#Setup target aliases to match external usage
-add_library(Celix::async_rsa_common ALIAS async_rsa_common)
-install(TARGETS async_rsa_common EXPORT celix DESTINATION 
${CMAKE_INSTALL_LIBDIR} COMPONENT async_rsa_common)
-install(DIRECTORY include/ DESTINATION include/celix/async_rsa_common 
COMPONENT async_rsa_common)
diff --git 
a/bundles/cxx_remote_services/common/include/ExportedServiceFactory.h 
b/bundles/cxx_remote_services/common/include/ExportedServiceFactory.h
deleted file mode 100644
index 1db4bae..0000000
--- a/bundles/cxx_remote_services/common/include/ExportedServiceFactory.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * 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.
- */
-#pragma once
-
-#include <celix/dm/DependencyManager.h>
-#include <pubsub_endpoint.h>
-#include <IExportedService.h>
-#include "celix/rsa/EndpointDescription.h"
-
-namespace celix::async_rsa {
-    /// Service factory interface.
-    struct IExportedServiceFactory {
-        virtual ~IExportedServiceFactory() = default;
-
-        virtual celix::dm::BaseComponent& create(void* svc, std::string 
endpointId) = 0;
-    };
-
-    /// Default templated Exported service factory. If more than a simple 
creation is needed, please create your own factory derived from 
IExportedServiceFactory
-    /// \tparam Interface
-    /// \tparam Implementation
-    template <typename SvcInterfaceT, typename WrapperT>
-    struct DefaultExportedServiceFactory final : public 
IExportedServiceFactory {
-        static_assert(std::is_constructible_v<WrapperT, SvcInterfaceT*>, 
"Wrapper needs to be constructible from a pointer to the type of svc it wraps");
-        static_assert(std::is_base_of_v<celix::async_rsa::IExportedService, 
WrapperT>, "Wrapper needs to implement the IExportedService interface");
-
-        explicit DefaultExportedServiceFactory(const 
std::shared_ptr<celix::dm::DependencyManager> &mng) noexcept : _mng(mng), 
_topic(SvcInterfaceT::NAME) {
-            std::cout << 
"[DefaultExportedServiceFactory::DefaultExportedServiceFactory]" << std::endl;
-        }
-        explicit DefaultExportedServiceFactory(const 
std::shared_ptr<celix::dm::DependencyManager> &mng, std::string topic) noexcept 
: _mng(mng), _topic(std::move(topic)) {
-            std::cout << 
"[DefaultExportedServiceFactory::DefaultExportedServiceFactory]" << std::endl;
-        }
-
-        ~DefaultExportedServiceFactory() noexcept final {
-            std::cout << 
"[DefaultExportedServiceFactory::~DefaultExportedServiceFactory]" << std::endl;
-            for (auto &[id, cmp] : _subCmps) {
-                celix_bundleContext_unregisterService(_mng->bundleContext(), 
id);
-            }
-            _subCmps.clear();
-            _mng = nullptr;
-        }
-
-        celix::dm::BaseComponent& create(void* svc, std::string endpointId) 
final {
-            std::cout << "[DefaultExportedServiceFactory::create]" << 
std::endl;
-
-            auto &cmp = _mng->template 
createComponent<WrapperT>(std::make_unique<WrapperT>(static_cast<SvcInterfaceT*>(svc)),
 std::string{WrapperT::NAME})
-                    .template 
addInterface<celix::async_rsa::IExportedService>(std::string{SvcInterfaceT::VERSION},
 Properties{{celix::rsa::Endpoint::EXPORTS, std::string{SvcInterfaceT::NAME}}, 
{celix::rsa::Endpoint::IMPORTED, "false"}, {celix::rsa::Endpoint::IDENTIFIER, 
endpointId}});
-
-            cmp.template 
createCServiceDependency<pubsub_publisher_t>(PUBSUB_PUBLISHER_SERVICE_NAME)
-                    .setVersionRange("[3.0.0,4)")
-                    
.setFilter(std::string{"(topic="}.append(_topic).append("Ret_").append(endpointId).append(")"))
-                    .setCallbacks([&cmp](const pubsub_publisher_t * pub, 
Properties&&){ cmp.getInstance().setPublisher(pub); })
-                    .setRequired(true)
-                    .build();
-            cmp.template 
createCServiceDependency<pubsub_subscriber_t>(PUBSUB_SUBSCRIBER_SERVICE_NAME)
-                    .setVersionRange("[3.0.0,4)")
-                    
.setFilter(std::string{"(topic="}.append(_topic).append("Args_").append(endpointId).append(")"))
-                    .setRequired(true)
-                    .build();
-
-            auto sub = std::make_unique<pubsub_subscriber_t>();
-            sub->handle = &cmp.getInstance();
-            sub->init = [](void *) -> int {
-                return 0;
-            };
-            sub->receive = [](void *handle, const char *msgType, unsigned int 
msgTypeId, void *msg, const celix_properties_t *metadata, bool *){ return 
static_cast<WrapperT*>(handle)->receiveMessage(msgType, msgTypeId, msg, 
metadata); };
-
-            auto *props = celix_properties_create();
-            celix_properties_set(props, PUBSUB_SUBSCRIBER_TOPIC, 
std::string{""}.append(_topic).append("Args_").append(endpointId).c_str());
-
-            celix_service_registration_options_t opts{};
-            opts.serviceName = PUBSUB_SUBSCRIBER_SERVICE_NAME;
-            opts.serviceVersion = PUBSUB_SUBSCRIBER_SERVICE_VERSION;
-            opts.svc = sub.get();
-            opts.properties = props;
-
-            long id = 
celix_bundleContext_registerServiceWithOptions(_mng->bundleContext(), &opts);
-
-            _subCmps.emplace_back(id, std::move(sub));
-            cmp.build();
-
-            return cmp;
-        }
-
-    private:
-        std::shared_ptr<celix::dm::DependencyManager> _mng{};
-        std::string _topic{};
-        std::vector<std::pair<long, std::unique_ptr<pubsub_subscriber_t>>> 
_subCmps{};
-    };
-}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/common/include/IExportedService.h 
b/bundles/cxx_remote_services/common/include/IExportedService.h
deleted file mode 100644
index 104427a..0000000
--- a/bundles/cxx_remote_services/common/include/IExportedService.h
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- */
-#pragma once
-
-namespace celix::async_rsa {
-    struct IExportedService {
-        virtual ~IExportedService() = default;
-    };
-}
diff --git 
a/bundles/cxx_remote_services/common/include/ImportedServiceFactory.h 
b/bundles/cxx_remote_services/common/include/ImportedServiceFactory.h
deleted file mode 100644
index 6a342f7..0000000
--- a/bundles/cxx_remote_services/common/include/ImportedServiceFactory.h
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- * 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.
- */
-#pragma once
-
-#include <celix/dm/DependencyManager.h>
-
-namespace celix::async_rsa {
-    /// Service factory interface.
-    struct IImportedServiceFactory {
-        virtual ~IImportedServiceFactory() = default;
-
-        virtual celix::dm::BaseComponent& create(std::string endpointId) = 0;
-    };
-
-    /// Default templated imported service factory. If more than a simple 
creation is needed, please create your own factory derived from 
IImportedServiceFactory
-    /// \tparam Interface
-    /// \tparam Implementation
-    template <typename Interface, typename Implementation>
-    struct DefaultImportedServiceFactory final : public 
IImportedServiceFactory {
-        static_assert(std::is_base_of_v<Interface, Implementation>, 
"Implementation needs to implement Interface");
-
-        explicit DefaultImportedServiceFactory(const 
std::shared_ptr<celix::dm::DependencyManager> &mng) noexcept : _mng(mng), 
_topic(Interface::NAME) {
-        }
-        explicit DefaultImportedServiceFactory(const 
std::shared_ptr<celix::dm::DependencyManager> &mng, std::string topic) noexcept 
: _mng(mng), _topic(std::move(topic)) {
-            std::cout << 
"[DefaultExportedServiceFactory::DefaultExportedServiceFactory]" << std::endl;
-        }
-
-        ~DefaultImportedServiceFactory() noexcept final {
-            std::cout << "~DefaultImportedServiceFactory" << std::endl;
-            for (auto &[id, cmp] : _subCmps) {
-                celix_bundleContext_unregisterService(_mng->bundleContext(), 
id);
-            }
-            _subCmps.clear();
-            _mng = nullptr;
-        }
-
-        celix::dm::BaseComponent& create(std::string endpointId) final {
-            auto &cmp = _mng->template 
createComponent<Implementation>(std::string{Interface::NAME})
-                .template 
addInterface<Interface>(std::string{Interface::VERSION});
-
-            cmp.template 
createCServiceDependency<pubsub_publisher_t>(PUBSUB_PUBLISHER_SERVICE_NAME)
-                    .setVersionRange("[3.0.0,4)")
-                    
.setFilter(std::string{"(topic="}.append(_topic).append("Args_").append(endpointId).append(")"))
-                    .setCallbacks([&cmp](const pubsub_publisher_t * pub, 
Properties&&){ cmp.getInstance().setPublisher(pub); })
-                    .setRequired(true)
-                    .build();
-            cmp.template 
createCServiceDependency<pubsub_subscriber_t>(PUBSUB_SUBSCRIBER_SERVICE_NAME)
-                    .setVersionRange("[3.0.0,4)")
-                    
.setFilter(std::string{"(topic="}.append(_topic).append("Ret_").append(endpointId).append(")"))
-                    .setRequired(true)
-                    .build();
-
-            auto sub = std::make_unique<pubsub_subscriber_t>();
-            sub->handle = &cmp.getInstance();
-            sub->init = [](void *) -> int {
-                return 0;
-            };
-            sub->receive = [](void *handle, const char *msgType, unsigned int 
msgTypeId, void *msg, const celix_properties_t *metadata, bool *){ return 
static_cast<Implementation*>(handle)->receiveMessage(msgType, msgTypeId, msg, 
metadata); };
-
-            auto *props = celix_properties_create();
-            celix_properties_set(props, PUBSUB_SUBSCRIBER_TOPIC, 
std::string{""}.append(_topic).append("Ret_").append(endpointId).c_str());
-
-            celix_service_registration_options_t opts{};
-            opts.serviceName = PUBSUB_SUBSCRIBER_SERVICE_NAME;
-            opts.serviceVersion = PUBSUB_SUBSCRIBER_SERVICE_VERSION;
-            opts.svc = sub.get();
-            opts.properties = props;
-
-            long id = 
celix_bundleContext_registerServiceWithOptions(_mng->bundleContext(), &opts);
-
-            _subCmps.emplace_back(id, std::move(sub));
-            cmp.build();
-
-            return cmp;
-        }
-
-    private:
-        std::shared_ptr<celix::dm::DependencyManager> _mng{};
-        std::string _topic{};
-        std::vector<std::pair<long, std::unique_ptr<pubsub_subscriber_t>>> 
_subCmps{};
-    };
-}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/common/src/common.cc 
b/bundles/cxx_remote_services/common/src/common.cc
deleted file mode 100644
index 723bd5e..0000000
--- a/bundles/cxx_remote_services/common/src/common.cc
+++ /dev/null
@@ -1,2 +0,0 @@
-
-// empty
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt 
b/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt
index 833b718..39850ef 100644
--- a/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt
+++ b/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt
@@ -22,6 +22,7 @@ add_library(RsaConfiguredDiscovery_api INTERFACE)
 target_include_directories(RsaConfiguredDiscovery_api INTERFACE
         include
 )
+add_library(Celix::RsaConfiguredDiscovery_api ALIAS RsaConfiguredDiscovery_api)
 
 add_celix_bundle(RsaConfiguredDiscovery
     VERSION 0.9.0
diff --git a/bundles/cxx_remote_services/examples/CMakeLists.txt 
b/bundles/cxx_remote_services/examples/CMakeLists.txt
deleted file mode 100644
index 3aa8ee4..0000000
--- a/bundles/cxx_remote_services/examples/CMakeLists.txt
+++ /dev/null
@@ -1,108 +0,0 @@
-# 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.
-
-add_celix_bundle(hardcoded_example_provider
-        SOURCES
-        HardcodedExampleProvider.cc
-        HardcodedExampleSerializer.cc
-        SYMBOLIC_NAME "apache_celix_hardcoded_example_service_provider"
-        VERSION 0.0.1
-        )
-add_celix_bundle(hardcoded_example_subscriber
-        SOURCES
-        HardcodedExampleSubscriber.cc
-        HardcodedExampleSerializer.cc
-        SYMBOLIC_NAME "apache_celix_hardcoded_example_service_subscriber"
-        VERSION 0.0.1
-        )
-
-celix_bundle_files(hardcoded_example_provider
-        
${CMAKE_CURRENT_SOURCE_DIR}/pubsub_properties/IHardcodedService.properties
-        DESTINATION "META-INF/topics/pub"
-        )
-celix_bundle_files(hardcoded_example_provider
-        
${CMAKE_CURRENT_SOURCE_DIR}/pubsub_properties/IHardcodedService.properties
-        DESTINATION "META-INF/topics/sub"
-        )
-
-celix_bundle_files(hardcoded_example_subscriber
-        
${CMAKE_CURRENT_SOURCE_DIR}/pubsub_properties/IHardcodedService.properties
-        DESTINATION "META-INF/topics/pub"
-        )
-celix_bundle_files(hardcoded_example_subscriber
-        
${CMAKE_CURRENT_SOURCE_DIR}/pubsub_properties/IHardcodedService.properties
-        DESTINATION "META-INF/topics/sub"
-        )
-
-target_link_libraries(hardcoded_example_provider PRIVATE Celix::framework 
Celix::async_rsa_common)
-target_link_libraries(hardcoded_example_subscriber PRIVATE Celix::framework 
Celix::async_rsa_common)
-target_compile_options(hardcoded_example_provider INTERFACE -std=c++17)
-target_compile_options(hardcoded_example_subscriber INTERFACE -std=c++17)
-
-set(PUBSUB_CONTAINER_LIBS
-        Jansson
-        ZMQ::lib
-        CZMQ::lib
-        Celix::pubsub_api
-        Celix::pubsub_spi
-        Celix::async_rsa_common
-        Celix::Promises)
-
-find_package(ZMQ REQUIRED)
-find_package(CZMQ REQUIRED)
-find_package(Jansson REQUIRED)
-add_celix_container(hardcoded_example_provider_cnt
-        GROUP async_rsa
-        BUNDLES
-        Celix::log_admin
-        Celix::shell
-        Celix::shell_tui
-        Celix::pubsub_serializer_json
-        Celix::pubsub_discovery_etcd
-        Celix::pubsub_topology_manager
-        Celix::pubsub_admin_zmq_v2
-        Celix::pubsub_protocol_wire_v2
-        Celix::async_rsa_discovery_configured
-        Celix::async_topology_manager
-        Celix::RemoteServiceAdmin
-        hardcoded_example_provider
-        PROPERTIES
-        "org.osgi.framework.storage=.publisherCache"
-        
"CELIX_ASYNC_RSA_CONFIGURED_DISCOVERY_FILE=/home/oipo-unencrypted/Programming/celix/bundles/async_remote_services/examples/discovery/endpoint.json"
-        )
-target_link_libraries(hardcoded_example_provider PRIVATE 
${PUBSUB_CONTAINER_LIBS})
-
-add_celix_container(hardcoded_example_subscriber_cnt
-        GROUP async_rsa
-        BUNDLES
-        Celix::log_admin
-        Celix::shell
-        Celix::shell_tui
-        Celix::pubsub_serializer_json
-        Celix::pubsub_discovery_etcd
-        Celix::pubsub_topology_manager
-        Celix::pubsub_admin_zmq_v2
-        Celix::pubsub_protocol_wire_v2
-        Celix::async_rsa_discovery_configured
-        Celix::async_topology_manager
-        Celix::RemoteServiceAdmin
-        hardcoded_example_subscriber
-        PROPERTIES
-        "org.osgi.framework.storage=.subscriberCache"
-        
"CELIX_ASYNC_RSA_CONFIGURED_DISCOVERY_FILE=/home/oipo-unencrypted/Programming/celix/bundles/async_remote_services/examples/discovery/endpoint.json"
-        )
-target_link_libraries(hardcoded_example_subscriber PRIVATE 
${PUBSUB_CONTAINER_LIBS})
diff --git a/bundles/cxx_remote_services/examples/HardcodedExampleProvider.cc 
b/bundles/cxx_remote_services/examples/HardcodedExampleProvider.cc
deleted file mode 100644
index 4cbbc11..0000000
--- a/bundles/cxx_remote_services/examples/HardcodedExampleProvider.cc
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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 <celix_api.h>
-#include <string>
-#include <celix/Deferred.h>
-#include <pubsub/api.h>
-#include "HardcodedExampleSerializer.h"
-#include "IHardcodedService.h"
-#include <IExportedService.h>
-#include <celix/PromiseFactory.h>
-#include <ExportedServiceFactory.h>
-
-struct HardcodedService final : public IHardcodedService {
-    HardcodedService() {
-        std::cout << "started HardcodedService" << std::endl;
-    }
-    ~HardcodedService() final = default;
-
-    celix::Promise<int> add(int a, int b) noexcept final {
-        std::cout << "[HardcodedService] add " << a << " + " << b << std::endl;
-        auto deferred = _factory.deferred<int>();
-        deferred.resolve(a + b);
-        return deferred.getPromise();
-    }
-
-    celix::Promise<int> subtract(int a, int b) noexcept final {
-        std::cout << "[HardcodedService] subtract " << a << " + " << b << 
std::endl;
-        auto deferred = _factory.deferred<int>();
-        deferred.resolve(a - b);
-        return deferred.getPromise();
-    }
-
-    celix::Promise<std::string> toString(int a) noexcept final {
-        std::cout << "[HardcodedService] toString " << a << std::endl;
-        auto deferred = _factory.deferred<std::string>();
-        deferred.resolve(std::to_string(a));
-        return deferred.getPromise();
-    }
-
-private:
-    celix::PromiseFactory _factory{};
-};
-
-struct ExportedHardcodedService final : public 
celix::async_rsa::IExportedService {
-
-    static constexpr std::string_view VERSION = "1.0.0";
-    static constexpr std::string_view NAME = "ExportedHardcodedService";
-
-    ExportedHardcodedService(IHardcodedService *svc) noexcept : _svc(svc) {};
-    ~ExportedHardcodedService() final = default;
-
-    ExportedHardcodedService(ExportedHardcodedService const &) = delete;
-    ExportedHardcodedService(ExportedHardcodedService &&) = default;
-    ExportedHardcodedService& operator=(ExportedHardcodedService const &) = 
delete;
-    ExportedHardcodedService& operator=(ExportedHardcodedService &&) = default;
-
-    void setPublisher(pubsub_publisher_t const * publisher) {
-        _publisher = publisher;
-    }
-
-    int receiveMessage(const char *, unsigned int msgTypeId, void *msg, const 
celix_properties_t *) {
-        std::cout << "[ExportedHardcodedService] receiveMessage" << std::endl;
-        if(msgTypeId == 1) {
-            auto response = static_cast<AddArgs*>(msg);
-
-            if(response->ret) {
-                return 0;
-            }
-
-            response->ret = _svc->add(response->a, response->b).getValue();
-            _publisher->send(_publisher->handle, 1, response, nullptr);
-        } else if(msgTypeId == 2) {
-            auto response = static_cast<SubtractArgs*>(msg);
-
-            if(response->ret) {
-                return 0;
-            }
-
-            response->ret = _svc->subtract(response->a, 
response->b).getValue();
-            _publisher->send(_publisher->handle, 1, response, nullptr);
-        } else if(msgTypeId == 3) {
-            auto response = static_cast<ToStringArgs*>(msg);
-
-            if(response->ret) {
-                return 0;
-            }
-
-            response->ret = _svc->toString(response->a).getValue();
-            _publisher->send(_publisher->handle, 1, response, nullptr);
-        }
-
-        return 0;
-    }
-
-private:
-    IHardcodedService *_svc{};
-    pubsub_publisher_t const *_publisher{};
-};
-
-class ExampleActivator {
-public:
-    explicit ExampleActivator(const 
std::shared_ptr<celix::dm::DependencyManager>& mng) {
-        std::cout << "[ExampleActivator::ExampleActivator]" << std::endl;
-        _addArgsSerializer.emplace(mng);
-        _subtractArgsSerializer.emplace(mng);
-        _toStringSerializer.emplace(mng);
-
-        
mng->createComponent<HardcodedService>().addInterfaceWithName<IHardcodedService>(std::string{IHardcodedService::NAME},
 std::string{IHardcodedService::VERSION}, Properties{{"remote", "true"}, 
{celix::rsa::Endpoint::IDENTIFIER, "id-01"}, {celix::rsa::Endpoint::EXPORTS, 
"IHardcodedService"}}).build();
-        auto& factory = 
mng->createComponent(std::make_unique<celix::async_rsa::DefaultExportedServiceFactory<IHardcodedService,
 ExportedHardcodedService>>(mng))
-                
.addInterface<celix::async_rsa::IExportedServiceFactory>("1.0.0", 
Properties{{celix::rsa::Endpoint::EXPORTS, "IHardcodedService"}}).build();
-
-        _factory = &factory;
-    }
-
-    ExampleActivator(const ExampleActivator &) = delete;
-    ExampleActivator &operator=(const ExampleActivator &) = delete;
-
-private:
-    std::optional<AddArgsSerializer> _addArgsSerializer{};
-    std::optional<SubtractArgsSerializer> _subtractArgsSerializer{};
-    std::optional<ToStringArgsSerializer> _toStringSerializer{};
-    
Component<celix::async_rsa::DefaultExportedServiceFactory<IHardcodedService, 
ExportedHardcodedService>> *_factory{};
-};
-
-CELIX_GEN_CXX_BUNDLE_ACTIVATOR(ExampleActivator)
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/examples/HardcodedExampleSerializer.cc 
b/bundles/cxx_remote_services/examples/HardcodedExampleSerializer.cc
deleted file mode 100644
index a0452e2..0000000
--- a/bundles/cxx_remote_services/examples/HardcodedExampleSerializer.cc
+++ /dev/null
@@ -1,239 +0,0 @@
-//
-// Created by oipo on 01-03-21.
-//
-
-#include "HardcodedExampleSerializer.h"
-#include <rapidjson/document.h>
-#include <rapidjson/writer.h>
-
-AddArgsSerializer::AddArgsSerializer(std::shared_ptr<celix::dm::DependencyManager>
 mng) : _mng(std::move(mng)) {
-    _svc.deserialize = [](void*, const struct iovec* input, size_t, void** 
out) -> celix_status_t {
-        rapidjson::Document d{};
-        d.Parse(static_cast<char*>(input->iov_base));
-
-        if(d.HasParseError()) {
-            return CELIX_ILLEGAL_ARGUMENT;
-        }
-
-        int id = d["id"].GetInt();
-        int a = d["a"].GetInt();
-        int b = d["b"].GetInt();
-        decltype(AddArgs::ret) ret = d.HasMember("ret") ? d["ret"].GetInt() : 
decltype(AddArgs::ret){};
-
-        *out = new AddArgs{id, a, b, ret};
-
-        return CELIX_SUCCESS;
-    };
-    _svc.freeDeserializedMsg = [](void*, void* msg) {
-        delete static_cast<AddArgs*>(msg);
-    };
-
-    _svc.serialize = [](void*, const void* input, struct iovec** output, 
size_t* outputIovLen) -> celix_status_t {
-        auto *args = static_cast<AddArgs const *>(input);
-
-        if (*output == nullptr) {
-            *output = static_cast<iovec *>(calloc(1, sizeof(struct iovec)));
-            if (outputIovLen){
-                *outputIovLen = 1;
-            }
-        }
-
-        rapidjson::StringBuffer sb;
-        rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
-
-        writer.StartObject();
-
-        writer.String("id");
-        writer.Int(args->id);
-
-        writer.String("a");
-        writer.Int(args->a);
-
-        writer.String("b");
-        writer.Int(args->b);
-
-        if(args->ret) {
-            writer.String("ret");
-            writer.Int(args->ret.value());
-        }
-
-        writer.EndObject();
-
-        (*output)->iov_base = strndup(sb.GetString(), sb.GetSize() + 1);
-        (*output)->iov_len = sb.GetSize() + 1;
-
-        return CELIX_SUCCESS;
-    };
-
-    _svc.freeSerializedMsg = [](void*, struct iovec* input, size_t) {
-        free(input->iov_base);
-        free(input);
-    };
-
-    celix_properties_t* props = celix_properties_create();
-    celix_properties_set(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_MSG_FQN_PROPERTY, "AddArgs");
-    celix_properties_set(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_MSG_VERSION_PROPERTY, "1.0.0");
-    celix_properties_setLong(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_MSG_ID_PROPERTY, 1LL);
-    celix_properties_set(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_SERIALIZATION_TYPE_PROPERTY, "json");
-
-    celix_service_registration_options_t opts{};
-    opts.svc = &_svc;
-    opts.serviceName = PUBSUB_MESSAGE_SERIALIZATION_SERVICE_NAME;
-    opts.serviceVersion = PUBSUB_MESSAGE_SERIALIZATION_SERVICE_VERSION;
-    opts.properties = props;
-    _svcId = 
celix_bundleContext_registerServiceWithOptions(_mng->bundleContext(), &opts);
-}
-
-SubtractArgsSerializer::SubtractArgsSerializer(std::shared_ptr<celix::dm::DependencyManager>
 mng) : _mng(std::move(mng)) {
-    _svc.handle = this;
-    _svc.deserialize = [](void*, const struct iovec* input, size_t, void** 
out) -> celix_status_t {
-        rapidjson::Document d{};
-        d.Parse(static_cast<char*>(input->iov_base));
-
-        if(d.HasParseError()) {
-            return CELIX_ILLEGAL_ARGUMENT;
-        }
-
-        int id = d["id"].GetInt();
-        int a = d["a"].GetInt();
-        int b = d["b"].GetInt();
-        decltype(SubtractArgs::ret) ret = d.HasMember("ret") ? 
d["ret"].GetInt() : decltype(SubtractArgs::ret){};
-
-        *out = new SubtractArgs{id, a, b, ret};
-
-        return CELIX_SUCCESS;
-    };
-    _svc.freeDeserializedMsg = [](void*, void* msg) {
-        delete static_cast<SubtractArgs*>(msg);
-    };
-
-    _svc.serialize = [](void*, const void* input, struct iovec** output, 
size_t* outputIovLen) -> celix_status_t {
-        auto *args = static_cast<SubtractArgs const *>(input);
-
-        if (*output == nullptr) {
-            *output = static_cast<iovec *>(calloc(1, sizeof(struct iovec)));
-            if (outputIovLen){
-                *outputIovLen = 1;
-            }
-        }
-
-        rapidjson::StringBuffer sb;
-        rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
-
-        writer.StartObject();
-
-        writer.String("id");
-        writer.Int(args->id);
-
-        writer.String("a");
-        writer.Int(args->a);
-
-        writer.String("b");
-        writer.Int(args->b);
-
-        if(args->ret) {
-            writer.String("ret");
-            writer.Int(args->ret.value());
-        }
-
-        writer.EndObject();
-
-        (*output)->iov_base = strndup(sb.GetString(), sb.GetSize() + 1);
-        (*output)->iov_len = sb.GetSize() + 1;
-
-        return CELIX_SUCCESS;
-    };
-
-    _svc.freeSerializedMsg = [](void*, struct iovec* input, size_t) {
-        free(input->iov_base);
-        free(input);
-    };
-
-    celix_properties_t* props = celix_properties_create();
-    celix_properties_set(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_MSG_FQN_PROPERTY, "SubtractArgs");
-    celix_properties_set(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_MSG_VERSION_PROPERTY, "1.0.0");
-    celix_properties_setLong(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_MSG_ID_PROPERTY, 2LL);
-    celix_properties_set(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_SERIALIZATION_TYPE_PROPERTY, "json");
-
-    celix_service_registration_options_t opts{};
-    opts.svc = &_svc;
-    opts.serviceName = PUBSUB_MESSAGE_SERIALIZATION_SERVICE_NAME;
-    opts.serviceVersion = PUBSUB_MESSAGE_SERIALIZATION_SERVICE_VERSION;
-    opts.properties = props;
-    _svcId = 
celix_bundleContext_registerServiceWithOptions(_mng->bundleContext(), &opts);
-}
-
-ToStringArgsSerializer::ToStringArgsSerializer(std::shared_ptr<celix::dm::DependencyManager>
 mng) : _mng(std::move(mng)) {
-    _svc.handle = this;
-    _svc.deserialize = [](void*, const struct iovec* input, size_t, void** 
out) -> celix_status_t {
-        rapidjson::Document d{};
-        d.Parse(static_cast<char*>(input->iov_base));
-
-        if(d.HasParseError()) {
-            return CELIX_ILLEGAL_ARGUMENT;
-        }
-
-        int id = d["id"].GetInt();
-        int a = d["a"].GetInt();
-        decltype(ToStringArgs::ret) ret = d.HasMember("ret") ? 
d["ret"].GetString() : decltype(ToStringArgs::ret){};
-
-        *out = new ToStringArgs{id, a, ret};
-
-        return CELIX_SUCCESS;
-    };
-    _svc.freeDeserializedMsg = [](void*, void* msg) {
-        delete static_cast<ToStringArgs*>(msg);
-    };
-
-    _svc.serialize = [](void*, const void* input, struct iovec** output, 
size_t* outputIovLen) -> celix_status_t {
-        auto *args = static_cast<ToStringArgs const *>(input);
-
-        if (*output == nullptr) {
-            *output = static_cast<iovec *>(calloc(1, sizeof(struct iovec)));
-            if (outputIovLen){
-                *outputIovLen = 1;
-            }
-        }
-
-        rapidjson::StringBuffer sb;
-        rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
-
-        writer.StartObject();
-
-        writer.String("id");
-        writer.Int(args->id);
-
-        writer.String("a");
-        writer.Int(args->a);
-
-        if(args->ret) {
-            writer.String("ret");
-            writer.String(args->ret.value().c_str(), args->ret.value().size());
-        }
-
-        writer.EndObject();
-
-        (*output)->iov_base = strndup(sb.GetString(), sb.GetSize() + 1);
-        (*output)->iov_len = sb.GetSize() + 1;
-
-        return CELIX_SUCCESS;
-    };
-
-    _svc.freeSerializedMsg = [](void*, struct iovec* input, size_t) {
-        free(input->iov_base);
-        free(input);
-    };
-
-    celix_properties_t* props = celix_properties_create();
-    celix_properties_set(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_MSG_FQN_PROPERTY, "ToStringArgs");
-    celix_properties_set(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_MSG_VERSION_PROPERTY, "1.0.0");
-    celix_properties_setLong(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_MSG_ID_PROPERTY, 3LL);
-    celix_properties_set(props, 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_SERIALIZATION_TYPE_PROPERTY, "json");
-
-    celix_service_registration_options_t opts{};
-    opts.svc = &_svc;
-    opts.serviceName = PUBSUB_MESSAGE_SERIALIZATION_SERVICE_NAME;
-    opts.serviceVersion = PUBSUB_MESSAGE_SERIALIZATION_SERVICE_VERSION;
-    opts.properties = props;
-    _svcId = 
celix_bundleContext_registerServiceWithOptions(_mng->bundleContext(), &opts);
-}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/examples/HardcodedExampleSerializer.h 
b/bundles/cxx_remote_services/examples/HardcodedExampleSerializer.h
deleted file mode 100644
index 9a34fb6..0000000
--- a/bundles/cxx_remote_services/examples/HardcodedExampleSerializer.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <celix/dm/DependencyManager.h>
-#include <pubsub_message_serialization_service.h>
-#include <sys/uio.h>
-#include <pubsub_constants.h>
-
-#include <utility>
-
-struct AddArgs {
-    int id{};
-    int a{};
-    int b{};
-    std::optional<int> ret{};
-};
-
-struct SubtractArgs {
-    int id{};
-    int a{};
-    int b{};
-    std::optional<int> ret{};
-};
-
-struct ToStringArgs {
-    int id{};
-    int a{};
-    std::optional<std::string> ret{};
-};
-
-struct AddArgsSerializer {
-    explicit AddArgsSerializer(std::shared_ptr<celix::dm::DependencyManager> 
mng);
-
-    ~AddArgsSerializer() {
-        celix_bundleContext_unregisterService(_mng->bundleContext(), _svcId);
-    }
-
-private:
-    std::shared_ptr<celix::dm::DependencyManager> _mng{};
-    pubsub_message_serialization_service _svc{};
-    long _svcId{};
-};
-
-struct SubtractArgsSerializer {
-    explicit 
SubtractArgsSerializer(std::shared_ptr<celix::dm::DependencyManager> mng);
-
-    ~SubtractArgsSerializer() {
-        celix_bundleContext_unregisterService(_mng->bundleContext(), _svcId);
-    }
-
-private:
-    std::shared_ptr<celix::dm::DependencyManager> _mng{};
-    pubsub_message_serialization_service _svc{};
-    long _svcId{};
-};
-
-struct ToStringArgsSerializer {
-    explicit 
ToStringArgsSerializer(std::shared_ptr<celix::dm::DependencyManager> mng);
-
-    ToStringArgsSerializer(ToStringArgsSerializer const &) = delete;
-    ToStringArgsSerializer(ToStringArgsSerializer&&) = default;
-    ToStringArgsSerializer& operator=(ToStringArgsSerializer const &) = delete;
-    ToStringArgsSerializer& operator=(ToStringArgsSerializer &&) = default;
-
-    ~ToStringArgsSerializer() {
-        celix_bundleContext_unregisterService(_mng->bundleContext(), _svcId);
-    }
-
-private:
-    std::shared_ptr<celix::dm::DependencyManager> _mng{};
-    pubsub_message_serialization_service _svc{};
-    long _svcId{};
-};
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/examples/HardcodedExampleSubscriber.cc 
b/bundles/cxx_remote_services/examples/HardcodedExampleSubscriber.cc
deleted file mode 100644
index da96839..0000000
--- a/bundles/cxx_remote_services/examples/HardcodedExampleSubscriber.cc
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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 <celix_api.h>
-#include <string>
-#include <mutex>
-#include <ImportedServiceFactory.h>
-#include <pubsub/api.h>
-#include <celix/Deferred.h>
-#include <celix/PromiseFactory.h>
-#include <ConfiguredEndpoint.h>
-#include "IHardcodedService.h"
-#include "HardcodedExampleSerializer.h"
-
-#if defined(__has_include) && __has_include(<version>)
-#include <version>
-#endif
-
-#if __cpp_lib_memory_resource
-#include <memory_resource>
-#endif
-
-struct ImportedHardcodedService final : public IHardcodedService {
-    ImportedHardcodedService() = default;
-    ~ImportedHardcodedService() final = default;
-
-    ImportedHardcodedService(const ImportedHardcodedService&) = delete;
-    ImportedHardcodedService(ImportedHardcodedService&&) = delete;
-    ImportedHardcodedService& operator=(const ImportedHardcodedService&) = 
delete;
-    ImportedHardcodedService& operator=(ImportedHardcodedService&&) = delete;
-
-    celix::Promise<int> add(int a, int b) noexcept final {
-        std::cout << "[ImportedHardcodedService] add " << a << " + " << b << 
std::endl;
-        std::unique_lock l(_m);
-        AddArgs args{_idCounter++, a, b, {}};
-        _publisher->send(_publisher->handle, 1, &args, nullptr);
-
-        auto deferred = _factory.deferred<int>();
-        auto it = _intPromises.emplace(args.id, std::move(deferred));
-        return it.first->second.getPromise();
-    }
-
-    celix::Promise<int> subtract(int a, int b) noexcept final {
-        std::cout << "[ImportedHardcodedService] subtract " << a << " + " << b 
<< std::endl;
-        std::unique_lock l(_m);
-        SubtractArgs args{_idCounter++, a, b, {}};
-        _publisher->send(_publisher->handle, 2, &args, nullptr);
-
-        auto deferred = _factory.deferred<int>();
-        auto it = _intPromises.emplace(args.id, std::move(deferred));
-        return it.first->second.getPromise();
-    }
-
-    celix::Promise<std::string> toString(int a) noexcept final {
-        std::cout << "[ImportedHardcodedService] toString " << a << std::endl;
-        std::unique_lock l(_m);
-        ToStringArgs args{_idCounter++, a, {}};
-        _publisher->send(_publisher->handle, 3, &args, nullptr);
-
-        auto deferred = _factory.deferred<std::string>();
-        auto it = _stringPromises.emplace(args.id, std::move(deferred));
-        return it.first->second.getPromise();
-    }
-
-    void setPublisher(pubsub_publisher_t const * publisher) {
-        _publisher = publisher;
-    }
-
-    int receiveMessage(const char *, unsigned int msgTypeId, void *msg, const 
celix_properties_t *) {
-        std::cout << "[ImportedHardcodedService] receiveMessage" << std::endl;
-        std::unique_lock l(_m);
-        if(msgTypeId == 1) {
-            auto response = static_cast<AddArgs*>(msg);
-
-            if(!response->ret) {
-                return 0;
-            }
-
-            auto deferred = _intPromises.find(response->id);
-            if(deferred == end(_intPromises) || !response->ret) {
-                return 1;
-            }
-            deferred->second.resolve(response->ret.value());
-            _intPromises.erase(deferred);
-        } else if(msgTypeId == 2) {
-            auto response = static_cast<SubtractArgs*>(msg);
-
-            if(!response->ret) {
-                return 0;
-            }
-
-            auto deferred = _intPromises.find(response->id);
-            if(deferred == end(_intPromises) || !response->ret) {
-                return 1;
-            }
-            deferred->second.resolve(response->ret.value());
-            _intPromises.erase(deferred);
-        } else if(msgTypeId == 3) {
-            auto response = static_cast<ToStringArgs*>(msg);
-
-            if(!response->ret) {
-                return 0;
-            }
-
-            auto deferred = _stringPromises.find(response->id);
-            if(deferred == end(_stringPromises) || !response->ret) {
-                return 1;
-            }
-            deferred->second.resolve(response->ret.value());
-            _stringPromises.erase(deferred);
-        }
-
-        return 0;
-    }
-
-private:
-    std::mutex _m{};
-    pubsub_publisher_t const *_publisher{};
-#if __cpp_lib_memory_resource
-    std::pmr::unsynchronized_pool_resource _resource{};
-    std::pmr::unordered_map<int, celix::Deferred<int>> 
_intPromises{&_resource};
-    std::pmr::unordered_map<int, celix::Deferred<std::string>> 
_stringPromises{&_resource};
-#else
-    std::unordered_map<int, celix::Deferred<int>> _intPromises{};
-    std::unordered_map<int, celix::Deferred<std::string>> _stringPromises{};
-#endif
-    static std::atomic<int> _idCounter;
-    celix::PromiseFactory _factory{};
-};
-
-std::atomic<int> ImportedHardcodedService::_idCounter = 0;
-
-struct UsingHardcodedServiceService {
-
-    void setService(IHardcodedService * svc, Properties&&) {
-        _svc = svc;
-    }
-
-    void start() {
-        _t = std::thread([this]() {
-            _svc->add(14, 123).thenAccept([](int val) {
-                std::cout << "[UsingHardcodedServiceService] add(14, 123) 
returned " << val << std::endl;
-            }).timeout(std::chrono::seconds(10)).wait();
-        });
-    }
-
-    void stop() {
-        if(_t.joinable()) {
-            _t.join();
-        }
-    }
-
-private:
-    IHardcodedService *_svc{};
-    std::thread _t{};
-};
-
-class ExampleActivator {
-public:
-    explicit ExampleActivator(std::shared_ptr<celix::dm::DependencyManager> 
mng) {
-        _addArgsSerializer.emplace(mng);
-        _subtractArgsSerializer.emplace(mng);
-        _toStringSerializer.emplace(mng);
-
-        auto& factory = 
mng->createComponent(std::make_unique<celix::async_rsa::DefaultImportedServiceFactory<IHardcodedService,
 ImportedHardcodedService>>(mng))
-            .addInterface<celix::async_rsa::IImportedServiceFactory>("1.0.0", 
Properties{{celix::rsa::Endpoint::EXPORTS, "IHardcodedService"}}).build();
-        _factory = &factory;
-
-        auto &usingCmp = mng->createComponent<UsingHardcodedServiceService>()
-                .setCallbacks(nullptr, &UsingHardcodedServiceService::start, 
&UsingHardcodedServiceService::stop, nullptr);
-
-        
usingCmp.createServiceDependency<IHardcodedService>().setCallbacks([cmp = 
&usingCmp](IHardcodedService *svc, Properties&& props) {
-            cmp->getInstance().setService(svc, 
std::forward<Properties>(props));
-        })
-        .setRequired(true)
-        .build();
-
-        usingCmp.build();
-    }
-
-    ExampleActivator(const ExampleActivator &) = delete;
-    ExampleActivator &operator=(const ExampleActivator &) = delete;
-
-private:
-    std::optional<AddArgsSerializer> _addArgsSerializer{};
-    std::optional<SubtractArgsSerializer> _subtractArgsSerializer{};
-    std::optional<ToStringArgsSerializer> _toStringSerializer{};
-    
Component<celix::async_rsa::DefaultImportedServiceFactory<IHardcodedService, 
ImportedHardcodedService>> *_factory{};
-};
-
-CELIX_GEN_CXX_BUNDLE_ACTIVATOR(ExampleActivator)
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/examples/IHardcodedService.h 
b/bundles/cxx_remote_services/examples/IHardcodedService.h
deleted file mode 100644
index ba87878..0000000
--- a/bundles/cxx_remote_services/examples/IHardcodedService.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.
- */
-
-#pragma once
-
-#include <string>
-#include <celix/Promise.h>
-
-struct IHardcodedService {
-    virtual ~IHardcodedService() = default;
-
-    virtual celix::Promise<int> add(int a, int b) noexcept = 0;
-    virtual celix::Promise<int> subtract(int a, int b) noexcept = 0;
-    virtual celix::Promise<std::string> toString(int a) = 0;
-
-    static constexpr std::string_view VERSION = "1.0.0";
-    static constexpr std::string_view NAME = "IHardcodedService";
-};
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/examples/discovery/endpoint.json 
b/bundles/cxx_remote_services/examples/discovery/endpoint.json
deleted file mode 100644
index c8d65fc..0000000
--- a/bundles/cxx_remote_services/examples/discovery/endpoint.json
+++ /dev/null
@@ -1,26 +0,0 @@
-{
-  "endpoints": [
-    {
-      "endpoint.id": "id-01",
-      "service.imported": true,
-      "service.imported.configs": [
-        "pubsub"
-      ],
-      "service.exported.interfaces": "IHardcodedService",
-      "endpoint.objectClass": "TestComponentName",
-      "endpoint.scope": "default",
-      "endpoint.topic": "default"
-    },
-    {
-      "endpoint.id": "id-02",
-      "service.imported": true,
-      "service.imported.configs": [
-        "pubsub"
-      ],
-      "service.exported.interfaces": "*",
-      "endpoint.objectClass": "TestComponentName",
-      "endpoint.scope": "default",
-      "endpoint.topic": "default"
-    }
-  ]
-}
\ No newline at end of file
diff --git 
a/bundles/cxx_remote_services/examples/pubsub_properties/IHardcodedService.properties
 
b/bundles/cxx_remote_services/examples/pubsub_properties/IHardcodedService.properties
deleted file mode 100644
index 044c2e0..0000000
--- 
a/bundles/cxx_remote_services/examples/pubsub_properties/IHardcodedService.properties
+++ /dev/null
@@ -1,27 +0,0 @@
-# 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.
-tcp.static.bind.url=tcp://localhost:9500
-tcp.passive.key=tcp://localhost:9500
-
-topic.name=IHardcodedService
-topic.id=IHardcodedService
-
-#Interface info
-interface.name=IHardcodedService
-interface.version=1.0.0
-interface.messages=IHardcodedService
-
diff --git a/bundles/cxx_remote_services/integration/CMakeLists.txt 
b/bundles/cxx_remote_services/integration/CMakeLists.txt
index d12a42f..7f72d05 100644
--- a/bundles/cxx_remote_services/integration/CMakeLists.txt
+++ b/bundles/cxx_remote_services/integration/CMakeLists.txt
@@ -39,10 +39,12 @@ target_compile_options(CalculatorProvider PRIVATE 
-std=c++17) #TODO how can this
 add_celix_bundle(CalculatorConsumer
         SOURCES src/CalculatorConsumer.cc
 )
-target_link_libraries(CalculatorConsumer PRIVATE Celix::Promises)
+celix_bundle_files(CalculatorConsumer 
${CMAKE_CURRENT_SOURCE_DIR}/resources/endpoint_discovery.json DESTINATION 
"META-INF/discovery") # add configured discovery as resource in the bundle.
+target_link_libraries(CalculatorConsumer PRIVATE Celix::Promises 
Celix::shell_api Celix::RsaConfiguredDiscovery_api)
 target_include_directories(CalculatorConsumer PRIVATE include)
 target_compile_options(CalculatorConsumer PRIVATE -std=c++17) #TODO how can 
this be improved (bring back -std=c++17 on INTERFACE for promises?
 
+add_subdirectory(gtest)
 
 ################# Integration examples ##################################
 
@@ -55,7 +57,7 @@ add_celix_container(RemoteCalculatorProvider
             
#PSA_ZMQ_STATIC_BIND_URL_FOR_test_return=ipc:///tmp/pubsub-test-return
             
#PSA_ZMQ_STATIC_CONNECT_URL_FOR_test_invoke=ipc:///tmp/pubsub-test-invoke
         BUNDLES
-            Celix::shell
+            Celix::ShellCxx
             Celix::shell_tui
 
             #Needed for remote services (full pubsub stack + remote services 
stack)
@@ -79,9 +81,8 @@ add_celix_container(RemoteCalculatorConsumer
             #Configuration to let the pubsub zmq operate without dicscovery
             
#PSA_ZMQ_STATIC_BIND_URL_FOR_test_invoke=ipc:///tmp/pubsub-test-invoke
             
#PSA_ZMQ_STATIC_CONNECT_URL_FOR_test_return=ipc:///tmp/pubsub-test-return
-            
CELIX_RSA_CONFIGURED_DISCOVERY_DISCOVERY_FILES=${CMAKE_CURRENT_SOURCE_DIR}/resources/endpoint_discovery.json
         BUNDLES
-            Celix::shell
+            Celix::ShellCxx
             Celix::shell_tui
 
             #Needed for remote services (full pubsub stack + remote services 
stack)
diff --git a/bundles/cxx_remote_services/integration/gtest/CMakeLists.txt 
b/bundles/cxx_remote_services/integration/gtest/CMakeLists.txt
new file mode 100644
index 0000000..9b03a0f
--- /dev/null
+++ b/bundles/cxx_remote_services/integration/gtest/CMakeLists.txt
@@ -0,0 +1,67 @@
+# 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.
+
+add_executable(test_cxx_remote_services_integration
+    src/RemoteServicesIntegrationTestSuite.cc
+)
+target_link_libraries(test_cxx_remote_services_integration PRIVATE 
Celix::framework GTest::gtest GTest::gtest_main)
+target_compile_options(test_cxx_remote_services_integration PRIVATE -std=c++17)
+target_include_directories(test_cxx_remote_services_integration PRIVATE 
../include) #Add ICalculator
+
+add_celix_bundle_dependencies(test_cxx_remote_services_integration
+    Celix::pubsub_serializer_json
+    Celix::pubsub_topology_manager
+    Celix::pubsub_admin_zmq
+    Celix::pubsub_protocol_wire_v2
+    Celix::RsaConfiguredDiscovery
+    Celix::RemoteServiceAdmin
+    TestExportImportRemoteServiceFactory
+    CalculatorProvider
+    CalculatorConsumer
+)
+
+celix_get_bundle_file(Celix::pubsub_serializer_json PS_SER_BUNDLE_LOC)
+target_compile_definitions(test_cxx_remote_services_integration PRIVATE 
PS_SER_BUNDLE_LOC="${PS_SER_BUNDLE_LOC}")
+
+celix_get_bundle_file(Celix::pubsub_topology_manager PS_PSTM_BUNDLE_LOC)
+target_compile_definitions(test_cxx_remote_services_integration PRIVATE 
PS_PSTM_BUNDLE_LOC="${PS_PSTM_BUNDLE_LOC}")
+
+celix_get_bundle_file(Celix::pubsub_admin_zmq PS_PSA_BUNDLE_LOC)
+target_compile_definitions(test_cxx_remote_services_integration PRIVATE 
PS_PSA_BUNDLE_LOC="${PS_PSA_BUNDLE_LOC}")
+
+celix_get_bundle_file(Celix::pubsub_protocol_wire_v2 PS_WIRE_BUNDLE_LOC)
+target_compile_definitions(test_cxx_remote_services_integration PRIVATE 
PS_WIRE_BUNDLE_LOC="${PS_WIRE_BUNDLE_LOC}")
+
+celix_get_bundle_file(Celix::RsaConfiguredDiscovery RS_DISCOVERY_BUNDLE_LOC)
+target_compile_definitions(test_cxx_remote_services_integration PRIVATE 
RS_DISCOVERY_BUNDLE_LOC="${RS_DISCOVERY_BUNDLE_LOC}")
+
+celix_get_bundle_file(Celix::RemoteServiceAdmin RS_RSA_BUNDLE_LOC)
+target_compile_definitions(test_cxx_remote_services_integration PRIVATE 
RS_RSA_BUNDLE_LOC="${RS_RSA_BUNDLE_LOC}")
+
+celix_get_bundle_file(TestExportImportRemoteServiceFactory 
RS_FACTORY_BUNDLE_LOC)
+target_compile_definitions(test_cxx_remote_services_integration PRIVATE 
RS_FACTORY_BUNDLE_LOC="${RS_FACTORY_BUNDLE_LOC}")
+
+celix_get_bundle_file(CalculatorProvider RS_PROVIDER_BUNDLE_LOC)
+target_compile_definitions(test_cxx_remote_services_integration PRIVATE 
RS_PROVIDER_BUNDLE_LOC="${RS_PROVIDER_BUNDLE_LOC}")
+
+celix_get_bundle_file(CalculatorConsumer RS_CONSUMER_BUNDLE_LOC)
+target_compile_definitions(test_cxx_remote_services_integration PRIVATE 
RS_CONSUMER_BUNDLE_LOC="${RS_CONSUMER_BUNDLE_LOC}")
+
+
+
+add_test(NAME test_cxx_remote_services_integration COMMAND 
test_cxx_remote_services_integration)
+setup_target_for_coverage(test_cxx_remote_services_integration SCAN_DIR ../..)
\ No newline at end of file
diff --git 
a/bundles/cxx_remote_services/integration/gtest/src/RemoteServicesIntegrationTestSuite.cc
 
b/bundles/cxx_remote_services/integration/gtest/src/RemoteServicesIntegrationTestSuite.cc
new file mode 100644
index 0000000..9e460ba
--- /dev/null
+++ 
b/bundles/cxx_remote_services/integration/gtest/src/RemoteServicesIntegrationTestSuite.cc
@@ -0,0 +1,78 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include "celix/FrameworkFactory.h"
+
+class RemoteServicesIntegrationTestSuite : public ::testing::Test {
+public:
+    RemoteServicesIntegrationTestSuite() {
+        celix::Properties clientConfig{
+                {"CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "trace"},
+                {celix::FRAMEWORK_CACHE_DIR, ".clientCache"}
+        };
+        clientFw = celix::createFramework(clientConfig);
+        clientCtx = clientFw->getFrameworkBundleContext();
+
+        celix::Properties serverConfig{
+                {"CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "trace"},
+                {celix::FRAMEWORK_CACHE_DIR, ".serverCache"}
+        };
+        serverFw = celix::createFramework(serverConfig);
+        serverCtx = serverFw->getFrameworkBundleContext();
+    }
+
+    void installSharedBundles(std::shared_ptr<celix::BundleContext>& ctx) {
+        auto sharedBundles = {
+                PS_SER_BUNDLE_LOC,
+                PS_PSTM_BUNDLE_LOC,
+                PS_PSA_BUNDLE_LOC,
+                PS_WIRE_BUNDLE_LOC,
+                RS_DISCOVERY_BUNDLE_LOC,
+                RS_RSA_BUNDLE_LOC,
+                RS_FACTORY_BUNDLE_LOC };
+        for (const auto& bndLoc : sharedBundles) {
+            auto bndId = ctx->installBundle(bndLoc);
+            EXPECT_GE(bndId, 0);
+        }
+    }
+
+    void installProviderBundles() {
+        installSharedBundles(serverCtx);
+        auto bndId = serverCtx->installBundle(RS_PROVIDER_BUNDLE_LOC);
+        EXPECT_GE(bndId, 0);
+    }
+
+    void installConsumerBundles() {
+        installSharedBundles(clientCtx);
+        auto bndId = clientCtx->installBundle(RS_CONSUMER_BUNDLE_LOC);
+        EXPECT_GE(bndId, 0);
+    }
+
+    std::shared_ptr<celix::Framework> clientFw{};
+    std::shared_ptr<celix::BundleContext> clientCtx{};
+    std::shared_ptr<celix::Framework> serverFw{};
+    std::shared_ptr<celix::BundleContext> serverCtx{};
+};
+
+TEST_F(RemoteServicesIntegrationTestSuite, StartStopFrameworks) {
+    installConsumerBundles();
+    installProviderBundles();
+}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/integration/src/CalculatorConsumer.cc 
b/bundles/cxx_remote_services/integration/src/CalculatorConsumer.cc
index de4caae..7ef3330 100644
--- a/bundles/cxx_remote_services/integration/src/CalculatorConsumer.cc
+++ b/bundles/cxx_remote_services/integration/src/CalculatorConsumer.cc
@@ -19,45 +19,36 @@
 
 #include <memory>
 
+#include "celix/IShellCommand.h"
 #include "celix/BundleActivator.h"
 #include "celix/PromiseFactory.h"
+#include "celix/rsa/IConfiguredDiscoveryManager.h"
 #include "ICalculator.h"
 
-class CalculatorConsumer final {
+class CalculatorConsumer final : public celix::IShellCommand {
 public:
-    void start() {
-        std::cout << "starting calc thread" << std::endl;
-        active = true;
-        calcThread = std::thread{[this]() {
-            double secondArg = 1;
-            while(active) {
-                std::cout << "Calling calc" << std::endl;
-                calculator->add(42, secondArg++)
-                    .onSuccess([](double val) {
-                        std::cout << "calc result is " << val << std::endl;
-                    })
-                    .onFailure([](const auto& exp) {
-                        std::cerr << "error calling calc: " << exp.what() << 
std::endl;
-                    });
-                std::this_thread::sleep_for(std::chrono::seconds{5});
-            }
-        }};
-    }
-
-    void stop() {
-        active = false;
-        if (calcThread.joinable()) {
-            calcThread.join();
-        }
-    }
+    ~CalculatorConsumer() override = default;
 
     void setCalculator(const std::shared_ptr<ICalculator>& cal) {
         calculator = cal;
     }
+
+    void executeCommand(const std::string &/*commandLine*/, const 
std::vector<std::string> &/*commandArgs*/, FILE *outStream,
+                        FILE *errorStream) override {
+        thread_local double secondArg = 1;
+        fprintf(outStream, "Calling calc\n");
+        calculator->add(42, secondArg++)
+                .onSuccess([outStream](double val) {
+                    fprintf(outStream, "calc result is %f\n", val);
+                })
+                .onFailure([errorStream](const auto& exp) {
+                    fprintf(errorStream, "error calling calc: %s", exp.what());
+                })
+                .wait(); //note waiting on promise to ensure outStream and 
errorStream are still valid.
+    }
+
 private:
-    std::atomic<bool> active{false};
     std::shared_ptr<ICalculator> calculator{};
-    std::thread calcThread{};
 };
 
 class CalculatorProviderActivator {
@@ -67,8 +58,17 @@ public:
         cmp.createServiceDependency<ICalculator>()
                 .setRequired(true)
                 .setCallbacks(&CalculatorConsumer::setCalculator);
-        cmp.setCallbacks(nullptr, &CalculatorConsumer::start, 
&CalculatorConsumer::stop, nullptr);
+        cmp.createProvidedService<celix::IShellCommand>()
+                .addProperty(celix::IShellCommand::COMMAND_NAME, "calc");
         cmp.build();
+
+        //bootstrap own configured import discovery to the configured 
discovery manager
+        auto path = 
ctx->getBundle().getEntry("META-INF/discovery/endpoint_discovery.json");
+        ctx->useService<celix::rsa::IConfiguredDiscoveryManager>()
+                .addUseCallback([&path](auto& disc) {
+                    disc.addConfiguredDiscoveryFile(path);
+                })
+                .build();
     }
 };
 
diff --git a/bundles/logging/log_helper/include/celix/LogHelper.h 
b/bundles/logging/log_helper/include/celix/LogHelper.h
index f4fd4b3..3f447f2 100644
--- a/bundles/logging/log_helper/include/celix/LogHelper.h
+++ b/bundles/logging/log_helper/include/celix/LogHelper.h
@@ -19,7 +19,9 @@
 
 #pragma once
 
+#include <memory>
 #include "celix_log_helper.h"
+#include "celix/BundleContext.h"
 
 namespace celix {
 
diff --git a/cmake/cmake_celix/Generic.cmake b/cmake/cmake_celix/Generic.cmake
index a0e00be..ae82881 100644
--- a/cmake/cmake_celix/Generic.cmake
+++ b/cmake/cmake_celix/Generic.cmake
@@ -18,3 +18,28 @@
 function(install_celix_targets)
     install_celix_bundle_targets(${ARGN})
 endfunction ()
+
+#[[
+Add bundles as dependencies to a cmake target, so that the bundle zip files 
are created before the cmake target is
+ created.
+
+add_celix_bundle_dependencies(<cmake_target>
+    bundles...
+)
+]]
+function(add_celix_bundle_dependencies)
+    list(GET ARGN 0 TARGET)
+    list(REMOVE_AT ARGN 0)
+    message("TEST")
+    foreach(BUNDLE_TARGET IN LISTS ARGN)
+        if (TARGET ${BUNDLE_TARGET})
+            get_target_property(IMPORT ${BUNDLE_TARGET} BUNDLE_IMPORTED)
+            get_target_property(CREATE_BUNDLE_TARGET ${BUNDLE_TARGET} 
BUNDLE_CREATE_BUNDLE_TARGET)
+            if (IMPORT)
+                #NOP, an imported bundle target -> handle target without 
DEPENDS
+            else ()
+                add_dependencies(${TARGET} ${CREATE_BUNDLE_TARGET})
+            endif ()
+        endif()
+    endforeach()
+endfunction()
\ No newline at end of file
diff --git a/libs/framework/include/celix/Bundle.h 
b/libs/framework/include/celix/Bundle.h
index a1e97b8..a098b3c 100644
--- a/libs/framework/include/celix/Bundle.h
+++ b/libs/framework/include/celix/Bundle.h
@@ -50,9 +50,10 @@ namespace celix {
          */
         std::string getEntry(const std::string& path) const {
             std::string result{};
-            const char* entry = celix_bundle_getEntry(cBnd.get(), 
path.c_str());
+            char* entry = celix_bundle_getEntry(cBnd.get(), path.c_str());
             if (entry != nullptr) {
                 result = std::string{entry};
+                free(entry);
             }
             return result;
         }
diff --git a/libs/framework/include/celix/Constants.h 
b/libs/framework/include/celix/Constants.h
index 7c44233..084602d 100644
--- a/libs/framework/include/celix/Constants.h
+++ b/libs/framework/include/celix/Constants.h
@@ -174,4 +174,12 @@ namespace celix {
      *
      */
     constexpr const char * const LOAD_BUNDLES_WITH_NODELETE = 
CELIX_LOAD_BUNDLES_WITH_NODELETE;
+
+    /**
+     * @brief Celix framework environment property (named 
"org.osgi.framework.storage") specifying the cache
+     * directory used for the bundle caches.
+     *
+     * If not specified ".cache" is used.
+     */
+    constexpr const char * const FRAMEWORK_CACHE_DIR = 
OSGI_FRAMEWORK_FRAMEWORK_STORAGE;
 }
\ No newline at end of file

Reply via email to