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

[celix] 01/02: CELIX-370: Initial commit for CompnentManager (DM) for C++ Celix

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

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

commit 2d6327e6918723bfd082830b6ddcc5fa2cd60798
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Jun 16 12:50:27 2019 +0200

    CELIX-370: Initial commit for CompnentManager (DM) for C++ Celix
---
 .../topology_manager/CMakeLists.txt                |   2 +-
 libs/framework_cxx/CMakeLists.txt                  |   1 +
 libs/framework_cxx/gtest/CMakeLists.txt            |   1 +
 .../gtest/src/ComponentManager_tests.cc            |  61 +++++
 .../framework_cxx/include/celix/ComponentManager.h | 288 +++++++++++++++++++++
 libs/framework_cxx/include/celix/Framework.h       |   2 +-
 libs/framework_cxx/src/ComponentManager.cc         | 102 ++++++++
 libs/framework_cxx/src/Framework.cc                |   6 +-
 libs/registry/include/celix/Properties.h           |  54 ++--
 libs/registry/src/ServiceRegistry.cc               |   2 +-
 10 files changed, 496 insertions(+), 23 deletions(-)

diff --git a/bundles/remote_services/topology_manager/CMakeLists.txt b/bundles/remote_services/topology_manager/CMakeLists.txt
index 9ee218f..211a31e 100644
--- a/bundles/remote_services/topology_manager/CMakeLists.txt
+++ b/bundles/remote_services/topology_manager/CMakeLists.txt
@@ -41,7 +41,7 @@ if (RSA_TOPOLOGY_MANAGER)
         include_directories(${CPPUTEST_INCLUDE_DIR})
         include_directories(${CPPUTEST_EXT_INCLUDE_DIR})
         add_subdirectory(tms_tst)
-   endif (ENABLE_TESTING)
+   endif ()
 
     install_celix_bundle(rsa_topology_manager EXPORT celix COMPONENT rsa)
     #Setup target aliases to match external usage
diff --git a/libs/framework_cxx/CMakeLists.txt b/libs/framework_cxx/CMakeLists.txt
index c4604ac..f5c3164 100644
--- a/libs/framework_cxx/CMakeLists.txt
+++ b/libs/framework_cxx/CMakeLists.txt
@@ -27,6 +27,7 @@ add_library(celix_framework_cxx SHARED
         src/Framework.cc
         src/BundleContext.cc
         src/Bundle.cc
+        src/ComponentManager.cc
 )
 target_include_directories(celix_framework_cxx PRIVATE src)
 target_include_directories(celix_framework_cxx PUBLIC include)
diff --git a/libs/framework_cxx/gtest/CMakeLists.txt b/libs/framework_cxx/gtest/CMakeLists.txt
index 4e76ed2..e12c856 100644
--- a/libs/framework_cxx/gtest/CMakeLists.txt
+++ b/libs/framework_cxx/gtest/CMakeLists.txt
@@ -18,6 +18,7 @@
 set(SOURCES
         src/main.cc
         src/Framework_tests.cc
+        src/ComponentManager_tests.cc
 )
 add_executable(celix_framework_cxx_tests ${SOURCES})
 target_link_libraries(celix_framework_cxx_tests PRIVATE gtest celix_framework_cxx glog::glog)
