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

commit 883baadcc6492e6f3d76e46904be1a8351def356
Author: Pepijn Noltes <[email protected]>
AuthorDate: Thu Apr 15 19:31:05 2021 +0200

    Refactors C++ remote service admin to use IExport(Import)ServiceFactory SPI.
---
 bundles/async_remote_services/CMakeLists.txt       |  12 +-
 bundles/async_remote_services/admin/CMakeLists.txt |  32 ++-
 .../{ => admin/gtest}/CMakeLists.txt               |  22 +-
 .../admin/gtest/src/RemoteServiceAdminTestSuite.cc | 279 +++++++++++++++++++++
 .../async_remote_services/admin/include/admin.h    |  61 ++---
 bundles/async_remote_services/admin/src/admin.cc   | 166 ++++++------
 .../async_remote_services/common/CMakeLists.txt    |   1 +
 .../common/include/ImportedServiceFactory.h        |   1 -
 .../async_remote_services/examples/CMakeLists.txt  |   8 +-
 .../async_remote_services/rsa_spi/CMakeLists.txt   |   1 -
 .../rsa_spi/include/celix/rsa/Constants.h          |  10 +-
 .../rsa_spi/include/celix/rsa/Endpoint.h           |  12 +-
 .../include/celix/rsa/IExportServiceFactory.h      |  22 +-
 .../include/celix/rsa/IImportServiceFactory.h      |  22 +-
 libs/framework/include/celix/ServiceRegistration.h |   8 +-
 .../include/celix/dm/DependencyManager_Impl.h      |   2 +-
 16 files changed, 453 insertions(+), 206 deletions(-)

diff --git a/bundles/async_remote_services/CMakeLists.txt 
b/bundles/async_remote_services/CMakeLists.txt
index c71b538..2257092 100644
--- a/bundles/async_remote_services/CMakeLists.txt
+++ b/bundles/async_remote_services/CMakeLists.txt
@@ -15,12 +15,12 @@
 # specific language governing permissions and limitations
 # under the License.
 
