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

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

commit 270ef6415407cc7da9bffb377f28b443bbc01df9
Author: Pepijn Noltes <[email protected]>
AuthorDate: Fri Apr 9 10:54:58 2021 +0200

    Refactor remote service admin for update dep man and adds interfaces to 
rsa_spi target.
---
 .../async_remote_services/admin/include/admin.h    |  57 ++--
 bundles/async_remote_services/admin/src/admin.cc   | 345 ++++++++++-----------
 .../common/include/ExportedServiceFactory.h        |   4 +-
 .../include/ConfiguredDiscoveryManager.h           |  10 +-
 .../include/ConfiguredEndpoint.h                   |   2 +-
 .../src/ConfiguredDiscoveryManagerActivator.cc     |   2 +-
 .../discovery_configured/src/ConfiguredEndpoint.cc |  40 +--
 .../examples/HardcodedExampleProvider.cc           |   4 +-
 .../examples/HardcodedExampleSubscriber.cc         |   2 +-
 .../rsa_spi/include/Endpoint.h                     |  63 ----
 .../rsa_spi/include/celix/rsa/Constants.h          |  28 +-
 .../rsa_spi/include/celix/rsa/Endpoint.h           |  68 ++++
 .../rsa_spi/include/celix/rsa/Exception.h          |  21 ++
 .../rsa/IEndpointAnnouncer.h}                      |  25 +-
 .../include/celix/rsa/IExportServiceFactory.h      |  65 ++++
 .../rsa_spi/include/celix/rsa/IExportedService.h   |  36 +--
 .../include/celix/rsa/IImportServiceFactory.h      |  65 ++++
 .../topology_manager/include/topology_manager.h    |   6 +-
 .../topology_manager/src/topology_manager.cc       |   8 +-
 libs/framework/include/celix/dm/types.h            |   6 +-
 20 files changed, 478 insertions(+), 379 deletions(-)

diff --git a/bundles/async_remote_services/admin/include/admin.h 
b/bundles/async_remote_services/admin/include/admin.h
index 57e043b..cf5a58a 100644
--- a/bundles/async_remote_services/admin/include/admin.h
+++ b/bundles/async_remote_services/admin/include/admin.h
@@ -17,13 +17,14 @@
  * under the License.
  */
 
-#include <Endpoint.h>
+#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>)
 #include <version>