diff --git a/libs/framework_cxx/gtest/src/ComponentManager_tests.cc b/libs/framework_cxx/gtest/src/ComponentManager_tests.cc
new file mode 100644
index 0000000..f9a42ad
--- /dev/null
+++ b/libs/framework_cxx/gtest/src/ComponentManager_tests.cc
@@ -0,0 +1,61 @@
+/**
+ *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 <atomic>
+
+#include "gtest/gtest.h"
+
+#include "celix/Framework.h"
+#include "celix/ComponentManager.h"
+
+class ComponentManagerTest : public ::testing::Test {
+public:
+    celix::Framework& framework() { return fw; }
+private:
+    celix::Framework fw{};
+};
+
+
+TEST_F(ComponentManagerTest, CreateDestroy) {
+    auto ctx = framework().context();
+
+    class Cmp {};
+
+    celix::ComponentManager<Cmp> cmpMng{ctx, std::make_shared<Cmp>()};
+    EXPECT_FALSE(cmpMng.isEnabled());
+    EXPECT_TRUE(cmpMng.isResolved()); //no deps -> resolved
+    EXPECT_EQ(cmpMng.getState(), celix::ComponentState::Disabled);
+
+    cmpMng.enable();
+    EXPECT_TRUE(cmpMng.isEnabled());
+}
+
+TEST_F(ComponentManagerTest, AddSvcDep) {
+    auto ctx = framework().context();
+
+    class Cmp {};
+    class ISvc {};
+
+    celix::ComponentManager<Cmp> cmpMng{ctx, std::make_shared<Cmp>()};
+    cmpMng.addServiceDependency(); //TODO
+    cmpMng.enable();
+    EXPECT_TRUE(cmpMng.isEnabled());
+
+
+}
\ No newline at end of file
diff --git a/libs/framework_cxx/include/celix/ComponentManager.h b/libs/framework_cxx/include/celix/ComponentManager.h
new file mode 100644
index 0000000..431b784
--- /dev/null
+++ b/libs/framework_cxx/include/celix/ComponentManager.h
@@ -0,0 +1,288 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_COMPONENT_MANAGER_H
+#define CXX_CELIX_COMPONENT_MANAGER_H
+
+#include <memory>
+#include <unordered_map>
+
+#include "celix/BundleContext.h"
+
+namespace celix {
+
+    enum class ComponentState {
+        Disabled,
+        Uninitialized,
+        Initialized,
+        Started
+    };
+
+    template<typename T, typename I>
+    class ServiceDependency; //forward declaration
+    class GenericServiceDependency; //forward declaration
+
+    class GenericComponentManager {
+    public:
+        virtual ~GenericComponentManager() = default;
+
+        ComponentState getState() const;
+        bool isEnabled() const;
+        bool isResolved() const;
+
+        //TODO make friend of SvcDep
+        void updateState();
+    protected:
+        GenericComponentManager(std::shared_ptr<BundleContext> _ctx, std::shared_ptr<void> cmpInstance) : ctx{std::move(_ctx)}, instance{std::move(cmpInstance)} {};
+
+        void removeServiceDependency(long serviceDependencyId);
+        void setEnabled(bool enable);
+
+
+        /**** Fields ****/
+        mutable std::mutex mutex{}; //protects below
+        ComponentState state = ComponentState::Disabled;
+        bool enabled = false;
+        std::function<void()> init{};
+        std::function<void()> start{};
+        std::function<void()> stop{};
+        std::function<void()> deinit{};
+
+        std::shared_ptr<BundleContext> ctx;
+        std::shared_ptr<void> instance;
+
+        long nextServiceDependencyId = 1L;
+        std::unordered_map<long,GenericServiceDependency> serviceDependencies{};
+    };
+
+    template<typename T>
+    class ComponentManager : public GenericComponentManager {
+    public:
+        using ComponentType = T;
+
+        ComponentManager(std::shared_ptr<BundleContext> ctx, std::shared_ptr<T> cmpInstance);
+        ~ComponentManager() override = default;
+
+        ComponentManager<T>& enable();
+        ComponentManager<T>& disable();
+
+        ComponentManager<T>& setCallbacks(
+                void (T::*init)(),
+                void (T::*start)(),
+                void (T::*stop)(),
+                void (T::*deinit)());
+
+//        template<typename I>
+//        ServiceDependency<T,I>& addServiceDependency();
+//
+//        template<typename F>
+//        ServiceDependency<T,F>& addFunctionServiceDependency(const std::string &functionName);
+
+    };
+
+    enum class Cardinality {
+        One,
+        Many
+    };
+
+    class GenericServiceDependency {
+    public:
+        virtual ~GenericServiceDependency() = default;
+
+        bool isResolved() const;
+        Cardinality getCardinality() const;
+        bool getRequired() const;
+        const std::string& getFilter() const;
+
+    protected:
+        GenericServiceDependency(std::shared_ptr<BundleContext> ctx);
+
+        //Fields
+        mutable std::mutex mutex{}; //protects below
+        bool required = false;
+        std::string filter{};
+        Cardinality cardinality = Cardinality::One;
+        std::vector<ServiceTracker> tracker{}; //max 1
+
+        std::shared_ptr<BundleContext> ctx;
+    };
+
+    template<typename T, typename I>
+    class ServiceDependency : public GenericServiceDependency {
+    public:
+        using ComponentType = T;
+        using ServiceType = I;
+
+        ServiceDependency(std::shared_ptr<ComponentManager<T>> mng);
+        ~ServiceDependency() override = default;
+
+        ServiceDependency<T,I>& setFilter(const std::string &filter);
+        ServiceDependency<T,I>& setRequired(bool required);
+        ServiceDependency<T,I>& setCardinality(celix::Cardinality cardinality);
+        ServiceDependency<T,I>& setCallbacks(void (T::*set)(std::shared_ptr<I>));
+        ServiceDependency<T,I>& setCallbacks(void (T::*add)(std::shared_ptr<I>), void (T::*remove)(std::shared_ptr<I>));
+        //TODO update callback
+
+        void enable();
+        void disable();
+        bool isResolved();
+    private:
+        std::function<void(std::shared_ptr<I>)> set{};
+        std::function<void(std::shared_ptr<I>)> add{};
+        std::function<void(std::shared_ptr<I>)> rem{};
+        std::shared_ptr<ComponentManager<T>> mng;
+    };
+}
+
+
+
+/**************************** IMPLEMENTATION *************************************************************************/
+
+template<typename T>
+celix::ComponentManager<T>::ComponentManager(std::shared_ptr<BundleContext> ctx, std::shared_ptr<T> cmpInstance) :
+    GenericComponentManager(ctx, std::static_pointer_cast<void>(cmpInstance)) {}
+
+template<typename T>
+celix::ComponentManager<T>& celix::ComponentManager<T>::enable() {
+    this->setEnabled(true);
+    return *this;
+}
+
+template<typename T>
+celix::ComponentManager<T>& celix::ComponentManager<T>::disable() {
+    this->setEnabled(false);
+    return *this;
+}
+
+template<typename T>
+celix::ComponentManager<T>& celix::ComponentManager<T>::setCallbacks(
+        void (T::*init)(),
+        void (T::*start)(),
+        void (T::*stop)(),
+        void (T::*deinit)()) {
+    std::lock_guard<std::mutex> lck{mutex};
+    auto initFunc = [this,init]() {
+        if (init) {
+            (this->instance->*init)();
+        }
+    };
+    auto startFunc = [this,start]() {
+        if (start) {
+            (this->instance->*start)();
+        }
+    };
+    auto stopFunc = [this,stop]() {
+        if (stop) {
+            (this->instance->*stop)();
+        }
+    };
+    auto deinitFunc = [this,deinit]() {
+        if (deinit) {
+            (this->instance->*deinit)();
+        }
+    };
+
+}
+
+template<typename T, typename I>
+celix::ServiceDependency<T,I>::ServiceDependency(std::shared_ptr<ComponentManager<T>> _mng) : mng{std::move(_mng)} {
+    add = [this](std::shared_ptr<I>) {
+        mng->updateState();
+    };
+    rem = [this](std::shared_ptr<I>) {
+        mng->updateState();
+    };
+}
+
+template<typename T, typename I>
+void celix::ServiceDependency<T,I>::enable() {
+    std::vector<celix::ServiceTracker> localTrackers{};
+    {
+        std::lock_guard<std::mutex> lck{mutex};
+        std::swap(localTrackers, tracker);
+        assert(tracker.size() == 0);
+
+        ServiceTrackerOptions<I> opts{};
+        opts.filter = this->filter;
+        opts.set = set;
+        opts.add = add;
+        opts.remove = rem;
+
+        this->tracker.push_back(this->ctx->trackServices(opts));
+    }
+
+}
+
+template<typename T, typename I>
+void celix::ServiceDependency<T,I>::disable() {
+    std::vector<celix::ServiceTracker> localTrackers{};
+    {
+        std::lock_guard<std::mutex> lck{mutex};
+        std::swap(localTrackers, tracker);
+        assert(tracker.size() == 0);
+    }
+}
+
+
+template<typename T, typename I>
+celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::setCallbacks(void (T::*setfp)(std::shared_ptr<I>)) {
+    std::lock_guard<std::mutex> lck{mutex};
+    set = [this, setfp](std::shared_ptr<I> svc) {
+        (mng->instance->*setfp)(svc);
+    };
+    return *this;
+}
+
+template<typename T, typename I>
+celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::setCallbacks(void (T::*addfp)(std::shared_ptr<I>), void (T::*remfp)(std::shared_ptr<I>)) {
+    std::lock_guard<std::mutex> lck{mutex};
+    add = [this, addfp](std::shared_ptr<I> svc) {
+        (mng->instance->*addfp)(svc);
+        mng->updateState();
+    };
+    rem = [this, remfp](std::shared_ptr<I> svc) {
+        (mng->instance->*remfp)(svc);
+        mng->updateState();
+    };
+    return *this;
+}
+
+template<typename T, typename I>
+celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::setFilter(const std::string &f) {
+    std::lock_guard<std::mutex> lck{mutex};
+    filter = f;
+    return *this;
+}
+
+template<typename T, typename I>
+celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::setRequired(bool r) {
+    std::lock_guard<std::mutex> lck{mutex};
+    required = r;
+    return *this;
+}
+
+template<typename T, typename I>
+celix::ServiceDependency<T,I>& celix::ServiceDependency<T,I>::setCardinality(celix::Cardinality c) {
+    std::lock_guard<std::mutex> lck{mutex};
+    cardinality = c;
+    return *this;
+}
+
+
+#endif //CXX_CELIX_PROPERTIES_H
diff --git a/libs/framework_cxx/include/celix/Framework.h b/libs/framework_cxx/include/celix/Framework.h
index 8689be7..8e7fdd7 100644
--- a/libs/framework_cxx/include/celix/Framework.h
+++ b/libs/framework_cxx/include/celix/Framework.h
@@ -88,7 +88,7 @@ namespace celix {
         std::string cacheDir() const;
         std::string uuid() const;
 
-        celix::BundleContext& context() const;
+        std::shared_ptr<celix::BundleContext> context() const;
 
         //TODO trackBundles
 
diff --git a/libs/framework_cxx/src/ComponentManager.cc b/libs/framework_cxx/src/ComponentManager.cc
new file mode 100644
index 0000000..b3b4205
--- /dev/null
+++ b/libs/framework_cxx/src/ComponentManager.cc
@@ -0,0 +1,102 @@
+/**
+ *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 <iostream>
+
+#include "celix/ComponentManager.h"
+
+celix::GenericServiceDependency::GenericServiceDependency(std::shared_ptr<celix::BundleContext> _ctx) : ctx{_ctx} {}
+
+
+bool celix::GenericServiceDependency::isResolved() const {
+    std::lock_guard<std::mutex> lck{mutex};
+    if (!tracker.empty()) {
+        return tracker[0].trackCount() >= 1;
+    } else {
+        return false;
+    }
+}
+
+celix::Cardinality celix::GenericServiceDependency::getCardinality() const {
+    std::lock_guard<std::mutex> lck{mutex};
+    return cardinality;
+}
+
+bool celix::GenericServiceDependency::getRequired() const {
+    std::lock_guard<std::mutex> lck{mutex};
+    return required;
+}
+
+const std::string &celix::GenericServiceDependency::getFilter() const {
+    std::lock_guard<std::mutex> lck{mutex};
+    return filter;
+}
+
+celix::ComponentState celix::GenericComponentManager::getState() const {
+    std::lock_guard<std::mutex> lck{mutex};
+    return state;
+}
+
+bool celix::GenericComponentManager::isEnabled() const  {
+    std::lock_guard<std::mutex> lck{mutex};
+    //TODO update state
+    return enabled;
+}
+
+bool celix::GenericComponentManager::isResolved() const {
+    std::lock_guard<std::mutex> lck{mutex};
+//    for (auto &pair : serviceDependencies) {
+//        if (!pair->second.isResolved()) {
+//            return false;
+//        }
+//    }
+    return true;
+}
+
+void celix::GenericComponentManager::removeServiceDependency(long serviceDependencyId) {
+    std::lock_guard<std::mutex> lck{mutex};
+    serviceDependencies.erase(serviceDependencyId);
+}
+
+void celix::GenericComponentManager::setEnabled(bool e) {
+    std::lock_guard<std::mutex> lck{mutex};
+    enabled = e;
+}
+
+void celix::GenericComponentManager::updateState() {
+    std::lock_guard<std::mutex> lck{mutex};
+
+    //TODO state thing
+
+    //TODO check enabled.
+
+    bool allDependenciesResolved = true;
+    for (auto &pair : serviceDependencies) {
+        if (!pair.second.isResolved()) {
+            allDependenciesResolved = false;
+            break;
+        }
+    }
+
+    std::cout << "resolved? " << (allDependenciesResolved ? "true" : "false") << std::endl;
+}
+
+
+
diff --git a/libs/framework_cxx/src/Framework.cc b/libs/framework_cxx/src/Framework.cc
index 9128c0e..c5eb0ac 100644
--- a/libs/framework_cxx/src/Framework.cc
+++ b/libs/framework_cxx/src/Framework.cc
@@ -301,9 +301,9 @@ public:
         return fwUUID;
     }
 
-    celix::BundleContext& frameworkContext() const {
+    std::shared_ptr<celix::BundleContext> frameworkContext() const {
         std::lock_guard<std::mutex> lck(bundles.mutex);
-        return *bundles.entries.at(celix::FRAMEWORK_BUNDLE_ID)->context();
+        return bundles.entries.at(celix::FRAMEWORK_BUNDLE_ID)->context();
     }
 
     bool startFramework() {
@@ -447,7 +447,7 @@ std::string celix::Framework::uuid() const {
     return pimpl->uuid();
 }
 
-celix::BundleContext& celix::Framework::context() const {
+std::shared_ptr<celix::BundleContext> celix::Framework::context() const {
     return pimpl->frameworkContext();
 }
 
diff --git a/libs/registry/include/celix/Properties.h b/libs/registry/include/celix/Properties.h
index 649cf4c..0588f3f 100644
--- a/libs/registry/include/celix/Properties.h
+++ b/libs/registry/include/celix/Properties.h
@@ -29,33 +29,53 @@ namespace celix {
 
     inline const std::string& getProperty(const Properties& props, const std::string &key, const std::string &defaultValue) noexcept {
         auto it = props.find(key);
-        if (it != props.end()) {
-            return props.at(key);
-        } else {
-            return defaultValue;
-        }
+        return it != props.end() ? it->second : defaultValue;
     }
 
-    inline int getProperty(const Properties& props, const std::string &key, int defaultValue)  noexcept {
-        std::string val = getProperty(props, key, std::to_string(defaultValue));
-        return std::stoi(val, nullptr, 10);
+    inline long getPropertyAsLong(const Properties& props, const std::string &key, long defaultValue) noexcept {
+        const std::string &strVal = getProperty(props, key, std::to_string(defaultValue));
+        char *endptr[1];
+        long lval = strtol(strVal.c_str(), endptr, 10);
+        return strVal.c_str() == *endptr ? defaultValue : lval;
     }
 
-    inline unsigned int getProperty(const Properties& props, const std::string &key, unsigned int defaultValue) noexcept {
-        std::string val = getProperty(props, key, std::to_string(defaultValue));
-        return static_cast<unsigned  int>(std::stoul(val, nullptr, 10)); //NOTE no std::stou ??
+    inline unsigned long getPropertyAsUnsignedLong(const Properties& props, const std::string &key, unsigned long defaultValue) noexcept {
+        const std::string &strVal = getProperty(props, key, std::to_string(defaultValue));
+        char *endptr[1];
+        unsigned long lval = strtoul(strVal.c_str(), endptr, 10);
+        return strVal.c_str() == *endptr ? defaultValue : lval;
     }
 
-    inline long getProperty(const Properties& props, const std::string &key, long defaultValue) noexcept {
-        std::string val = getProperty(props, key, std::to_string(defaultValue));
-        return std::stol(val, nullptr, 10);
+    inline int getPropertyAsInt(const Properties& props, const std::string &key, int defaultValue) noexcept {
+        long def = defaultValue;
+        long r = getPropertyAsLong(props, key, def);
+        return (int)r;
     }
 
-    inline unsigned int getProperty(const Properties& props, const std::string &key, unsigned long defaultValue) noexcept {
-        std::string val = getProperty(props, key, std::to_string(defaultValue));
-        return std::stoul(val, nullptr, 10);
+    inline unsigned int getPropertyAsUnsignedInt(const Properties& props, const std::string &key, unsigned int defaultValue) noexcept {
+        unsigned long def = defaultValue;
+        unsigned long r = getPropertyAsUnsignedLong(props, key, def);
+        return (unsigned int)r;
     }
 
+    inline bool getPropertyAsBool(const Properties& props, const std::string &key, bool defaultValue) noexcept {
+        const std::string &strVal = getProperty(props, key, std::to_string(defaultValue));
+        return strVal == "true" || strVal == "TRUE";
+    }
+
+    inline double getPropertyAsDouble(const Properties& props, const std::string &key, double defaultValue) noexcept {
+        const std::string &strVal = getProperty(props, key, std::to_string(defaultValue));
+        char *endptr[1];
+        double dval = strtod(strVal.c_str(), endptr);
+        return strVal.c_str() == *endptr ? defaultValue : dval;
+    }
+
+    inline float getPropertyAsFloat(const Properties& props, const std::string &key, float defaultValue) noexcept {
+        const std::string &strVal = getProperty(props, key, std::to_string(defaultValue));
+        char *endptr[1];
+        float fval = strtof(strVal.c_str(), endptr);
+        return strVal.c_str() == *endptr ? defaultValue : fval;
+    }
 
     celix::Properties loadProperties(const std::string &path);
     celix::Properties loadProperties(std::istream &stream);
diff --git a/libs/registry/src/ServiceRegistry.cc b/libs/registry/src/ServiceRegistry.cc
index 33b2bb6..a8cf2f5 100644
--- a/libs/registry/src/ServiceRegistry.cc
+++ b/libs/registry/src/ServiceRegistry.cc
@@ -67,7 +67,7 @@ namespace {
                  celix::Properties &&_props) :
                 owner{std::move(_owner)}, svcId{_svcId}, svcName{std::move(_svcName)},
                 props{std::forward<celix::Properties>(_props)},
-                ranking{celix::getProperty(props, celix::SERVICE_RANKING, 0L)},
+                ranking{celix::getPropertyAsLong(props, celix::SERVICE_RANKING, 0L)},
                 svc{_svc}, svcFactory{_svcFac} {}
 
         SvcEntry(SvcEntry &&rhs) = delete;