-celix_subproject(ASYNC_REMOTE_SERVICE_ADMIN "Option to enable building the 
C++17 async Remote Service Admin Service bundles" OFF)
-if (ASYNC_REMOTE_SERVICE_ADMIN)
-    add_subdirectory(common)
+celix_subproject(REMOTE_SERVICE_ADMIN "Option to enable building the C++17 
Remote Service Admin Service bundles" OFF)
+if (REMOTE_SERVICE_ADMIN)
+    #add_subdirectory(common)
     add_subdirectory(rsa_spi)
     add_subdirectory(admin)
-    add_subdirectory(topology_manager)
-    add_subdirectory(discovery_configured)
-    add_subdirectory(examples)
+    #add_subdirectory(topology_manager)
+    #add_subdirectory(discovery_configured)
+    #add_subdirectory(examples)
 endif()
\ No newline at end of file
diff --git a/bundles/async_remote_services/admin/CMakeLists.txt 
b/bundles/async_remote_services/admin/CMakeLists.txt
index b74c41e..4eee9c1 100644
--- a/bundles/async_remote_services/admin/CMakeLists.txt
+++ b/bundles/async_remote_services/admin/CMakeLists.txt
@@ -15,29 +15,27 @@
 # specific language governing permissions and limitations
 # under the License.
 
-add_celix_bundle(async_rsa
+add_celix_bundle(RemoteServiceAdmin
         VERSION 0.9.0
-        SYMBOLIC_NAME "apache_celix_async_remote_service_admin"
-        NAME "Apache Celix Async Remote Service Admin"
-        GROUP "Celix/AsyncRSA"
+        SYMBOLIC_NAME "celix::RemoteServiceAdmin"
+        NAME "Apache Celix Remote Service Admin"
+        GROUP "Celix/RSA"
+        FILENAME "Celix_RemoteServiceAdmin"
         SOURCES
-        src/admin.cc
-        )
-target_include_directories(async_rsa PRIVATE include)
-target_link_libraries(async_rsa PRIVATE
-        Celix::async_rsa_common
-        Celix::pubsub_api
-        Celix::pubsub_spi
+            src/admin.cc
+)
+target_include_directories(RemoteServiceAdmin PRIVATE include)
+target_link_libraries(RemoteServiceAdmin PRIVATE
         Celix::rsa_spi
         Celix::framework
         Celix::log_helper
-        )
+)
 
-#if (ENABLE_TESTING)
-#    add_subdirectory(gtest)
-#endif()
+if (ENABLE_TESTING)
+    add_subdirectory(gtest)
+endif()
 
 
-install_celix_bundle(async_rsa EXPORT celix COMPONENT async_rsa)
+install_celix_bundle(RemoteServiceAdmin EXPORT celix COMPONENT rsa)
 #Setup target aliases to match external usage
-add_library(Celix::async_rsa ALIAS async_rsa)
\ No newline at end of file
+add_library(Celix::RemoteServiceAdmin ALIAS RemoteServiceAdmin)
\ No newline at end of file
diff --git a/bundles/async_remote_services/CMakeLists.txt 
b/bundles/async_remote_services/admin/gtest/CMakeLists.txt
similarity index 54%
copy from bundles/async_remote_services/CMakeLists.txt
copy to bundles/async_remote_services/admin/gtest/CMakeLists.txt
index c71b538..42e2ce8 100644
--- a/bundles/async_remote_services/CMakeLists.txt
+++ b/bundles/async_remote_services/admin/gtest/CMakeLists.txt
@@ -15,12 +15,16 @@
 # specific language governing permissions and limitations
 # under the License.
 
-celix_subproject(ASYNC_REMOTE_SERVICE_ADMIN "Option to enable building the 
C++17 async Remote Service Admin Service bundles" OFF)
-if (ASYNC_REMOTE_SERVICE_ADMIN)
-    add_subdirectory(common)
-    add_subdirectory(rsa_spi)
-    add_subdirectory(admin)
-    add_subdirectory(topology_manager)
-    add_subdirectory(discovery_configured)
-    add_subdirectory(examples)
-endif()
\ No newline at end of file
+add_executable(test_cxx_remote_service_admin
+    src/RemoteServiceAdminTestSuite.cc
+)
+
+target_link_libraries(test_cxx_remote_service_admin PRIVATE Celix::framework 
GTest::gtest GTest::gtest_main Celix::rsa_spi)
+add_dependencies(test_cxx_remote_service_admin RemoteServiceAdmin_bundle)
+
+celix_get_bundle_file(RemoteServiceAdmin REMOTE_SERVICE_ADMIN_BUNDLE_LOCATION)
+target_compile_definitions(test_cxx_remote_service_admin PRIVATE 
REMOTE_SERVICE_ADMIN_BUNDLE_LOCATION="${REMOTE_SERVICE_ADMIN_BUNDLE_LOCATION}")
+
+
+add_test(NAME test_cxx_remote_service_admin COMMAND 
test_cxx_remote_service_admin)
+setup_target_for_coverage(test_cxx_remote_service_admin SCAN_DIR ..)
\ No newline at end of file
diff --git 
a/bundles/async_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc 
b/bundles/async_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
new file mode 100644
index 0000000..20ff87e
--- /dev/null
+++ 
b/bundles/async_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
@@ -0,0 +1,279 @@
+/*
+ * 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"
+#include "celix/rsa/IExportServiceFactory.h"
+#include "celix/rsa/IExportedService.h"
+#include "celix/rsa/IImportServiceFactory.h"
+#include "celix/rsa/Constants.h"
+
+class RemoteServiceAdminTestSuite : public ::testing::Test {
+public:
+    RemoteServiceAdminTestSuite() {
+        fw = celix::createFramework();
+        ctx = fw->getFrameworkBundleContext();
+    }
+
+    std::shared_ptr<celix::Framework> fw{};
+    std::shared_ptr<celix::BundleContext> ctx{};
+};
+
+TEST_F(RemoteServiceAdminTestSuite, startStopStartStopBundle) {
+    auto bndId = ctx->installBundle(REMOTE_SERVICE_ADMIN_BUNDLE_LOCATION);
+    EXPECT_GE(bndId, 0);
+    ctx->stopBundle(bndId);
+    ctx->startBundle(bndId);
+}
+
+
+/**
+ * The StubExported* classes mimic the expected behaviour of export service 
factories so that this can be used to test
+ * the RemoteServiceAdmin.
+ */
+
+class StubExportedService : public celix::rsa::IExportedService {
+public:
+    ~StubExportedService() noexcept override = default;
+    std::shared_ptr<celix::rsa::Endpoint> getEndpoint() override {
+        return endpoint;
+    }
+private:
+    std::shared_ptr<celix::rsa::Endpoint> endpoint = 
std::make_shared<celix::rsa::Endpoint>(celix::Properties{}); //can be empty for 
stub
+};
+
+class StubExportedServiceGuard {
+public:
+    explicit 
StubExportedServiceGuard(std::shared_ptr<celix::ServiceRegistration> _reg) : 
reg{std::move(_reg)} {}
+
+    void close() {
+        reg->unregister();
+    }
+private:
+    const std::shared_ptr<celix::ServiceRegistration> reg;
+};
+
+class StubExportServiceRegistration : public 
celix::rsa::IExportServiceRegistration {
+public:
+    explicit 
StubExportServiceRegistration(std::weak_ptr<StubExportedServiceGuard> _guard) : 
guard{std::move(_guard)} {}
+    ~StubExportServiceRegistration() noexcept override {
+        auto g = guard.lock();
+        if (g) {
+            g->close();
+        }
+    }
+
+private:
+    const std::weak_ptr<StubExportedServiceGuard> guard;
+};
+
+class StubExportServiceFactory : public celix::rsa::IExportServiceFactory {
+public:
+    explicit StubExportServiceFactory(std::shared_ptr<celix::BundleContext> 
_ctx) : ctx{std::move(_ctx)} {}
+
+    std::unique_ptr<celix::rsa::IExportServiceRegistration> 
exportService(const celix::Properties& /*serviceProperties*/) override {
+        auto svcReg= 
ctx->registerService<celix::rsa::IExportedService>(std::make_shared<StubExportedService>()).build();
+        auto guard = 
std::make_shared<StubExportedServiceGuard>(std::move(svcReg));
+
+        std::lock_guard<std::mutex> lock{mutex};
+        guards.emplace_back(guard);
+        return std::make_unique<StubExportServiceRegistration>(guard);
+    }
+
+private:
+    const std::shared_ptr<celix::BundleContext> ctx;
+    std::mutex mutex{};
+    std::vector<std::shared_ptr<StubExportedServiceGuard>> guards{};
+};
+
+class IDummyService {
+public:
+    virtual ~IDummyService() noexcept = default;
+};
+
+class DummyServiceImpl : public IDummyService {
+public:
+    ~DummyServiceImpl() noexcept override = default;
+};
+
+TEST_F(RemoteServiceAdminTestSuite, exportService) {
+    auto bndId = ctx->installBundle(REMOTE_SERVICE_ADMIN_BUNDLE_LOCATION);
+    EXPECT_GE(bndId, 0);
+
+    /**
+     * When I add a export service factory and register a service with 
exported interfaces the
+     * RemoteServiceAdmin will create a ExportedService with using the service 
factory
+     */
+     auto count = ctx->useService<celix::rsa::IExportedService>()
+             .build();
+     EXPECT_EQ(0, count);
+
+     auto reg1 = 
ctx->registerService<celix::rsa::IExportServiceFactory>(std::make_shared<StubExportServiceFactory>(ctx))
+             
.addProperty(celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME, 
celix::typeName<IDummyService>())
+             .build();
+
+    count = ctx->useService<celix::rsa::IExportedService>()
+            .build();
+    EXPECT_EQ(0, count);
+
+     auto reg2 = 
ctx->registerService<IDummyService>(std::make_shared<DummyServiceImpl>())
+             .addProperty(celix::rsa::REMOTE_SERVICE_EXPORTED_PROPERTY_NAME, 
true)
+             .build();
+
+    //rsa called export service factory which created a 
IExportServiceRegistration, which register the marker interface 
IExportedService indicating an exported service
+    count = ctx->useService<celix::rsa::IExportedService>()
+            .build();
+    EXPECT_EQ(1, count);
+
+
+    reg1->unregister();
+
+    //removed factory -> removed exported interface
+    count = ctx->useService<celix::rsa::IExportedService>()
+            .build();
+    EXPECT_EQ(0, count);
+}
+
+TEST_F(RemoteServiceAdminTestSuite, exportServiceDifferentOrder) {
+    auto bndId = ctx->installBundle(REMOTE_SERVICE_ADMIN_BUNDLE_LOCATION);
+    EXPECT_GE(bndId, 0);
+
+    /**
+     * When I add a export service factory and register a service with 
exported interfaces the
+     * RemoteServiceAdmin will create a ExportedService with using the service 
factory
+     */
+    auto count = ctx->useService<celix::rsa::IExportedService>()
+            .build();
+    EXPECT_EQ(0, count);
+
+    auto reg1 = 
ctx->registerService<IDummyService>(std::make_shared<DummyServiceImpl>())
+            .addProperty(celix::rsa::REMOTE_SERVICE_EXPORTED_PROPERTY_NAME, 
true)
+            .build();
+
+    count = ctx->useService<celix::rsa::IExportedService>()
+            .build();
+    EXPECT_EQ(0, count);
+
+    auto reg2 = 
ctx->registerService<celix::rsa::IExportServiceFactory>(std::make_shared<StubExportServiceFactory>(ctx))
+            
.addProperty(celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME, 
celix::typeName<IDummyService>())
+            .build();
+
+    //rsa called export service factory which created a 
IExportServiceRegistration, which register the marker interface 
IExportedService indicating an exported service
+    count = ctx->useService<celix::rsa::IExportedService>()
+            .build();
+    EXPECT_EQ(1, count);
+}
+
+
+
+
+/**
+ * The StubImported* classes mimic the expected behaviour of import service 
factories so that this can be used to test
+ * the RemoteServiceAdmin.
+ */
+
+class StubImportedServiceGuard {
+public:
+    explicit 
StubImportedServiceGuard(std::shared_ptr<celix::ServiceRegistration> _reg) : 
reg{std::move(_reg)} {}
+
+    void close() {
+        reg->unregister();
+    }
+private:
+    const std::shared_ptr<celix::ServiceRegistration> reg;
+};
+
+class StubImportServiceRegistration : public 
celix::rsa::IImportServiceRegistration {
+public:
+    explicit 
StubImportServiceRegistration(std::weak_ptr<StubImportedServiceGuard> _guard) : 
guard{std::move(_guard)} {}
+    ~StubImportServiceRegistration() noexcept override {
+        auto g = guard.lock();
+        if (g) {
+            g->close();
+        }
+    }
+
+private:
+    const std::weak_ptr<StubImportedServiceGuard> guard;
+};
+
+class StubImportServiceFactory : public celix::rsa::IImportServiceFactory {
+public:
+    explicit StubImportServiceFactory(std::shared_ptr<celix::BundleContext> 
_ctx) : ctx{std::move(_ctx)} {}
+
+    virtual std::unique_ptr<celix::rsa::IImportServiceRegistration> 
importService(const celix::rsa::Endpoint& endpoint) {
+           if (endpoint.getExportedInterfaces() == 
celix::typeName<IDummyService>()) {
+               auto reg = 
ctx->registerService<IDummyService>(std::make_shared<DummyServiceImpl>())
+                       
.addProperty(celix::rsa::REMOTE_SERVICE_IMPORTED_PROPERTY_NAME, true)
+                       .build();
+               std::lock_guard<std::mutex> lock{mutex};
+               auto guard = 
std::make_shared<StubImportedServiceGuard>(std::move(reg));
+               guards.emplace_back(guard);
+               return std::make_unique<StubImportServiceRegistration>(guard);
+           } else {
+               return {};
+           }
+    }
+
+private:
+    const std::shared_ptr<celix::BundleContext> ctx;
+    std::mutex mutex{};
+    std::vector<std::shared_ptr<StubImportedServiceGuard>> guards{};
+};
+
+TEST_F(RemoteServiceAdminTestSuite, importService) {
+    auto bndId = ctx->installBundle(REMOTE_SERVICE_ADMIN_BUNDLE_LOCATION);
+    EXPECT_GE(bndId, 0);
+
+    /**
+     * When I add a import service factory and register a Endpoint/
+     * RemoteServiceAdmin will create a imported service (proxy for remote 
service described by the endpoint).
+     */
+    auto count = ctx->useService<IDummyService>()
+            .build();
+    EXPECT_EQ(0, count);
+
+    auto reg1 = 
ctx->registerService<celix::rsa::IImportServiceFactory>(std::make_shared<StubImportServiceFactory>(ctx))
+            
.addProperty(celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME, 
celix::typeName<IDummyService>())
+            .build();
+
+    count = ctx->useService<IDummyService>()
+            .build();
+    EXPECT_EQ(0, count);
+
+    auto endpoint = std::make_shared<celix::rsa::Endpoint>(celix::Properties{
+        {celix::rsa::Endpoint::IDENTIFIER, "endpoint-id-1"},
+        {celix::rsa::Endpoint::EXPORTS, celix::typeName<IDummyService>()}});
+    auto reg2 = ctx->registerService<celix::rsa::Endpoint>(std::move(endpoint))
+            .build();
+
+    //rsa called import service factory which created a IImportService, which 
register a IDummtService
+    count = ctx->useService<IDummyService>()
+            .build();
+    EXPECT_EQ(1, count);
+
+
+    reg1->unregister();
+
+    //removed factory -> removed imported interface
+    count = ctx->useService<IDummyService>()
+            .build();
+    EXPECT_EQ(0, count);
+}
\ No newline at end of file
diff --git a/bundles/async_remote_services/admin/include/admin.h 
b/bundles/async_remote_services/admin/include/admin.h
index cf5a58a..80be3ad 100644
--- a/bundles/async_remote_services/admin/include/admin.h
+++ b/bundles/async_remote_services/admin/include/admin.h
@@ -19,11 +19,7 @@
 
 #include "celix/rsa/Endpoint.h"
 #include <celix_api.h>
-#include <ImportedServiceFactory.h>
-#include <ExportedServiceFactory.h>
 #include <mutex>
-#include <pubsub/api.h>
-#include <pubsub_message_serialization_service.h>
 #include "celix_log_service.h"
 
 #if defined(__has_include) && __has_include(<version>)
@@ -32,45 +28,26 @@
 
 #if __cpp_lib_memory_resource
 #include <memory_resource>
+#include <celix/rsa/IImportServiceFactory.h>
+#include <celix/rsa/IExportServiceFactory.h>
+
 #endif
 
 namespace celix::async_rsa {
-    class AsyncAdmin;
-
-    struct subscriber_handle {
-        subscriber_handle(long _svcId, AsyncAdmin *_admin, std::string_view 
_interface) : svcId(_svcId), admin(_admin), interface(_interface) {}
-        subscriber_handle(subscriber_handle const&) = default;
-        subscriber_handle(subscriber_handle&&) = default;
-        subscriber_handle& operator=(subscriber_handle const&) = default;
-        subscriber_handle& operator=(subscriber_handle&&) = default;
-        ~subscriber_handle() = default;
-
-        long svcId;
-        AsyncAdmin *admin;
-        std::string interface;
-    };
 
     class AsyncAdmin {
     public:
-        explicit AsyncAdmin(std::shared_ptr<celix::BundleContext> ctx) 
noexcept;
-        ~AsyncAdmin() noexcept = default;
-
-        AsyncAdmin(AsyncAdmin const &) = delete;
-        AsyncAdmin(AsyncAdmin&&) = delete;
-        AsyncAdmin& operator=(AsyncAdmin const &) = delete;
-        AsyncAdmin& operator=(AsyncAdmin&&) = delete;
-
         // Imported endpoint add/remove functions
         void addEndpoint(const std::shared_ptr<celix::rsa::Endpoint>& 
endpoint);
         void removeEndpoint(const std::shared_ptr<celix::rsa::Endpoint>& 
endpoint);
 
-        // Imported endpoint add/remove functions
-        void addImportedServiceFactory(const 
std::shared_ptr<celix::async_rsa::IImportedServiceFactory>& factory, const 
std::shared_ptr<const celix::Properties>& properties);
-        void removeImportedServiceFactory(const 
std::shared_ptr<celix::async_rsa::IImportedServiceFactory>& factory, const 
std::shared_ptr<const celix::Properties>& properties);
+        // import service factory. used to create new imported services
+        void addImportedServiceFactory(const 
std::shared_ptr<celix::rsa::IImportServiceFactory>& factory, const 
std::shared_ptr<const celix::Properties>& properties);
+        void removeImportedServiceFactory(const 
std::shared_ptr<celix::rsa::IImportServiceFactory>& factory, const 
std::shared_ptr<const celix::Properties>& properties);
 
-        // Exported endpoint add/remove functions
-        void addExportedServiceFactory(const 
std::shared_ptr<celix::async_rsa::IExportedServiceFactory>& factory, const 
std::shared_ptr<const celix::Properties>& properties);
-        void removeExportedServiceFactory(const 
std::shared_ptr<celix::async_rsa::IExportedServiceFactory>& factory, const 
std::shared_ptr<const celix::Properties>& properties);
+        // export service factory. used to create new exported services
+        void addExportedServiceFactory(const 
std::shared_ptr<celix::rsa::IExportServiceFactory>& factory, const 
std::shared_ptr<const celix::Properties>& properties);
+        void removeExportedServiceFactory(const 
std::shared_ptr<celix::rsa::IExportServiceFactory>& factory, const 
std::shared_ptr<const celix::Properties>& properties);
 
         // Add/remove services, used to track all services registered with 
celix and check if remote = true.
         void addService(const std::shared_ptr<void>& svc, const 
std::shared_ptr<const celix::Properties>& properties);
@@ -82,23 +59,23 @@ namespace celix::async_rsa {
         void createExportServices();
         void createImportServices();
 
-        std::shared_ptr<celix::BundleContext> _ctx;
         std::shared_ptr<celix_log_service> _logService{};
         std::mutex _m{}; // protects below
 
 #if __cpp_lib_memory_resource
         std::pmr::unsynchronized_pool_resource _memResource{};
-        std::pmr::unordered_map<std::string, 
std::shared_ptr<celix::async_rsa::IExportedServiceFactory>> 
_exportedServiceFactories{&_memResource};
-        std::pmr::unordered_map<std::string, 
std::shared_ptr<celix::async_rsa::IImportedServiceFactory>> 
_importedServiceFactories{&_memResource};
-        std::pmr::unordered_map<std::string, std::string> 
_importedServiceInstances{&_memResource}; //key = endpoint id, value = cmp uuid.
-        std::pmr::unordered_map<long, std::string> 
_exportedServiceInstances{&_memResource}; //key = service id, value = cmp uuid.
+
+        std::pmr::unordered_map<std::string, 
std::shared_ptr<celix::rsa::IExportServiceFactory>> 
_exportServiceFactories{&_memResource}; //key = service name
+        std::pmr::unordered_map<std::string, 
std::shared_ptr<celix::rsa::IImportServiceFactory>> 
_importServiceFactories{&_memResource}; //key = service name
+        std::pmr::unordered_map<std::string, 
std::unique_ptr<celix::rsa::IImportServiceRegistration>> 
_importedServices{&_memResource}; //key = endpoint id
+        std::pmr::unordered_map<long, 
std::unique_ptr<celix::rsa::IExportServiceRegistration>> 
_exportedServices{&_memResource}; //key = service id
 #else
-        std::unordered_map<std::string, 
std::shared_ptr<celix::async_rsa::IExportedServiceFactory>> 
_exportedServiceFactories{};
-        std::unordered_map<std::string, 
std::shared_ptr<celix::async_rsa::IImportedServiceFactory>> 
_importedServiceFactories{};
-        std::unordered_map<std::string, std::string> 
_importedServiceInstances{};
-        std::unordered_map<long, std::string> _exportedServiceInstances{};
+        std::unordered_map<std::string, 
std::shared_ptr<celix::rsa::IExportServiceFactory>> _exportServiceFactories{}; 
//key = service name
+        std::unordered_map<std::string, 
std::shared_ptr<celix::rsa::IImportServiceFactory>> _importServiceFactories{}; 
//key = service name
+        std::unordered_map<std::string, 
std::unique_ptr<celix::rsa::IImportServiceRegistration>> _importedServices{}; 
//key = endpoint id
+        std::unordered_map<long, 
std::unique_ptr<celix::rsa::IExportServiceRegistration>> _exportedServices{}; 
//key = service id
 #endif
         std::vector<std::shared_ptr<celix::rsa::Endpoint>> 
_toBeImportedServices{};
-        std::vector<std::pair<std::shared_ptr<void>, std::shared_ptr<const 
celix::Properties>>> _toBeExportedServices{};
+        std::vector<std::shared_ptr<const celix::Properties>> 
_toBeExportedServices{};
     };
 }
\ No newline at end of file
diff --git a/bundles/async_remote_services/admin/src/admin.cc 
b/bundles/async_remote_services/admin/src/admin.cc
index c776599..3b92867 100644
--- a/bundles/async_remote_services/admin/src/admin.cc
+++ b/bundles/async_remote_services/admin/src/admin.cc
@@ -18,9 +18,6 @@
  */
 
 #include <admin.h>
-#include <celix_api.h>
-#include <pubsub_message_serialization_service.h>
-#include <ConfiguredEndpoint.h>
 #include "celix/rsa/Constants.h"
 
 #define L_DEBUG(...) \
@@ -40,10 +37,6 @@
         _logService->error(_logService->handle, __VA_ARGS__);           \
     }
 
-celix::async_rsa::AsyncAdmin::AsyncAdmin(std::shared_ptr<celix::BundleContext> 
ctx) noexcept : _ctx{std::move(ctx)} {
-
-}
-
 void celix::async_rsa::AsyncAdmin::addEndpoint(const 
std::shared_ptr<celix::rsa::Endpoint>& endpoint) {
     assert(endpoint);
 
@@ -73,87 +66,89 @@ void celix::async_rsa::AsyncAdmin::removeEndpoint(const 
std::shared_ptr<celix::r
         return;
     }
 
-    std::lock_guard l(_m);
-
-    _toBeImportedServices.erase(std::remove_if(_toBeImportedServices.begin(), 
_toBeImportedServices.end(), [&id](auto const &endpoint){
-        return id == endpoint->getEndpointId();
-    }), _toBeImportedServices.end());
+    std::shared_ptr<celix::rsa::IImportServiceRegistration> tmpStore{}; //to 
ensure destruction outside of lock
+    {
+        std::lock_guard l(_m);
 
+        
_toBeImportedServices.erase(std::remove_if(_toBeImportedServices.begin(), 
_toBeImportedServices.end(), [&id](auto const &endpoint){
+            return id == endpoint->getEndpointId();
+        }), _toBeImportedServices.end());
 
-    auto instanceIt = _importedServiceInstances.find(id);
-    if (instanceIt == end(_importedServiceInstances)) {
-        return;
+        auto it = _importedServices.find(id);
+        if (it != _importedServices.end()) {
+            tmpStore = std::move(it->second);
+            _importedServices.erase(it);
+        }
     }
-
-    _ctx->getDependencyManager()->removeComponentAsync(instanceIt->second);
-    _importedServiceInstances.erase(instanceIt);
 }
 
-void celix::async_rsa::AsyncAdmin::addImportedServiceFactory(const 
std::shared_ptr<celix::async_rsa::IImportedServiceFactory>& factory, const 
std::shared_ptr<const celix::Properties>& properties) {
-    auto interface = properties->get(celix::rsa::Endpoint::EXPORTS);
-
-    if (interface.empty()) {
-        L_DEBUG("Adding service factory but no exported interfaces");
+void celix::async_rsa::AsyncAdmin::addImportedServiceFactory(
+        const std::shared_ptr<celix::rsa::IImportServiceFactory> &factory,
+        const std::shared_ptr<const celix::Properties> &properties) {
+    auto targetServiceName = 
properties->get(celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME);
+    if (targetServiceName.empty()) {
+        L_WARN("Adding service factory but missing %s property", 
celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME);
         return;
     }
 
-    std::lock_guard l(_m);
 
-    auto existingFactory = _importedServiceFactories.find(interface);
-    if(existingFactory != end(_importedServiceFactories)) {
+    std::lock_guard l(_m);
+    auto existingFactory = _importServiceFactories.find(targetServiceName);
+    if (existingFactory != end(_importServiceFactories)) {
         L_WARN("Adding imported factory but factory already exists");
         return;
     }
 
-    _importedServiceFactories.emplace(interface, factory);
+    _importServiceFactories.emplace(targetServiceName, factory);
 
     createImportServices();
 }
 
-void celix::async_rsa::AsyncAdmin::removeImportedServiceFactory(const 
std::shared_ptr<celix::async_rsa::IImportedServiceFactory>& /*factory*/, const 
std::shared_ptr<const celix::Properties>& properties) {
-    auto interface = properties->get(celix::rsa::Endpoint::EXPORTS);
-
-    if (interface.empty()) {
-        L_WARN("Removing service factory but missing exported interfaces");
+void celix::async_rsa::AsyncAdmin::removeImportedServiceFactory(
+        const std::shared_ptr<celix::rsa::IImportServiceFactory> &/*factory*/,
+        const std::shared_ptr<const celix::Properties> &properties) {
+    auto targetServiceName = 
properties->get(celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME);
+    if (targetServiceName.empty()) {
+        L_WARN("Removing service factory but missing %s property", 
celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME);
         return;
     }
 
     std::lock_guard l(_m);
-    _importedServiceFactories.erase(interface);
+    _importServiceFactories.erase(targetServiceName);
 
-    //TODO TBD are the removal of the imported services also needed when a 
ImportedServiceFactory is removed (and maybe the bundle is uninstalled?)
+    //TODO remove imported services from this factory ??needed
 }
 
-void celix::async_rsa::AsyncAdmin::addExportedServiceFactory(const 
std::shared_ptr<celix::async_rsa::IExportedServiceFactory>& factory, const 
std::shared_ptr<const celix::Properties>& properties) {
-    auto interface = properties->get(celix::rsa::Endpoint::EXPORTS);
-
-    if (interface.empty()) {
-        L_WARN("Adding exported factory but missing exported interfaces");
+void celix::async_rsa::AsyncAdmin::addExportedServiceFactory(
+        const std::shared_ptr<celix::rsa::IExportServiceFactory> &factory,
+        const std::shared_ptr<const celix::Properties> &properties) {
+    auto targetServiceName = 
properties->get(celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME);
+    if (targetServiceName.empty()) {
+        L_WARN("Adding service factory but missing %s property", 
celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME);
         return;
     }
 
     std::lock_guard<std::mutex> lock{_m};
-    _exportedServiceFactories.emplace(interface, factory);
+    _exportServiceFactories.emplace(targetServiceName, factory);
     createExportServices();
 }
 
-void celix::async_rsa::AsyncAdmin::removeExportedServiceFactory(const 
std::shared_ptr<celix::async_rsa::IExportedServiceFactory>& /*factory*/, const 
std::shared_ptr<const celix::Properties>& properties) {
-    auto interface = properties->get(celix::rsa::Endpoint::EXPORTS);
-
-    if(interface.empty()) {
-        L_WARN("Removing imported factory but missing exported interfaces");
+void celix::async_rsa::AsyncAdmin::removeExportedServiceFactory(
+        const std::shared_ptr<celix::rsa::IExportServiceFactory> &/*factory*/,
+        const std::shared_ptr<const celix::Properties> &properties) {
+    auto targetServiceName = 
properties->get(celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME);
+    if (targetServiceName.empty()) {
+        L_WARN("Removing service factory but missing %s property", 
celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME);
         return;
     }
 
     std::lock_guard l(_m);
-    _exportedServiceFactories.erase(interface);
+    _exportServiceFactories.erase(targetServiceName);
 
-    //TODO TBD are the removal of the exported services also needed when a 
ExportedServiceFactory is removed (and maybe the bundle is uninstalled?)
+    //TODO remove exported services from this factory ??needed
 }
 
-void celix::async_rsa::AsyncAdmin::addService(const std::shared_ptr<void>& 
svc, const std::shared_ptr<const celix::Properties>& props) {
-    assert(props->getAsBool(celix::rsa::REMOTE_SERVICE_PROPERTY_NAME, false)); 
//"only remote services should be tracker by the service tracker");
-
+void celix::async_rsa::AsyncAdmin::addService(const std::shared_ptr<void>& 
/*svc*/, const std::shared_ptr<const celix::Properties>& props) {
     auto serviceName = props->get(celix::SERVICE_NAME, "");
     if (serviceName.empty()) {
         L_WARN("Adding service to be exported but missing objectclass");
@@ -161,70 +156,71 @@ void celix::async_rsa::AsyncAdmin::addService(const 
std::shared_ptr<void>& svc,
     }
 
     std::lock_guard<std::mutex> lock{_m};
-    _toBeExportedServices.emplace_back(svc, props);
+    _toBeExportedServices.emplace_back(props);
     createExportServices();
 }
 
 void celix::async_rsa::AsyncAdmin::removeService(const std::shared_ptr<void>& 
/*svc*/, const std::shared_ptr<const celix::Properties>& props) {
-    assert(props->getAsBool(celix::rsa::REMOTE_SERVICE_PROPERTY_NAME, false)); 
//"only remote services should be tracker by the service tracker");
-
     long svcId = props->getAsLong(celix::SERVICE_ID, -1);
     if (svcId < 0) {
         L_WARN("Removing service to be exported but missing service.id");
         return;
     }
 
-    std::lock_guard l(_m);
+    std::unique_ptr<celix::rsa::IExportServiceRegistration> tmpStore{}; //to 
ensure destruction outside of lock
+    {
+        std::lock_guard l(_m);
 
-    //remove export interface (if present)
-    auto instanceIt = _exportedServiceInstances.find(svcId);
-    if (instanceIt != end(_exportedServiceInstances)) {
-        //note cannot remove async, because the svc lifetime needs to extend 
the lifetime of the component.
-        //TODO improve by creating export service based on svc id instead of 
svc pointer, so that export service can track its own dependencies.
-        _ctx->getDependencyManager()->removeComponent(instanceIt->second);
-        _exportedServiceInstances.erase(instanceIt);
-    }
+        auto instanceIt = _exportedServices.find(svcId);
+        if (instanceIt != end(_exportedServices)) {
+            tmpStore = std::move(instanceIt->second);
+            _exportedServices.erase(instanceIt);
+        }
 
-    //remove to be exported endpoint (if present)
-    for (auto it = _toBeExportedServices.begin(); it != 
_toBeExportedServices.end(); ++it) {
-        if (it->second->getAsBool(celix::SERVICE_ID, -1) == svcId) {
-            _toBeExportedServices.erase(it);
-            break;
+        //remove to be exported endpoint (if present)
+        for (auto it = _toBeExportedServices.begin(); it != 
_toBeExportedServices.end(); ++it) {
+            if ((*it)->getAsBool(celix::SERVICE_ID, -1) == svcId) {
+                _toBeExportedServices.erase(it);
+                break;
+            }
         }
     }
-
 }
 
 void celix::async_rsa::AsyncAdmin::createImportServices() {
-    for (auto it = _toBeImportedServices.begin(); it != 
_toBeImportedServices.end(); ++it) {
+    auto it = _toBeImportedServices.begin();
+    while (it != _toBeImportedServices.end()) {
         auto interface = (*it)->getExportedInterfaces();
-        auto existingFactory = _importedServiceFactories.find(interface);
-        if (existingFactory == end(_importedServiceFactories)) {
+        auto existingFactory = _importServiceFactories.find(interface);
+        if (existingFactory == end(_importServiceFactories)) {
             L_DEBUG("Adding endpoint to be imported but no factory available 
yet, delaying import");
+            ++it;
+            continue;
         }
         auto endpointId = (*it)->getEndpointId();
         L_DEBUG("Adding endpoint, created service");
-        _importedServiceInstances.emplace(endpointId, 
existingFactory->second->create(endpointId).getUUID());
+        _importedServices.emplace(endpointId, 
existingFactory->second->importService(**it));
         it = _toBeImportedServices.erase(it);
     }
 }
 
 void celix::async_rsa::AsyncAdmin::createExportServices() {
-    for (auto it = _toBeExportedServices.begin(); it != 
_toBeExportedServices.end(); ++it) {
-        auto serviceName = it->second->get(celix::SERVICE_NAME, "");
-        auto svcId = it->second->getAsLong(celix::SERVICE_ID, -1);
+    auto it = _toBeExportedServices.begin();
+    while (it != _toBeExportedServices.end()) {
+        const auto& svcProperties = **it;
+        auto serviceName = svcProperties.get(celix::SERVICE_NAME, "");
+        auto svcId = svcProperties.getAsLong(celix::SERVICE_ID, -1);
         if (serviceName.empty()) {
             L_WARN("Adding service to be exported but missing objectclass for 
svc id %li", svcId);
             continue;
         }
-        auto factory = _exportedServiceFactories.find(serviceName);
-        if (factory == end(_exportedServiceFactories)) {
+        auto factory = _exportServiceFactories.find(serviceName);
+        if (factory == end(_exportServiceFactories)) {
             L_DEBUG("Adding service to be exported but no factory available 
yet, delaying creation");
+            ++it;
             continue;
         }
-        auto endpointId = _ctx->getFramework()->getUUID() + "-" + 
std::to_string(svcId);
-        auto cmpUUID = factory->second->create(it->first.get(), 
std::move(endpointId)).getUUID();
-        _exportedServiceInstances.emplace(svcId, std::move(cmpUUID));
+        _exportedServices.emplace(svcId, 
factory->second->exportService(svcProperties));
         it = _toBeExportedServices.erase(it);
     }
 }
@@ -236,18 +232,18 @@ void celix::async_rsa::AsyncAdmin::setLogger(const 
std::shared_ptr<celix_log_ser
 class AdminActivator {
 public:
     explicit AdminActivator(const std::shared_ptr<celix::BundleContext>& ctx) {
-        auto admin = std::make_shared<celix::async_rsa::AsyncAdmin>(ctx);
+        auto admin = std::make_shared<celix::async_rsa::AsyncAdmin>();
 
         auto& cmp = ctx->getDependencyManager()->createComponent(admin);
         cmp.createServiceDependency<celix::rsa::Endpoint>()
                 .setRequired(false)
                 .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
                 .setCallbacks(&celix::async_rsa::AsyncAdmin::addEndpoint, 
&celix::async_rsa::AsyncAdmin::removeEndpoint);
-        
cmp.createServiceDependency<celix::async_rsa::IImportedServiceFactory>()
+        cmp.createServiceDependency<celix::rsa::IImportServiceFactory>()
                 .setRequired(false)
                 .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
                 
.setCallbacks(&celix::async_rsa::AsyncAdmin::addImportedServiceFactory, 
&celix::async_rsa::AsyncAdmin::removeImportedServiceFactory);
-        
cmp.createServiceDependency<celix::async_rsa::IExportedServiceFactory>()
+        cmp.createServiceDependency<celix::rsa::IExportServiceFactory>()
                 .setRequired(false)
                 .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
                 
.setCallbacks(&celix::async_rsa::AsyncAdmin::addExportedServiceFactory, 
&celix::async_rsa::AsyncAdmin::removeExportedServiceFactory);
@@ -259,8 +255,8 @@ public:
         cmp.build();
 
         //note adding void service dependencies is not supported for the 
dependency manager, using a service tracker instead.
-        _remoteServiceTracker = ctx->trackServices<void>()
-                
.setFilter(std::string{"("}.append(celix::rsa::REMOTE_SERVICE_PROPERTY_NAME).append("=*)"))
+        _remoteServiceTracker = ctx->trackAnyServices()
+                
.setFilter(std::string{"("}.append(celix::rsa::REMOTE_SERVICE_EXPORTED_PROPERTY_NAME).append("=*)"))
                 .addAddWithPropertiesCallback([admin](const 
std::shared_ptr<void>& svc, const std::shared_ptr<const celix::Properties>& 
properties) {
                     admin->addService(svc, properties);
                 })
diff --git a/bundles/async_remote_services/common/CMakeLists.txt 
b/bundles/async_remote_services/common/CMakeLists.txt
index 979305c..42888bd 100644
--- a/bundles/async_remote_services/common/CMakeLists.txt
+++ b/bundles/async_remote_services/common/CMakeLists.txt
@@ -21,6 +21,7 @@ target_include_directories(async_rsa_common INTERFACE
         $<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)
diff --git 
a/bundles/async_remote_services/common/include/ImportedServiceFactory.h 
b/bundles/async_remote_services/common/include/ImportedServiceFactory.h
index 5783d47..6a342f7 100644
--- a/bundles/async_remote_services/common/include/ImportedServiceFactory.h
+++ b/bundles/async_remote_services/common/include/ImportedServiceFactory.h
@@ -19,7 +19,6 @@
 #pragma once
 
 #include <celix/dm/DependencyManager.h>
-#include <pubsub_endpoint.h>
 
 namespace celix::async_rsa {
     /// Service factory interface.
diff --git a/bundles/async_remote_services/examples/CMakeLists.txt 
b/bundles/async_remote_services/examples/CMakeLists.txt
index 0935068..3aa8ee4 100644
--- a/bundles/async_remote_services/examples/CMakeLists.txt
+++ b/bundles/async_remote_services/examples/CMakeLists.txt
@@ -48,8 +48,8 @@ celix_bundle_files(hardcoded_example_subscriber
         DESTINATION "META-INF/topics/sub"
         )
 
-target_link_libraries(hardcoded_example_provider PRIVATE Celix::framework 
Celix::async_rsa_discovery_configured Celix::async_rsa_common Celix::async_rsa)
-target_link_libraries(hardcoded_example_subscriber PRIVATE Celix::framework 
Celix::async_rsa_discovery_configured Celix::async_rsa_common Celix::async_rsa)
+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)
 
@@ -78,7 +78,7 @@ add_celix_container(hardcoded_example_provider_cnt
         Celix::pubsub_protocol_wire_v2
         Celix::async_rsa_discovery_configured
         Celix::async_topology_manager
-        Celix::async_rsa
+        Celix::RemoteServiceAdmin
         hardcoded_example_provider
         PROPERTIES
         "org.osgi.framework.storage=.publisherCache"
@@ -99,7 +99,7 @@ add_celix_container(hardcoded_example_subscriber_cnt
         Celix::pubsub_protocol_wire_v2
         Celix::async_rsa_discovery_configured
         Celix::async_topology_manager
-        Celix::async_rsa
+        Celix::RemoteServiceAdmin
         hardcoded_example_subscriber
         PROPERTIES
         "org.osgi.framework.storage=.subscriberCache"
diff --git a/bundles/async_remote_services/rsa_spi/CMakeLists.txt 
b/bundles/async_remote_services/rsa_spi/CMakeLists.txt
index 33ed0a5..47568ff 100644
--- a/bundles/async_remote_services/rsa_spi/CMakeLists.txt
+++ b/bundles/async_remote_services/rsa_spi/CMakeLists.txt
@@ -20,7 +20,6 @@ target_include_directories(rsa_spi INTERFACE
     $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
     $<INSTALL_INTERFACE:include/celix/rsa>
 )
-target_link_libraries(rsa_spi INTERFACE Celix::async_rsa_discovery_configured)
 target_compile_options(rsa_spi INTERFACE -std=c++17)
 
 install(TARGETS rsa_spi EXPORT celix DESTINATION ${CMAKE_INSTALL_LIBDIR} 
COMPONENT rsa)
diff --git 
a/bundles/async_remote_services/rsa_spi/include/celix/rsa/Constants.h 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/Constants.h
index 2b5d0c4..5ae1c9f 100644
--- a/bundles/async_remote_services/rsa_spi/include/celix/rsa/Constants.h
+++ b/bundles/async_remote_services/rsa_spi/include/celix/rsa/Constants.h
@@ -23,9 +23,15 @@
 namespace celix::rsa {
 
     /**
-     * @brief Service property (named "remote") to mark a service as a remote 
service.
+     * @brief Service property (named "service.exported") to mark a service as 
wanting to be exported (remote).
      * Present means -> export service as a remote service.
      */
-    constexpr const char *const REMOTE_SERVICE_PROPERTY_NAME = "remote";
+    constexpr const char * const REMOTE_SERVICE_EXPORTED_PROPERTY_NAME = 
"service.exported";
+
+    /**
+     * @brief Service property (named "remote") to mark a service as a 
imported service.
+     * Present means -> service is a imported service (proxy of a remote 
service).
+     */
+    constexpr const char * const REMOTE_SERVICE_IMPORTED_PROPERTY_NAME = 
"service.imported";
 
 }
\ No newline at end of file
diff --git a/bundles/async_remote_services/rsa_spi/include/celix/rsa/Endpoint.h 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/Endpoint.h
index 97a81da..6035823 100644
--- a/bundles/async_remote_services/rsa_spi/include/celix/rsa/Endpoint.h
+++ b/bundles/async_remote_services/rsa_spi/include/celix/rsa/Endpoint.h
@@ -31,12 +31,12 @@ namespace celix::rsa {
     class Endpoint {
     public:
         static constexpr const char * const IDENTIFIER = "endpoint.id";
-        static constexpr const char * const IMPORTED = "service.imported";
-        static constexpr const char * const IMPORT_CONFIGS = 
"service.imported.configs";
+//        static constexpr const char * const IMPORTED = "service.imported";
+//        static constexpr const char * const IMPORT_CONFIGS = 
"service.imported.configs";
         static constexpr const char * const EXPORTS = 
"service.exported.interfaces";
-        static constexpr const char * const OBJECTCLASS = 
"endpoint.objectClass";
-        static constexpr const char * const SCOPE = "endpoint.scope";
-        static constexpr const char * const TOPIC = "endpoint.topic";
+//        static constexpr const char * const OBJECTCLASS = 
"endpoint.objectClass";
+//        static constexpr const char * const SCOPE = "endpoint.scope";
+//        static constexpr const char * const TOPIC = "endpoint.topic";
 
 
         /**
@@ -59,8 +59,6 @@ namespace celix::rsa {
             return _celixProperties.get(EXPORTS);
         }
 
-
-
     protected:
         celix::dm::Properties _celixProperties;
 
diff --git 
a/bundles/async_remote_services/rsa_spi/include/celix/rsa/IExportServiceFactory.h
 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/IExportServiceFactory.h
index b0a4c96..fa5508c 100644
--- 
a/bundles/async_remote_services/rsa_spi/include/celix/rsa/IExportServiceFactory.h
+++ 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/IExportServiceFactory.h
@@ -19,21 +19,17 @@
 #pragma once
 
 #include <memory>
+#include "celix/rsa/Endpoint.h"
 
 namespace celix::rsa {
 
     /**
-     * @brief ExportService class which represent a (opaque) exported service.
+     * @brief ExportServiceRegistration class which represent a (opaque) 
exported service.
      * The lifetime of this object should be coupled with the lifetime of the 
exported service.
      */
-    class ExportedService {
+    class IExportServiceRegistration {
     public:
-        virtual ~ExportedService() noexcept = default;
-
-        /**
-         * @brief returns the endpoint for this exported service (to be used 
in discovery).
-         */
-        virtual const celix::rsa::Endpoint& getEndpoint() const = 0;
+        virtual ~IExportServiceRegistration() noexcept = default;
     };
 
     /**
@@ -45,14 +41,12 @@ namespace celix::rsa {
      */
     class IExportServiceFactory {
     public:
-        static constexpr std::string_view TARGET_SERVICE_NAME = 
"target.service.name";
-
-        virtual ~IExportServiceFactory() noexcept = default;
-
         /**
          * @brief The service name for which this factory can created exported 
services.
          */
-        std::string& const getTargetServiceName() const = 0;
+        static constexpr const char * const TARGET_SERVICE_NAME = 
"target.service.name";
+
+        virtual ~IExportServiceFactory() noexcept = default;
 
         /**
          * @brief Exports the service identified with svcId
@@ -60,6 +54,6 @@ namespace celix::rsa {
          * @return A ExportService.
          * @throws celix::rsa::RemoteServicesException if the export failed.
          */
-        virtual std::unique_ptr<ExportedService> exportService(const 
celix::Properties& serviceProperties) = 0;
+        virtual std::unique_ptr<celix::rsa::IExportServiceRegistration> 
exportService(const celix::Properties& serviceProperties) = 0;
     };
 }
\ No newline at end of file
diff --git 
a/bundles/async_remote_services/rsa_spi/include/celix/rsa/IImportServiceFactory.h
 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/IImportServiceFactory.h
index 9427146..f62cf23 100644
--- 
a/bundles/async_remote_services/rsa_spi/include/celix/rsa/IImportServiceFactory.h
+++ 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/IImportServiceFactory.h
@@ -19,21 +19,17 @@
 #pragma once
 
 #include <memory>
+#include "celix/rsa/Endpoint.h"
 
 namespace celix::rsa {
 
     /**
-     * @brief ImportService class which represent a (opaque) imported service.
+     * @brief ImportServiceRegistration class which represent a (opaque) 
imported service.
      * The lifetime of this object should be coupled with the lifetime of the 
imported service.
      */
-    class ImportedService {
+    class IImportServiceRegistration {
     public:
-        virtual ~ImportedService() noexcept = default;
-
-        /**
-         * @brief returns the endpoint used for this imported service.
-         */
-        virtual const celix::rsa::Endpoint& getEndpoint() const = 0;
+        virtual ~IImportServiceRegistration() noexcept = default;
     };
 
     /**
@@ -45,14 +41,12 @@ namespace celix::rsa {
      */
     class IImportServiceFactory {
     public:
-        static constexpr std::string_view TARGET_SERVICE_NAME = 
"target.service.name";
-
-        virtual ~IImportServiceFactory() noexcept = default;
-
         /**
          * @brief The service name for which this factory can created exported 
services.
          */
-        std::string& const getTargetServiceName() const = 0;
+        static constexpr const char * const TARGET_SERVICE_NAME = 
"target.service.name";
+
+        virtual ~IImportServiceFactory() noexcept = default;
 
         /**
          * @brief Imports the service identified with svcId
@@ -60,6 +54,6 @@ namespace celix::rsa {
          * @return A ImportService.
          * @throws celix::rsa::RemoteServicesException if the import failed.
          */
-        virtual std::unique_ptr<ImportedService> importService(const 
celix::rsa::Endpoint& endpoint) = 0;
+        virtual std::unique_ptr<celix::rsa::IImportServiceRegistration> 
importService(const celix::rsa::Endpoint& endpoint) = 0;
     };
 }
\ No newline at end of file
diff --git a/libs/framework/include/celix/ServiceRegistration.h 
b/libs/framework/include/celix/ServiceRegistration.h
index 38981b0..d3e4d0c 100644
--- a/libs/framework/include/celix/ServiceRegistration.h
+++ b/libs/framework/include/celix/ServiceRegistration.h
@@ -208,6 +208,7 @@ namespace celix {
                         {
                             std::lock_guard<std::mutex> lck{reg->mutex};
                             reg->state = 
ServiceRegistrationState::UNREGISTERED;
+                            reg->svc.reset();
                         }
                         for (const auto &cb : reg->onUnregisteredCallbacks) {
                             cb(*reg);
@@ -229,6 +230,7 @@ namespace celix {
                     {
                         std::lock_guard<std::mutex> lck{mutex};
                         state = ServiceRegistrationState::UNREGISTERED;
+                        svc.reset();
                     }
                     for (const auto& cb: onUnregisteredCallbacks) {
                         cb(*this);
@@ -262,14 +264,14 @@ namespace celix {
                 std::vector<std::function<void(ServiceRegistration&)>> 
_onRegisteredCallbacks,
                 std::vector<std::function<void(ServiceRegistration&)>> 
_onUnregisteredCallbacks) :
                 cCtx{std::move(_cCtx)},
-                svc{std::move(_svc)},
                 name{std::move(_name)},
                 version{std::move(_version)},
                 properties{std::move(_properties)},
                 registerAsync{_registerAsync},
                 unregisterAsync{_unregisterAsync},
                 onRegisteredCallbacks{std::move(_onRegisteredCallbacks)},
-                onUnregisteredCallbacks{std::move(_onUnregisteredCallbacks)} {}
+                onUnregisteredCallbacks{std::move(_onUnregisteredCallbacks)},
+                svc{std::move(_svc)} {}
 
 
         /**
@@ -333,7 +335,6 @@ namespace celix {
         }
 
         const std::shared_ptr<celix_bundle_context_t> cCtx;
-        const std::shared_ptr<void> svc;
         const std::string name;
         const std::string version;
         const celix::Properties properties;
@@ -344,6 +345,7 @@ namespace celix {
 
         mutable std::mutex mutex{}; //protects below
         long svcId{-1};
+        std::shared_ptr<void> svc;
         ServiceRegistrationState state{ServiceRegistrationState::REGISTERING};
         std::weak_ptr<ServiceRegistration> self{}; //weak ptr to self, so that 
callbacks can receive a shared ptr
     };
diff --git a/libs/framework/include/celix/dm/DependencyManager_Impl.h 
b/libs/framework/include/celix/dm/DependencyManager_Impl.h
index 86a90c7..6ff1da2 100644
--- a/libs/framework/include/celix/dm/DependencyManager_Impl.h
+++ b/libs/framework/include/celix/dm/DependencyManager_Impl.h
@@ -27,7 +27,7 @@ inline 
DependencyManager::DependencyManager(celix_bundle_context_t *ctx) :
     cDepMan{celix_bundleContext_getDependencyManager(ctx), 
[](celix_dependency_manager_t*){/*nop*/}} {}
 
 inline DependencyManager::~DependencyManager() {
-    clear();
+    clearAsync();
 }
 
 template<class T>

Reply via email to