@@ -51,8 +52,8 @@ namespace celix::async_rsa {
 
     class AsyncAdmin {
     public:
-        explicit AsyncAdmin(std::shared_ptr<celix::dm::DependencyManager> 
&mng) noexcept;
-        ~AsyncAdmin();
+        explicit AsyncAdmin(std::shared_ptr<celix::BundleContext> ctx) 
noexcept;
+        ~AsyncAdmin() noexcept = default;
 
         AsyncAdmin(AsyncAdmin const &) = delete;
         AsyncAdmin(AsyncAdmin&&) = delete;
@@ -60,44 +61,44 @@ namespace celix::async_rsa {
         AsyncAdmin& operator=(AsyncAdmin&&) = delete;
 
         // Imported endpoint add/remove functions
-        void addEndpoint(celix::rsa::Endpoint* endpoint, Properties 
&&properties);
-        void removeEndpoint(celix::rsa::Endpoint* endpoint, Properties 
&&properties);
+        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(celix::async_rsa::IImportedServiceFactory *factory, 
Properties&& properties);
-        void 
removeImportedServiceFactory(celix::async_rsa::IImportedServiceFactory 
*factory, Properties&& properties);
+        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);
 
         // Exported endpoint add/remove functions
-        void 
addExportedServiceFactory(celix::async_rsa::IExportedServiceFactory *factory, 
Properties&& properties);
-        void 
removeExportedServiceFactory(celix::async_rsa::IExportedServiceFactory 
*factory, Properties&& properties);
+        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);
 
         // Add/remove services, used to track all services registered with 
celix and check if remote = true.
-        void addService(void *svc, const celix_properties_t *props);
-        void removeService(void *svc, const celix_properties_t *props);
-
+        void addService(const std::shared_ptr<void>& svc, const 
std::shared_ptr<const celix::Properties>& properties);
+        void removeService(const std::shared_ptr<void>& svc, const 
std::shared_ptr<const celix::Properties>& properties);
 
+        // Set logging service
+        void setLogger(const std::shared_ptr<celix_log_service>& logService);
     private:
-        std::shared_ptr<celix::dm::DependencyManager> _mng{};
-        celix_log_helper_t *_logger;
-        long _serviceTrackerId{-1};
+        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, 
celix::async_rsa::IExportedServiceFactory*> 
_exportedServiceFactories{&_memResource};
-        std::pmr::unordered_map<std::string, 
celix::async_rsa::IImportedServiceFactory*> 
_importedServiceFactories{&_memResource};
-        std::pmr::unordered_map<std::string, celix::dm::BaseComponent&> 
_importedServiceInstances{&_memResource};
-        std::pmr::unordered_map<std::string, celix::dm::BaseComponent&> 
_exportedServiceInstances{&_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.
 #else
-        std::unordered_map<std::string, 
celix::async_rsa::IExportedServiceFactory*> _exportedServiceFactories{};
-        std::unordered_map<std::string, 
celix::async_rsa::IImportedServiceFactory*> _importedServiceFactories{};
-        std::unordered_map<std::string, celix::dm::BaseComponent&> 
_importedServiceInstances{};
-        std::unordered_map<std::string, celix::dm::BaseComponent&> 
_exportedServiceInstances{};
+        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{};
 #endif
-        std::vector<celix::rsa::Endpoint> _toBeCreatedImportedEndpoints{};
-        std::vector<std::pair<void*, Properties>> 
_toBeCreatedExportedEndpoints{};
-
-        // Internal functions for code re-use
-        void addEndpointInternal(celix::rsa::Endpoint& endpoint);
+        std::vector<std::shared_ptr<celix::rsa::Endpoint>> 
_toBeImportedServices{};
+        std::vector<std::pair<std::shared_ptr<void>, 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 7dbc6d9..348ebcb 100644
--- a/bundles/async_remote_services/admin/src/admin.cc
+++ b/bundles/async_remote_services/admin/src/admin.cc
@@ -21,82 +21,80 @@
 #include <celix_api.h>
 #include <pubsub_message_serialization_service.h>
 #include <ConfiguredEndpoint.h>
+#include "celix/rsa/Constants.h"
 
 #define L_DEBUG(...) \
-    celix_logHelper_log(_logger, CELIX_LOG_LEVEL_DEBUG, __VA_ARGS__)
+    if (_logService) {                                                  \
+        _logService->debug(_logService->handle, __VA_ARGS__);           \
+    }
 #define L_INFO(...) \
-    celix_logHelper_log(_logger, CELIX_LOG_LEVEL_INFO, __VA_ARGS__)
+    if (_logService) {                                                  \
+        _logService->info(_logService->handle, __VA_ARGS__);            \
+    }
 #define L_WARN(...) \
-    celix_logHelper_log(_logger, CELIX_LOG_LEVEL_WARNING, __VA_ARGS__)
+    if (_logService) {                                                  \
+        _logService->warning(_logService->handle, __VA_ARGS__);         \
+    }
 #define L_ERROR(...) \
-    celix_logHelper_log(_logger, CELIX_LOG_LEVEL_ERROR, __VA_ARGS__)
-
-celix::async_rsa::AsyncAdmin::AsyncAdmin(std::shared_ptr<celix::dm::DependencyManager>
 &mng) noexcept : _mng(mng), 
_logger(celix_logHelper_create(mng->bundleContext(), "celix_async_rsa_admin")) {
-
-    // C++ version of tracking services without type not possible (yet?)
-    celix_service_tracking_options_t opts{};
-    opts.callbackHandle = this;
-    opts.addWithProperties = [](void *handle, void *svc, const 
celix_properties_t *props){
-        auto *admin = static_cast<AsyncAdmin*>(handle);
-        admin->addService(svc, props);
-    };
-    opts.removeWithProperties = [](void *handle, void *svc, const 
celix_properties_t *props){
-        auto *admin = static_cast<AsyncAdmin*>(handle);
-        admin->removeService(svc, props);
-    };
-    _serviceTrackerId = 
celix_bundleContext_trackServicesWithOptions(_mng->bundleContext(), &opts);
-
-    if(_serviceTrackerId < 0) {
-        L_ERROR("couldn't register tracker");
+    if (_logService) {                                                  \
+        _logService->error(_logService->handle, __VA_ARGS__);           \
     }
-}
 
-celix::async_rsa::AsyncAdmin::~AsyncAdmin() {
-    celix_logHelper_destroy(_logger);
-    celix_bundleContext_stopTracker(_mng->bundleContext(), _serviceTrackerId);
+celix::async_rsa::AsyncAdmin::AsyncAdmin(std::shared_ptr<celix::BundleContext> 
ctx) noexcept : _ctx{std::move(ctx)} {
+
 }
 
-void celix::async_rsa::AsyncAdmin::addEndpoint(celix::rsa::Endpoint* endpoint, 
[[maybe_unused]] Properties &&properties) {
+void celix::async_rsa::AsyncAdmin::addEndpoint(const 
std::shared_ptr<celix::rsa::Endpoint>& endpoint) {
+    assert(endpoint);
     std::unique_lock l(_m);
-    addEndpointInternal(*endpoint);
-}
 
-void celix::async_rsa::AsyncAdmin::removeEndpoint([[maybe_unused]] 
celix::rsa::Endpoint* endpoint, [[maybe_unused]] Properties &&properties) {
-    auto interface = properties.get(ENDPOINT_EXPORTS);
+    auto interface = endpoint->getExportedInterfaces();
+    if (interface.empty()) {
+        L_WARN("Adding endpoint but missing exported interfaces");
+        return;
+    }
 
-    if(interface.empty()) {
-        L_DEBUG("Removing endpoint but no exported interfaces");
+    auto endpointId = endpoint->getEndpointId();
+    if (endpointId.empty()) {
+        L_WARN("Adding endpoint but missing service id");
         return;
     }
+    _toBeImportedServices.emplace_back(endpoint);
 
-    std::unique_lock l(_m);
+    l.unlock();
+    createImportServices();
+}
 
-    
_toBeCreatedImportedEndpoints.erase(std::remove_if(_toBeCreatedImportedEndpoints.begin(),
 _toBeCreatedImportedEndpoints.end(), [&interface](auto const &endpoint){
-        auto endpointInterface = 
endpoint.getProperties().get(ENDPOINT_EXPORTS);
-        return !endpointInterface.empty() && endpointInterface == interface;
-    }), _toBeCreatedImportedEndpoints.end());
+void celix::async_rsa::AsyncAdmin::removeEndpoint(const 
std::shared_ptr<celix::rsa::Endpoint>& endpoint) {
+    assert(endpoint);
+    std::unique_lock l(_m);
 
-    auto svcId = properties.get(ENDPOINT_IDENTIFIER);
+    auto id = endpoint->getEndpointId();
 
-    if(svcId.empty()) {
-        L_DEBUG("Removing endpoint but no service instance");
+    if (id.empty()) {
+        L_WARN("Cannot remove endpoint without a valid id");
         return;
     }
 
-    auto instanceIt = _importedServiceInstances.find(svcId);
+    _toBeImportedServices.erase(std::remove_if(_toBeImportedServices.begin(), 
_toBeImportedServices.end(), [&id](auto const &endpoint){
+        return id == endpoint->getEndpointId();
+    }), _toBeImportedServices.end());
 
-    if(instanceIt == end(_importedServiceInstances)) {
+
+    auto instanceIt = _importedServiceInstances.find(id);
+
+    if (instanceIt == end(_importedServiceInstances)) {
         return;
     }
 
-    _mng->destroyComponent(instanceIt->second);
+    _ctx->getDependencyManager()->removeComponentAsync(instanceIt->second);
     _importedServiceInstances.erase(instanceIt);
 }
 
-void 
celix::async_rsa::AsyncAdmin::addImportedServiceFactory(celix::async_rsa::IImportedServiceFactory
 *factory, Properties &&properties) {
-    auto interface = properties.get(ENDPOINT_EXPORTS);
+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()) {
+    if (interface.empty()) {
         L_DEBUG("Adding service factory but no exported interfaces");
         return;
     }
@@ -112,64 +110,59 @@ void 
celix::async_rsa::AsyncAdmin::addImportedServiceFactory(celix::async_rsa::I
 
     _importedServiceFactories.emplace(interface, factory);
 
-    for(auto it = _toBeCreatedImportedEndpoints.begin(); it != 
_toBeCreatedImportedEndpoints.end();) {
-        auto tbceInterface = it->getProperties().get(ENDPOINT_EXPORTS);
-        if(tbceInterface.empty() || tbceInterface != interface) {
-            it++;
-        } else {
-            addEndpointInternal(*it);
-            _toBeCreatedImportedEndpoints.erase(it);
-        }
-    }
+    l.unlock();
+    createImportServices();
 }
 
-void 
celix::async_rsa::AsyncAdmin::removeImportedServiceFactory([[maybe_unused]] 
celix::async_rsa::IImportedServiceFactory *factory, Properties &&properties) {
-    auto interface = properties.get(ENDPOINT_EXPORTS);
+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()) {
+    if (interface.empty()) {
         L_WARN("Removing service factory but missing exported interfaces");
         return;
     }
 
     std::unique_lock l(_m);
     _importedServiceFactories.erase(interface);
-}
 
-void 
celix::async_rsa::AsyncAdmin::addExportedServiceFactory(celix::async_rsa::IExportedServiceFactory
 *factory, Properties&& properties) {
-    auto interface = properties.get(ENDPOINT_EXPORTS);
+    //TODO TBD are the removal of the imported services also needed when a 
ImportedServiceFactory is removed (and maybe the bundle is uninstalled?)
+}
 
-    if(interface.empty()) {
-        L_WARN("Adding exported factory but missing exported interfaces");
-        return;
+void celix::async_rsa::AsyncAdmin::createImportServices() {
+    std::lock_guard<std::mutex> lock{_m};
+
+    for (auto it = _toBeImportedServices.begin(); it != 
_toBeImportedServices.end(); ++it) {
+        auto interface = (*it)->getExportedInterfaces();
+        auto existingFactory = _importedServiceFactories.find(interface);
+        if (existingFactory != end(_importedServiceFactories)) {
+            auto endpointId = (*it)->getEndpointId();
+            L_DEBUG("Adding endpoint, created service");
+            _importedServiceInstances.emplace(endpointId, 
existingFactory->second->create(endpointId).getUUID());
+            _toBeImportedServices.erase(it--);
+        } else {
+            L_DEBUG("Adding endpoint to be imported but no factory available 
yet, delaying import");
+        }
     }
+}
 
-    std::unique_lock l(_m);
-    auto factoryIt = _exportedServiceFactories.find(interface);
+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(factoryIt != end(_exportedServiceFactories)) {
-        L_WARN("Adding exported factory but factory already exists");
+    if (interface.empty()) {
+        L_WARN("Adding exported factory but missing exported interfaces");
         return;
     }
 
-    _exportedServiceFactories.emplace(interface, factory);
-    L_WARN("Looping over %i tbce for interface %s", 
_toBeCreatedExportedEndpoints.size(), interface.c_str());
-
-    for(auto it = _toBeCreatedExportedEndpoints.begin(); it != 
_toBeCreatedExportedEndpoints.end(); ) {
-        auto interfaceToBeCreated = it->second.get(ENDPOINT_EXPORTS);
-        L_WARN("Checking tbce interface %s", interfaceToBeCreated.c_str());
-
-        if(interfaceToBeCreated.empty() || interfaceToBeCreated != interface) {
-            it++;
-        } else {
-            auto endpointId = it->second.get(ENDPOINT_IDENTIFIER);
-            _exportedServiceInstances.emplace(endpointId, 
factory->create(it->first, endpointId));
-            it = _toBeCreatedExportedEndpoints.erase(it);
-        }
+    {
+        std::lock_guard<std::mutex> lock{_m};
+        _exportedServiceFactories.emplace(interface, factory);
     }
+
+    createExportServices();
 }
 
-void 
celix::async_rsa::AsyncAdmin::removeExportedServiceFactory(celix::async_rsa::IExportedServiceFactory
 *, Properties&& properties) {
-    auto interface = properties.get(ENDPOINT_EXPORTS);
+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");
@@ -178,143 +171,121 @@ void 
celix::async_rsa::AsyncAdmin::removeExportedServiceFactory(celix::async_rsa
 
     std::unique_lock l(_m);
     _exportedServiceFactories.erase(interface);
+
+    //TODO TBD are the removal of the exported services also needed when a 
ExportedServiceFactory is removed (and maybe the bundle is uninstalled?)
 }
 
-void celix::async_rsa::AsyncAdmin::addService(void *svc, const 
celix_properties_t *props) {
-    auto *objectClass = celix_properties_get(props, 
OSGI_FRAMEWORK_OBJECTCLASS, nullptr);
-    auto *remote = celix_properties_get(props, "remote", nullptr);
-    auto endpointId = celix_properties_get(props, ENDPOINT_IDENTIFIER, 
nullptr);
+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");
 
-    if(objectClass == nullptr) {
+    auto serviceName = props->get(celix::SERVICE_NAME, "");
+    if (serviceName.empty()) {
         L_WARN("Adding service to be exported but missing objectclass");
         return;
     }
 
-    if(remote == nullptr) {
-        // not every service is remote, this is fine but not something the RSA 
admin is interested in.
-        return;
-    } else {
-        L_WARN("found remote service %s", objectClass);
-    }
-
-    if(endpointId == nullptr) {
-        L_WARN("Adding service to be exported but missing endpoint.id");
-        return;
-    }
-
-    std::unique_lock l(_m);
-    auto factory = _exportedServiceFactories.find(objectClass);
-
-    if(factory == end(_exportedServiceFactories)) {
-        L_WARN("Adding service to be exported but no factory available yet, 
delaying creation");
-
-        Properties cppProps;
-
-        auto it = celix_propertiesIterator_construct(props);
-        const char* key;
-        while(key = celix_propertiesIterator_nextKey(&it), key != nullptr) {
-            cppProps.set(key, celix_properties_get(props, key, nullptr));
-        }
-
-        _toBeCreatedExportedEndpoints.emplace_back(std::make_pair(svc, 
std::move(cppProps)));
-        return;
+    {
+        std::lock_guard<std::mutex> lock{_m};
+        _toBeExportedServices.emplace_back(std::make_pair(std::move(svc), 
std::move(props)));
     }
 
-    _exportedServiceInstances.emplace(endpointId, factory->second->create(svc, 
endpointId));
+    createExportServices();
 }
 
-void celix::async_rsa::AsyncAdmin::removeService(void *, const 
celix_properties_t *props) {
-    auto *objectClass = celix_properties_get(props, 
OSGI_FRAMEWORK_OBJECTCLASS, nullptr);
-    auto *remote = celix_properties_get(props, "remote", nullptr);
-    auto svcId = celix_properties_get(props, ENDPOINT_IDENTIFIER, nullptr);
-
-    if(objectClass == nullptr) {
-        L_WARN("Removing service to be exported but missing objectclass");
-        return;
-    }
-
-    if(remote == nullptr) {
-        // not every service is remote, this is fine but not something the RSA 
admin is interested in.
-        return;
-    }
+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");
 
-    if(svcId == nullptr) {
-        L_WARN("Removing service to be exported but missing endpoint.id");
+    long svcId = props->getAsLong(celix::SERVICE_ID, -1);
+    if (svcId < 0) {
+        L_WARN("Removing service to be exported but missing service.id");
         return;
     }
 
     std::unique_lock l(_m);
-    auto instanceIt = _exportedServiceInstances.find(svcId);
 
-    if(instanceIt == end(_exportedServiceInstances)) {
-        return;
+    //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);
     }
 
-    _mng->destroyComponent(instanceIt->second);
-    _exportedServiceInstances.erase(instanceIt);
-}
-
-void celix::async_rsa::AsyncAdmin::addEndpointInternal(celix::rsa::Endpoint& 
endpoint) {
-
-    const auto& properties = endpoint.getProperties();
-    auto interface = properties.get(ENDPOINT_EXPORTS);
-
-    if(interface.empty()) {
-        L_WARN("Adding endpoint but missing exported interfaces");
-        return;
+    //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;
+        }
     }
 
-    auto endpointId = properties.get(ENDPOINT_IDENTIFIER);
-
-    if(endpointId.empty()) {
-        L_WARN("Adding endpoint but missing service id");
-        return;
-    }
+}
 
-    auto existingFactory = _importedServiceFactories.find(interface);
+void celix::async_rsa::AsyncAdmin::createExportServices() {
+    std::lock_guard<std::mutex> lock{_m};
 
-    if(existingFactory == end(_importedServiceFactories)) {
-        L_DEBUG("Adding endpoint but no factory available yet, delaying 
creation");
-        
_toBeCreatedImportedEndpoints.emplace_back(celix::rsa::Endpoint{properties});
-        return;
+    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);
+        if (serviceName.empty()) {
+            L_WARN("Adding service to be exported but missing objectclass for 
svc id %li", svcId);
+        } else {
+            auto factory = _exportedServiceFactories.find(serviceName);
+            if (factory != _exportedServiceFactories.end()) {
+                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));
+                _toBeExportedServices.erase(it--);
+            } else {
+                L_DEBUG("Adding service to be exported but no factory 
available yet, delaying creation");
+            }
+        }
     }
+}
 
-    L_DEBUG("Adding endpoint, created service");
-    _importedServiceInstances.emplace(endpointId, 
existingFactory->second->create(endpointId));
+void celix::async_rsa::AsyncAdmin::setLogger(const 
std::shared_ptr<celix_log_service>& logService) {
+    _logService = logService;
 }
 
 class AdminActivator {
 public:
-    explicit AdminActivator(std::shared_ptr<celix::dm::DependencyManager> mng) 
:
-            
_cmp(mng->createComponent(std::make_unique<celix::async_rsa::AsyncAdmin>(mng))),
 _mng(std::move(mng)) {
+    explicit AdminActivator(const std::shared_ptr<celix::BundleContext>& ctx) {
+        auto admin = std::make_shared<celix::async_rsa::AsyncAdmin>(ctx);
 
-        _cmp.createServiceDependency<celix::rsa::Endpoint>()
+        auto& cmp = ctx->getDependencyManager()->createComponent(admin);
+        cmp.createServiceDependency<celix::rsa::Endpoint>()
                 .setRequired(false)
-                .setCallbacks(&celix::async_rsa::AsyncAdmin::addEndpoint, 
&celix::async_rsa::AsyncAdmin::removeEndpoint)
-                .build();
-
-        
_cmp.createServiceDependency<celix::async_rsa::IImportedServiceFactory>()
+                .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
+                .setCallbacks(&celix::async_rsa::AsyncAdmin::addEndpoint, 
&celix::async_rsa::AsyncAdmin::removeEndpoint);
+        
cmp.createServiceDependency<celix::async_rsa::IImportedServiceFactory>()
                 .setRequired(false)
-                
.setCallbacks(&celix::async_rsa::AsyncAdmin::addImportedServiceFactory, 
&celix::async_rsa::AsyncAdmin::removeImportedServiceFactory)
-                .build();
-
-        
_cmp.createServiceDependency<celix::async_rsa::IExportedServiceFactory>()
+                .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
+                
.setCallbacks(&celix::async_rsa::AsyncAdmin::addImportedServiceFactory, 
&celix::async_rsa::AsyncAdmin::removeImportedServiceFactory);
+        
cmp.createServiceDependency<celix::async_rsa::IExportedServiceFactory>()
                 .setRequired(false)
-                
.setCallbacks(&celix::async_rsa::AsyncAdmin::addExportedServiceFactory, 
&celix::async_rsa::AsyncAdmin::removeExportedServiceFactory)
+                .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
+                
.setCallbacks(&celix::async_rsa::AsyncAdmin::addExportedServiceFactory, 
&celix::async_rsa::AsyncAdmin::removeExportedServiceFactory);
+        cmp.createServiceDependency<celix_log_service>(CELIX_LOG_SERVICE_NAME)
+                .setRequired(false)
+                
.setFilter(std::string{"("}.append(CELIX_LOG_SERVICE_PROPERTY_NAME).append("=celix::rsa::RemoteServiceAdmin)"))
+                .setStrategy(celix::dm::DependencyUpdateStrategy::suspend)
+                .setCallbacks(&celix::async_rsa::AsyncAdmin::setLogger);
+        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("=*)"))
+                .addAddWithPropertiesCallback([admin](const 
std::shared_ptr<void>& svc, const std::shared_ptr<const celix::Properties>& 
properties) {
+                    admin->addService(svc, properties);
+                })
+                .addRemWithPropertiesCallback([admin](const 
std::shared_ptr<void>& svc, const std::shared_ptr<const celix::Properties>& 
properties) {
+                    admin->removeService(svc, properties);
+                })
                 .build();
-
-        _cmp.build();
     }
-
-    ~AdminActivator() noexcept {
-        _mng->destroyComponent(_cmp);
-    }
-
-    AdminActivator(const AdminActivator &) = delete;
-    AdminActivator &operator=(const AdminActivator &) = delete;
 private:
-    celix::dm::Component<celix::async_rsa::AsyncAdmin>& _cmp;
-    std::shared_ptr<celix::dm::DependencyManager> _mng;
+    std::shared_ptr<celix::ServiceTracker<void>> _remoteServiceTracker{};
 };
 
-CELIX_GEN_CXX_BUNDLE_ACTIVATOR(AdminActivator)
+CELIX_GEN_CXX_BUNDLE_ACTIVATOR(AdminActivator)
\ No newline at end of file
diff --git 
a/bundles/async_remote_services/common/include/ExportedServiceFactory.h 
b/bundles/async_remote_services/common/include/ExportedServiceFactory.h
index 258916f..6dcc0c9 100644
--- a/bundles/async_remote_services/common/include/ExportedServiceFactory.h
+++ b/bundles/async_remote_services/common/include/ExportedServiceFactory.h
@@ -21,7 +21,7 @@
 #include <celix/dm/DependencyManager.h>
 #include <pubsub_endpoint.h>
 #include <IExportedService.h>
-#include <Endpoint.h>
+#include "celix/rsa/Endpoint.h"
 
 namespace celix::async_rsa {
     /// Service factory interface.
@@ -59,7 +59,7 @@ namespace celix::async_rsa {
             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{{ENDPOINT_EXPORTS, std::string{SvcInterfaceT::NAME}}, 
{ENDPOINT_IMPORTED, "false"}, {ENDPOINT_IDENTIFIER, endpointId}});
+                    .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)")
diff --git 
a/bundles/async_remote_services/discovery_configured/include/ConfiguredDiscoveryManager.h
 
b/bundles/async_remote_services/discovery_configured/include/ConfiguredDiscoveryManager.h
index 58c8a2f..f4646c6 100644
--- 
a/bundles/async_remote_services/discovery_configured/include/ConfiguredDiscoveryManager.h
+++ 
b/bundles/async_remote_services/discovery_configured/include/ConfiguredDiscoveryManager.h
@@ -18,13 +18,13 @@
  */
 #pragma once
 
-#include <EndpointAnnouncer.h>
+#include "celix/rsa/IEndpointAnnouncer.h"
 
 #include <memory>
 #include <vector>
 #include <string>
 
-#include <Endpoint.h>
+#include "celix/rsa/Endpoint.h"
 #include <celix_api.h>
 
 #include <ConfiguredEndpoint.h>
@@ -42,7 +42,7 @@ namespace celix::rsa {
  * a local configuration JSON file.
  * This configured discovery manager announces local exported endpoints and 
imported endpoints from the JSON file.
  */
-class ConfiguredDiscoveryManager final : public EndpointAnnouncer {
+class ConfiguredDiscoveryManager final : public IEndpointAnnouncer {
 public:
 
     /**
@@ -71,6 +71,10 @@ public:
      */
     ConfiguredDiscoveryManager& operator=(const ConfiguredDiscoveryManager&) = 
delete;
 
+    void announceEndpoint(std::unique_ptr<Endpoint> /*endpoint*/) override 
{/*nop*/}
+
+    void revokeEndpoint(std::unique_ptr<Endpoint> /*endpoint*/) override 
{/*nop*/}
+
 private:
 
     void discoverEndpoints();
diff --git 
a/bundles/async_remote_services/discovery_configured/include/ConfiguredEndpoint.h
 
b/bundles/async_remote_services/discovery_configured/include/ConfiguredEndpoint.h
index 9ae110f..a107397 100644
--- 
a/bundles/async_remote_services/discovery_configured/include/ConfiguredEndpoint.h
+++ 
b/bundles/async_remote_services/discovery_configured/include/ConfiguredEndpoint.h
@@ -18,7 +18,7 @@
  */
 #pragma once
 
-#include <Endpoint.h>
+#include "celix/rsa/Endpoint.h"
 #include <ConfiguredEndpointProperties.h>
 
 #include <optional>
diff --git 
a/bundles/async_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc
 
b/bundles/async_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc
index 4beba4d..e5758f6 100644
--- 
a/bundles/async_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc
+++ 
b/bundles/async_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc
@@ -26,7 +26,7 @@ 
ConfiguredDiscoveryManagerActivator::ConfiguredDiscoveryManagerActivator(
         const std::shared_ptr<celix::dm::DependencyManager>& 
dependencyManager) :
             _component{dependencyManager->createComponent(
                 
std::make_unique<celix::rsa::ConfiguredDiscoveryManager>(dependencyManager))
-                                        
.addInterface<celix::rsa::EndpointAnnouncer>().build()}, 
_mng(dependencyManager) {
+                                        
.addInterface<celix::rsa::IEndpointAnnouncer>().build()}, 
_mng(dependencyManager) {
 }
 
     
ConfiguredDiscoveryManagerActivator::~ConfiguredDiscoveryManagerActivator() {
diff --git 
a/bundles/async_remote_services/discovery_configured/src/ConfiguredEndpoint.cc 
b/bundles/async_remote_services/discovery_configured/src/ConfiguredEndpoint.cc
index 4327b3f..0ded5c1 100644
--- 
a/bundles/async_remote_services/discovery_configured/src/ConfiguredEndpoint.cc
+++ 
b/bundles/async_remote_services/discovery_configured/src/ConfiguredEndpoint.cc
@@ -23,16 +23,16 @@ namespace celix::rsa {
 
 celix::dm::Properties convertEndpointPropertiesToCelix(const 
ConfiguredEndpointProperties& endpointProperties) {
 
-    return celix::dm::Properties{{ENDPOINT_IMPORTED, 
std::to_string(endpointProperties.isImported()).c_str()},
-                                 {ENDPOINT_EXPORTS, 
endpointProperties.getExports()},
-                                 {ENDPOINT_IDENTIFIER, 
endpointProperties.getId()}};
+    return celix::dm::Properties{{celix::rsa::Endpoint::IMPORTED, 
std::to_string(endpointProperties.isImported()).c_str()},
+                                 {celix::rsa::Endpoint::EXPORTS, 
endpointProperties.getExports()},
+                                 {celix::rsa::Endpoint::IDENTIFIER, 
endpointProperties.getId()}};
 }
 
 ConfiguredEndpointProperties convertCelixPropertiesToEndpoint(const 
celix::dm::Properties& celixProperties) {
 
-    auto endpointId = celixProperties.get(ENDPOINT_IDENTIFIER);
-    auto exports = celixProperties.get(ENDPOINT_EXPORTS);
-    auto imported = celixProperties.get(ENDPOINT_IMPORTED);
+    auto endpointId = celixProperties.get(celix::rsa::Endpoint::IDENTIFIER);
+    auto exports = celixProperties.get(celix::rsa::Endpoint::EXPORTS);
+    auto imported = celixProperties.get(celix::rsa::Endpoint::IMPORTED);
     return ConfiguredEndpointProperties{endpointId,
                                         (imported == "true"),
                                         {}, exports, {}, "", ""};
@@ -40,13 +40,13 @@ ConfiguredEndpointProperties 
convertCelixPropertiesToEndpoint(const celix::dm::P
 
 bool isValidEndpointJson(const rapidjson::Value& endpointJson) {
 
-    return (endpointJson.HasMember(ENDPOINT_IDENTIFIER)
-         && endpointJson.HasMember(ENDPOINT_IMPORTED)
-         && endpointJson.HasMember(ENDPOINT_IMPORT_CONFIGS)
-         && endpointJson.HasMember(ENDPOINT_EXPORTS)
-         && endpointJson.HasMember(ENDPOINT_OBJECTCLASS)
-         && endpointJson.HasMember(ENDPOINT_SCOPE)
-         && endpointJson.HasMember(ENDPOINT_TOPIC));
+    return (endpointJson.HasMember(celix::rsa::Endpoint::IDENTIFIER)
+         && endpointJson.HasMember(celix::rsa::Endpoint::IMPORTED)
+         && endpointJson.HasMember(celix::rsa::Endpoint::IMPORT_CONFIGS)
+         && endpointJson.HasMember(celix::rsa::Endpoint::EXPORTS)
+         && endpointJson.HasMember(celix::rsa::Endpoint::OBJECTCLASS)
+         && endpointJson.HasMember(celix::rsa::Endpoint::SCOPE)
+         && endpointJson.HasMember(celix::rsa::Endpoint::TOPIC));
 }
 
 std::vector<std::string> parseJSONStringArray(const rapidjson::Value& 
jsonArray) {
@@ -69,13 +69,13 @@ ConfiguredEndpoint::ConfiguredEndpoint(const 
rapidjson::Value& endpointJson) :
 
     if (isValidEndpointJson(endpointJson)) {
 
-        _configuredProperties = {endpointJson[ENDPOINT_IDENTIFIER].GetString(),
-                                 endpointJson[ENDPOINT_IMPORTED].GetBool(),
-                                 
parseJSONStringArray(endpointJson[ENDPOINT_IMPORT_CONFIGS]),
-                                 endpointJson[ENDPOINT_EXPORTS].GetString(),
-                                 
parseJSONStringArray(endpointJson[ENDPOINT_OBJECTCLASS]),
-                                 endpointJson[ENDPOINT_SCOPE].GetString(),
-                                 endpointJson[ENDPOINT_TOPIC].GetString()};
+        _configuredProperties = 
{endpointJson[celix::rsa::Endpoint::IDENTIFIER].GetString(),
+                                 
endpointJson[celix::rsa::Endpoint::IMPORTED].GetBool(),
+                                 
parseJSONStringArray(endpointJson[celix::rsa::Endpoint::IMPORT_CONFIGS]),
+                                 
endpointJson[celix::rsa::Endpoint::EXPORTS].GetString(),
+                                 
parseJSONStringArray(endpointJson[celix::rsa::Endpoint::OBJECTCLASS]),
+                                 
endpointJson[celix::rsa::Endpoint::SCOPE].GetString(),
+                                 
endpointJson[celix::rsa::Endpoint::TOPIC].GetString()};
 
         _celixProperties = 
convertEndpointPropertiesToCelix(*_configuredProperties);
     }
diff --git a/bundles/async_remote_services/examples/HardcodedExampleProvider.cc 
b/bundles/async_remote_services/examples/HardcodedExampleProvider.cc
index f517ca1..4cbbc11 100644
--- a/bundles/async_remote_services/examples/HardcodedExampleProvider.cc
+++ b/bundles/async_remote_services/examples/HardcodedExampleProvider.cc
@@ -122,9 +122,9 @@ public:
         _subtractArgsSerializer.emplace(mng);
         _toStringSerializer.emplace(mng);
 
-        
mng->createComponent<HardcodedService>().addInterfaceWithName<IHardcodedService>(std::string{IHardcodedService::NAME},
 std::string{IHardcodedService::VERSION}, Properties{{"remote", "true"}, 
{ENDPOINT_IDENTIFIER, "id-01"}, {ENDPOINT_EXPORTS, 
"IHardcodedService"}}).build();
+        
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{{ENDPOINT_EXPORTS, "IHardcodedService"}}).build();
+                
.addInterface<celix::async_rsa::IExportedServiceFactory>("1.0.0", 
Properties{{celix::rsa::Endpoint::EXPORTS, "IHardcodedService"}}).build();
 
         _factory = &factory;
     }
diff --git 
a/bundles/async_remote_services/examples/HardcodedExampleSubscriber.cc 
b/bundles/async_remote_services/examples/HardcodedExampleSubscriber.cc
index c10f7b8..da96839 100644
--- a/bundles/async_remote_services/examples/HardcodedExampleSubscriber.cc
+++ b/bundles/async_remote_services/examples/HardcodedExampleSubscriber.cc
@@ -179,7 +179,7 @@ public:
         _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{{ENDPOINT_EXPORTS, "IHardcodedService"}}).build();
+            .addInterface<celix::async_rsa::IImportedServiceFactory>("1.0.0", 
Properties{{celix::rsa::Endpoint::EXPORTS, "IHardcodedService"}}).build();
         _factory = &factory;
 
         auto &usingCmp = mng->createComponent<UsingHardcodedServiceService>()
diff --git a/bundles/async_remote_services/rsa_spi/include/Endpoint.h 
b/bundles/async_remote_services/rsa_spi/include/Endpoint.h
deleted file mode 100644
index 76a9f47..0000000
--- a/bundles/async_remote_services/rsa_spi/include/Endpoint.h
+++ /dev/null
@@ -1,63 +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 <map>
-
-#include <celix/dm/Properties.h>
-
-constexpr const char* ENDPOINT_IDENTIFIER = "endpoint.id";
-constexpr const char* ENDPOINT_IMPORTED = "service.imported";
-constexpr const char* ENDPOINT_IMPORT_CONFIGS = "service.imported.configs";
-constexpr const char* ENDPOINT_EXPORTS = "service.exported.interfaces";
-constexpr const char* ENDPOINT_OBJECTCLASS = "endpoint.objectClass";
-constexpr const char* ENDPOINT_SCOPE = "endpoint.scope";
-constexpr const char* ENDPOINT_TOPIC = "endpoint.topic";
-
-namespace celix::rsa {
-
-/**
- * Endpoint class for celix::rsa namespace.
- * This class holds data for discovered remote services or published local 
services.
- */
-class Endpoint {
-public:
-
-    /**
-     * Endpoint constructor.
-     * @param properties celix properties with information about this endpoint 
and what its documenting.
-     */
-    explicit Endpoint(celix::dm::Properties properties) : 
_celixProperties{std::move(properties)} {
-        // TODO validate mandatory properties are set.
-    }
-
-    [[nodiscard]] const celix::dm::Properties& getProperties() const {
-        return _celixProperties;
-    }
-
-    [[nodiscard]] std::string getEndpointId() const {
-        return _celixProperties.get("endpoint.id");
-    }
-
-protected:
-    celix::dm::Properties _celixProperties;
-
-};
-} // end namespace celix::rsa.
diff --git a/libs/framework/include/celix/dm/types.h 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/Constants.h
similarity index 63%
copy from libs/framework/include/celix/dm/types.h
copy to bundles/async_remote_services/rsa_spi/include/celix/rsa/Constants.h
index c8fca93..2b5d0c4 100644
--- a/libs/framework/include/celix/dm/types.h
+++ b/bundles/async_remote_services/rsa_spi/include/celix/rsa/Constants.h
@@ -19,27 +19,13 @@
 
 #pragma once
 
-#include "celix/Utils.h"
 
-namespace celix { namespace dm {
-    //forward declarations
-//    class DependencyManager;
+namespace celix::rsa {
 
-    class BaseServiceDependency;
+    /**
+     * @brief Service property (named "remote") to mark a service as a remote 
service.
+     * Present means -> export service as a remote service.
+     */
+    constexpr const char *const REMOTE_SERVICE_PROPERTY_NAME = "remote";
 
-    class BaseProvidedService;
-
-    template<typename T, typename I>
-    class ProvidedService;
-
-    template<class T, typename I>
-    class CServiceDependency;
-
-    template<class T, class I>
-    class ServiceDependency;
-
-    template<typename T>
-    std::string typeName() {
-        return celix::typeName<T>();
-    }
-}}
+}
\ 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
new file mode 100644
index 0000000..97a81da
--- /dev/null
+++ b/bundles/async_remote_services/rsa_spi/include/celix/rsa/Endpoint.h
@@ -0,0 +1,68 @@
+/*
+ * 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 <map>
+
+#include <celix/dm/Properties.h>
+
+namespace celix::rsa {
+
+    /**
+     * @brief Endpoint class which represent a remote endpoint discovered by 
the framework.
+     */
+    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 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";
+
+
+        /**
+         * Endpoint constructor.
+         * @param properties celix properties with information about this 
endpoint and what its documenting.
+         */
+        explicit Endpoint(celix::Properties properties) : 
_celixProperties{std::move(properties)} {
+            // TODO validate mandatory properties are set.
+        }
+
+        [[nodiscard]] const celix::dm::Properties& getProperties() const {
+            return _celixProperties;
+        }
+
+        [[nodiscard]] std::string getEndpointId() const {
+            return _celixProperties.get(IDENTIFIER);
+        }
+
+        [[nodiscard]] std::string getExportedInterfaces() const {
+            return _celixProperties.get(EXPORTS);
+        }
+
+
+
+    protected:
+        celix::dm::Properties _celixProperties;
+
+    };
+} // end namespace celix::rsa.
diff --git 
a/bundles/async_remote_services/rsa_spi/include/celix/rsa/Exception.h 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/Exception.h
new file mode 100644
index 0000000..058c2eb
--- /dev/null
+++ b/bundles/async_remote_services/rsa_spi/include/celix/rsa/Exception.h
@@ -0,0 +1,21 @@
+#pragma once
+
+#include <exception>
+
+namespace celix::rsa {
+
+    /**
+     * @brief Celix Remote Service Admin Exception
+     */
+    class Exception : public std::exception {
+    public:
+        explicit Exception(std::string msg) : w{std::move(msg)} {}
+
+        const char* what() const noexcept override {
+            return w.c_str();
+        }
+    private:
+        const std::string w;
+    };
+
+}
\ No newline at end of file
diff --git a/bundles/async_remote_services/rsa_spi/include/EndpointAnnouncer.h 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/IEndpointAnnouncer.h
similarity index 70%
rename from bundles/async_remote_services/rsa_spi/include/EndpointAnnouncer.h
rename to 
bundles/async_remote_services/rsa_spi/include/celix/rsa/IEndpointAnnouncer.h
index deebd40..425a6e4 100644
--- a/bundles/async_remote_services/rsa_spi/include/EndpointAnnouncer.h
+++ 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/IEndpointAnnouncer.h
@@ -18,45 +18,34 @@
  */
 #pragma once
 
-#include <Endpoint.h>
-
 #include <memory>
 
-#include <celix/dm/Properties.h>
+#include "celix/rsa/Endpoint.h"
+#include "celix/dm/Properties.h"
 
 namespace celix::rsa {
 
 /**
- * Base class defining functions for all compatible endpoint announcer classes.
+ * @brief Interface used to announce or revoke endpoint to the remote service 
discovery network/system.
  */
-class EndpointAnnouncer {
+class IEndpointAnnouncer {
 public:
-
-    /**
-     * Defaulted constructor.
-     */
-    EndpointAnnouncer() = default;
-
     /**
      * Defaulted virtual destructor.
      */
-    virtual ~EndpointAnnouncer() = default;
+    virtual ~IEndpointAnnouncer() = default;
 
     /**
      * Task the endpoint announcer to make the given endpoint visible for 
discovery by other managers/ frameworks.
      * @param endpoint The endpoint pointer in question, with valid properties 
within.
      */
-    virtual void announceEndpoint([[maybe_unused]] std::unique_ptr<Endpoint> 
endpoint) {
-        // default implementation ignores this function.
-    }
+    virtual void announceEndpoint(std::unique_ptr<Endpoint> endpoint) = 0;
 
     /**
      * Task the endpoint announcer to remove the discoverability of a given 
endpoint.
      * @param endpoint The endpoint pointer in question, with valid properties 
within.
      */
-    virtual void revokeEndpoint([[maybe_unused]] std::unique_ptr<Endpoint> 
endpoint) {
-        // default implementation ignores this function.
-    }
+    virtual void revokeEndpoint(std::unique_ptr<Endpoint> endpoint) = 0;
 };
 
 } // end namespace celix::rsa.
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
new file mode 100644
index 0000000..f57a3a4
--- /dev/null
+++ 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/IExportServiceFactory.h
@@ -0,0 +1,65 @@
+/*
+ * 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 <memory>
+
+namespace celix::rsa {
+
+    /**
+     * @brief ExportService class which represent a (opaque) exported service.
+     * The lifetime of this object should be coupled with the lifetime of the 
exported service.
+     */
+    class ExportedService {
+    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;
+    };
+
+    /**
+     * @brief A export service factory for a specific service type.
+     *
+     * The service type which this export service factory targets is provided 
with
+     * the mandatory celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME 
service property.
+     *
+     */
+    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;
+
+        /**
+         * @brief Exports the service identified with svcId
+         * @param svcId The service id of the exported service.
+         * @return A ExportService.
+         * @throws celix::rsa::Exception if the export failed.
+         */
+        virtual std::unique_ptr<ExportedService> exportService(const 
celix::Properties& serviceProperties) = 0;
+    };
+}
\ No newline at end of file
diff --git a/libs/framework/include/celix/dm/types.h 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/IExportedService.h
similarity index 63%
copy from libs/framework/include/celix/dm/types.h
copy to 
bundles/async_remote_services/rsa_spi/include/celix/rsa/IExportedService.h
index c8fca93..50b3159 100644
--- a/libs/framework/include/celix/dm/types.h
+++ b/bundles/async_remote_services/rsa_spi/include/celix/rsa/IExportedService.h
@@ -16,30 +16,22 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-
 #pragma once
 
-#include "celix/Utils.h"
-
-namespace celix { namespace dm {
-    //forward declarations
-//    class DependencyManager;
-
-    class BaseServiceDependency;
-
-    class BaseProvidedService;
-
-    template<typename T, typename I>
-    class ProvidedService;
+#include "celix/rsa/Endpoint.h"
 
-    template<class T, typename I>
-    class CServiceDependency;
+namespace celix::rsa {
 
-    template<class T, class I>
-    class ServiceDependency;
+    /**
+     * @brief IExportedService represents an exported interface
+     */
+    class IExportedService {
+    public:
+        virtual ~IExportedService() noexcept = default;
 
-    template<typename T>
-    std::string typeName() {
-        return celix::typeName<T>();
-    }
-}}
+        /**
+         * @brief the endpoint which can be used to announce this exported 
service to the network.
+         */
+        virtual std::shared_ptr<celix::rsa::Endpoint> getEndpoint() = 0;
+    };
+}
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
new file mode 100644
index 0000000..3ef1f99
--- /dev/null
+++ 
b/bundles/async_remote_services/rsa_spi/include/celix/rsa/IImportServiceFactory.h
@@ -0,0 +1,65 @@
+/*
+ * 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 <memory>
+
+namespace celix::rsa {
+
+    /**
+     * @brief ImportService class which represent a (opaque) imported service.
+     * The lifetime of this object should be coupled with the lifetime of the 
imported service.
+     */
+    class ImportedService {
+    public:
+        virtual ~ImportedService() noexcept = default;
+
+        /**
+         * @brief returns the endpoint used for this imported service.
+         */
+        virtual const celix::rsa::Endpoint& getEndpoint() const = 0;
+    };
+
+    /**
+     * @brief A import service factory for a specific service type.
+     *
+     * The service type which this import service factory targets is provided 
with
+     * the mandatory celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME 
service property.
+     *
+     */
+    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;
+
+        /**
+         * @brief Imports the service identified with svcId
+         * @param svcId The service id of the exported service.
+         * @return A ImportService.
+         * @throws celix::rsa::Exception if the import failed.
+         */
+        virtual std::unique_ptr<ImportedService> 
importService(celix::rsa::Endpoint& endpoint) = 0;
+    };
+}
\ No newline at end of file
diff --git 
a/bundles/async_remote_services/topology_manager/include/topology_manager.h 
b/bundles/async_remote_services/topology_manager/include/topology_manager.h
index fff53db..710cbdb 100644
--- a/bundles/async_remote_services/topology_manager/include/topology_manager.h
+++ b/bundles/async_remote_services/topology_manager/include/topology_manager.h
@@ -17,7 +17,7 @@
  * under the License.
  */
 
-#include <EndpointAnnouncer.h>
+#include "celix/rsa/IEndpointAnnouncer.h"
 #include <IExportedService.h>
 #include <celix_api.h>
 #include <mutex>
@@ -46,7 +46,7 @@ namespace celix::async_rsa {
             void addExportedService(celix::async_rsa::IExportedService 
*endpoint, Properties&& properties);
             void removeExportedService(celix::async_rsa::IExportedService 
*endpoint, Properties&& properties);
 
-            void setDiscovery(celix::rsa::EndpointAnnouncer *discovery);
+            void setDiscovery(celix::rsa::IEndpointAnnouncer *discovery);
 
         private:
             celix_log_helper_t *_logger;
@@ -58,6 +58,6 @@ namespace celix::async_rsa {
 #else
             std::unordered_map<std::string, 
celix::async_rsa::IExportedService*> _exportedServices{};
 #endif
-            celix::rsa::EndpointAnnouncer *_discovery{};
+            celix::rsa::IEndpointAnnouncer *_discovery{};
         };
 }
\ No newline at end of file
diff --git 
a/bundles/async_remote_services/topology_manager/src/topology_manager.cc 
b/bundles/async_remote_services/topology_manager/src/topology_manager.cc
index c8e031d..5ca4ef4 100644
--- a/bundles/async_remote_services/topology_manager/src/topology_manager.cc
+++ b/bundles/async_remote_services/topology_manager/src/topology_manager.cc
@@ -39,7 +39,7 @@ 
celix::async_rsa::AsyncTopologyManager::~AsyncTopologyManager() {
 }
 
 void 
celix::async_rsa::AsyncTopologyManager::addExportedService(celix::async_rsa::IExportedService
 *exportedService, Properties &&properties) {
-    auto interface = properties.get(ENDPOINT_EXPORTS);
+    auto interface = properties.get(celix::rsa::Endpoint::EXPORTS);
 
     if(interface.empty()) {
         L_DEBUG("Adding exported service but no exported interfaces");
@@ -66,7 +66,7 @@ void 
celix::async_rsa::AsyncTopologyManager::addExportedService(celix::async_rsa
 }
 
 void 
celix::async_rsa::AsyncTopologyManager::removeExportedService([[maybe_unused]] 
celix::async_rsa::IExportedService *exportedService, Properties &&properties) {
-    auto interface = properties.get(ENDPOINT_EXPORTS);
+    auto interface = properties.get(celix::rsa::Endpoint::EXPORTS);
 
     if(interface.empty()) {
         L_WARN("Removing exported service but missing exported interfaces");
@@ -85,7 +85,7 @@ void 
celix::async_rsa::AsyncTopologyManager::removeExportedService([[maybe_unuse
     }
 }
 
-void 
celix::async_rsa::AsyncTopologyManager::setDiscovery(celix::rsa::EndpointAnnouncer
 *discovery) {
+void 
celix::async_rsa::AsyncTopologyManager::setDiscovery(celix::rsa::IEndpointAnnouncer
 *discovery) {
     std::unique_lock l(_m);
     _discovery = discovery;
 }
@@ -99,7 +99,7 @@ public:
                 
.setCallbacks(&celix::async_rsa::AsyncTopologyManager::addExportedService, 
&celix::async_rsa::AsyncTopologyManager::removeExportedService)
                 .build();
 
-        _cmp.createServiceDependency<celix::rsa::EndpointAnnouncer>()
+        _cmp.createServiceDependency<celix::rsa::IEndpointAnnouncer>()
                 .setRequired(true)
                 
.setCallbacks(&celix::async_rsa::AsyncTopologyManager::setDiscovery)
                 .build();
diff --git a/libs/framework/include/celix/dm/types.h 
b/libs/framework/include/celix/dm/types.h
index c8fca93..16c1de0 100644
--- a/libs/framework/include/celix/dm/types.h
+++ b/libs/framework/include/celix/dm/types.h
@@ -32,12 +32,12 @@ namespace celix { namespace dm {
     template<typename T, typename I>
     class ProvidedService;
 
-    template<class T, typename I>
-    class CServiceDependency;
-
     template<class T, class I>
     class ServiceDependency;
 
+    template<class T, typename I>
+    class CServiceDependency;
+
     template<typename T>
     std::string typeName() {
         return celix::typeName<T>();

Reply via email to