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

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


The following commit(s) were added to 
refs/heads/feature/pubsub_custom_serializers by this push:
     new 92b5457  Refactoring of the message serialization provider/handler and 
adds a message serialization provider for avrobin
92b5457 is described below

commit 92b5457079cec81ff27a3e59ec96a3e3cd7916f9
Author: Pepijn Noltes <[email protected]>
AuthorDate: Thu Apr 16 18:51:35 2020 +0200

    Refactoring of the message serialization provider/handler and adds a 
message serialization provider for avrobin
---
 CMakeLists.txt                                     |   4 +
 .../log_service/loghelper_include/log_helper.h     |  12 ++-
 bundles/logging/log_service/src/log_helper.c       |  77 ++++++--------
 .../pubsub_serializer_avrobin/CMakeLists.txt       |   9 +-
 .../gtest/CMakeLists.txt                           |  22 ++--
 .../gtest/msg_descriptors/garbage.descriptor       |   1 +
 .../gtest/msg_descriptors/msg_poi1.descriptor      |   2 +-
 .../msg_descriptors/msg_poi1_invalid1.descriptor   |   4 +-
 .../msg_descriptors/msg_poi1_invalid2.descriptor}  |   5 +-
 .../msg_descriptors/msg_poi1_invalid3.descriptor   |   4 +-
 .../msg_descriptors/msg_poi1_invalid4.descriptor}  |   5 +-
 .../gtest/msg_descriptors/msg_poi2.descriptor      |   2 +-
 .../gtest/msg_descriptors/msg_poiCmd.descriptor    |   2 +-
 ...PubSubAvrobinSerializationProviderTestSuite.cc} |  94 ++++++++---------
 .../src/ps_avrobin_serializer_activator.c          |   4 +
 .../src/pubsub_avrobin_serialization_provider.c    | 117 +++++++++++++++++++++
 .../src/pubsub_avrobin_serialization_provider.h    |  40 +++++++
 .../pubsub/pubsub_serializer_json/CMakeLists.txt   |   2 +-
 .../pubsub_serializer_json/gtest/CMakeLists.txt    |  10 +-
 .../gtest/msg_descriptors/msg_poi1.descriptor      |   2 +-
 .../msg_descriptors/msg_poi1_invalid1.descriptor   |   4 +-
 .../msg_descriptors/msg_poi1_invalid2.descriptor   |  12 ++-
 .../msg_descriptors/msg_poi1_invalid3.descriptor   |   4 +-
 .../msg_descriptors/msg_poi1_invalid4.descriptor   |   8 +-
 .../gtest/msg_descriptors/msg_poi2.descriptor      |   2 +-
 .../gtest/msg_descriptors/msg_poiCmd.descriptor    |   2 +-
 .../PubSubJsonSerializationProviderTestSuite.cc    |  10 +-
 .../src/ps_json_serializer_activator.c             |   2 +-
 .../src/pubsub_avrobin_serialization_provider.c    | 116 ++++++++++++++++++++
 .../src/pubsub_json_serialization_provider.h       |  38 +------
 bundles/pubsub/pubsub_utils/CMakeLists.txt         |   3 +-
 bundles/pubsub/pubsub_utils/gtest/CMakeLists.txt   |  18 +++-
 .../gtest/msg_descriptors/garbage.descriptor       |   1 +
 .../gtest/msg_descriptors/msg_poi1.descriptor      |   2 +-
 .../msg_descriptors/msg_poi1_invalid1.descriptor   |   4 +-
 .../msg_descriptors/msg_poi1_invalid2.descriptor}  |   5 +-
 .../msg_descriptors/msg_poi1_invalid3.descriptor   |   4 +-
 .../msg_descriptors/msg_poi1_invalid4.descriptor}  |   5 +-
 .../gtest/msg_descriptors/msg_poi2.descriptor      |   2 +-
 .../gtest/msg_descriptors/msg_poiCmd.descriptor    |   2 +-
 ...e.cc => PubSubSerializationHandlerTestSuite.cc} |  40 +++----
 .../src/PubSubSerializationProviderTestSuite.cc    |  75 +++++++++++++
 .../include/pubsub_serialization_provider.h        | 107 +++++++++++++++++++
 .../include/pubsub_serializer_handler.h            |   9 +-
 .../pubsub_utils/src/pubsub_serializer_handler.c   |   1 +
 libs/framework/src/framework.c                     |   1 +
 46 files changed, 680 insertions(+), 215 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 665eb92..93f7b52 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -44,6 +44,10 @@ ELSE ()
     set(CMAKE_CXX_FLAGS "-Wall -Wextra -Weffc++ ${CMAKE_CXX_FLAGS}")
     set(CMAKE_C_FLAGS_DEBUG "-g -DDEBUG ${CMAKE_C_FLAGS}")
     set(CMAKE_CXX_FLAGS_DEBUG "-g -DDEBUG ${CMAKE_CXX_FLAGS}")
+
+    #prevent the linker from optimizing out linked libraries. libraries linked 
against executable are maybe not used
+    #by the executable, but could be used by the (dynamically) loaded 
libraries.
+    set(CMAKE_EXE_LINKER_FLAGS  "${CMAKE_EXE_LINKER_FLAGS} -Wl,--no-as-needed")
 ENDIF()
 
 IF(APPLE)
diff --git a/bundles/logging/log_service/loghelper_include/log_helper.h 
b/bundles/logging/log_service/loghelper_include/log_helper.h
index 6787701..e84071c 100644
--- a/bundles/logging/log_service/loghelper_include/log_helper.h
+++ b/bundles/logging/log_service/loghelper_include/log_helper.h
@@ -31,11 +31,19 @@ typedef struct log_helper log_helper_t;
 
 log_helper_t*  logHelper_createWithName(celix_bundle_context_t* context, const 
char *name);
 celix_status_t logHelper_create(celix_bundle_context_t *context, log_helper_t 
**log_helper);
-celix_status_t logHelper_start(log_helper_t *loghelper);
-celix_status_t logHelper_stop(log_helper_t *loghelper);
 celix_status_t logHelper_destroy(log_helper_t **loghelper);
 celix_status_t logHelper_log(log_helper_t *loghelper, log_level_t level, const 
char* message, ... );
 
+/**
+ * deprecated. log helper is already start in create
+ */
+celix_status_t logHelper_start(log_helper_t *loghelper);
+
+/**
+ * deprecated. log helper is already stopped in destroy
+ */
+celix_status_t logHelper_stop(log_helper_t *loghelper);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/bundles/logging/log_service/src/log_helper.c 
b/bundles/logging/log_service/src/log_helper.c
index c051f9e..d4fb832 100644
--- a/bundles/logging/log_service/src/log_helper.c
+++ b/bundles/logging/log_service/src/log_helper.c
@@ -75,22 +75,35 @@ static char* logHelper_backtrace(void) {
 struct log_helper {
        celix_bundle_context_t *bundleContext;
        char *name;
-       celix_service_tracker_t *logServiceTracker;
-       celix_thread_mutex_t logListLock;
+       long logServiceTrackerId;
+
+    celix_thread_mutex_t logListLock;
        array_list_pt logServices;
        bool stdOutFallback;
        bool stdOutFallbackIncludeDebug;
 };
 
-static celix_status_t logHelper_logServiceAdded(void *handle, 
service_reference_pt reference, void *service);
-static celix_status_t logHelper_logServiceRemoved(void *handle, 
service_reference_pt reference, void *service);
+static void logHelper_logServiceAdded(void *handle, void *service);
+static void logHelper_logServiceRemoved(void *handle, void *service);
+
+celix_status_t logHelper_start(log_helper_t *loghelper  
__attribute__((unused)))
+{
+    //NOP, done in create
+    return CELIX_SUCCESS;
+}
+
+celix_status_t logHelper_stop(log_helper_t *loghelper __attribute__((unused)))
+{
+    //NOP, done in stop
+    return CELIX_SUCCESS;
+}
 
 log_helper_t* logHelper_createWithName(celix_bundle_context_t* context, const 
char *name) {
        log_helper_t* logHelper = calloc(1, sizeof(*logHelper));
 
     logHelper->bundleContext = context;
     logHelper->name = celix_utils_strdup(name);
-    logHelper->logServiceTracker = NULL;
+    logHelper->logServiceTrackerId = -1L;
     logHelper->stdOutFallback = false;
 
     logHelper->stdOutFallback = celix_bundleContext_getPropertyAsBool(context, 
LOGHELPER_ENABLE_STDOUT_FALLBACK_NAME, 
LOGHELPER_ENABLE_STDOUT_FALLBACK_DEFAULT);
@@ -99,6 +112,13 @@ log_helper_t* 
logHelper_createWithName(celix_bundle_context_t* context, const ch
     pthread_mutex_init(&logHelper->logListLock, NULL);
     arrayList_create(&logHelper->logServices);
 
+    celix_service_tracking_options_t opts = 
CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
+    opts.filter.serviceName = OSGI_LOGSERVICE_NAME;
+    opts.callbackHandle = logHelper;
+    opts.add = logHelper_logServiceAdded;
+    opts.remove = logHelper_logServiceRemoved;
+    logHelper->logServiceTrackerId = 
celix_bundleContext_trackServicesWithOptions(logHelper->bundleContext, &opts);
+
        return logHelper;
 }
 
@@ -107,64 +127,28 @@ celix_status_t logHelper_create(bundle_context_pt 
context, log_helper_t **loghel
        return *loghelper == NULL ? CELIX_ILLEGAL_STATE : CELIX_SUCCESS;
 }
 
-celix_status_t logHelper_start(log_helper_t *loghelper)
-{
-       celix_status_t status;
-       service_tracker_customizer_pt logTrackerCustomizer = NULL;
-
-       status = serviceTrackerCustomizer_create(loghelper, NULL, 
logHelper_logServiceAdded, NULL, logHelper_logServiceRemoved, 
&logTrackerCustomizer);
-
-       if (status == CELIX_SUCCESS) {
-        loghelper->logServiceTracker = NULL;
-               status = serviceTracker_create(loghelper->bundleContext, 
(char*) OSGI_LOGSERVICE_NAME, logTrackerCustomizer, 
&loghelper->logServiceTracker);
-       }
-
-       if (status == CELIX_SUCCESS) {
-               status = serviceTracker_open(loghelper->logServiceTracker);
-       }
-
-       return status;
-}
-
-
-
-static celix_status_t logHelper_logServiceAdded(void *handle, 
service_reference_pt reference, void *service)
+static void logHelper_logServiceAdded(void *handle, void *service)
 {
        log_helper_t *loghelper = handle;
 
        pthread_mutex_lock(&loghelper->logListLock);
        arrayList_add(loghelper->logServices, service);
        pthread_mutex_unlock(&loghelper->logListLock);
-
-       return CELIX_SUCCESS;
 }
 
-static celix_status_t logHelper_logServiceRemoved(void *handle, 
service_reference_pt reference, void *service)
+static void logHelper_logServiceRemoved(void *handle, void *service)
 {
        log_helper_t *loghelper = handle;
 
        pthread_mutex_lock(&loghelper->logListLock);
        arrayList_removeElement(loghelper->logServices, service);
        pthread_mutex_unlock(&loghelper->logListLock);
-
-       return CELIX_SUCCESS;
-}
-
-
-celix_status_t logHelper_stop(log_helper_t *loghelper) {
-       celix_status_t status;
-
-    status = serviceTracker_close(loghelper->logServiceTracker);
-
-    return status;
 }
 
 celix_status_t logHelper_destroy(log_helper_t **loghelper) {
         celix_status_t status = CELIX_SUCCESS;
 
-        if((*loghelper)->logServiceTracker){
-               serviceTracker_destroy((*loghelper)->logServiceTracker);
-        }
+        celix_bundleContext_stopTracker((*loghelper)->bundleContext, 
(*loghelper)->logServiceTrackerId);
 
         pthread_mutex_lock(&(*loghelper)->logListLock);
         arrayList_destroy((*loghelper)->logServices);
@@ -172,14 +156,13 @@ celix_status_t logHelper_destroy(log_helper_t 
**loghelper) {
 
         pthread_mutex_destroy(&(*loghelper)->logListLock);
 
+        free((*loghelper)->name);
+
         free(*loghelper);
         *loghelper = NULL;
         return status;
 }
 
-
-
-
 celix_status_t logHelper_log(log_helper_t *loghelper, log_level_t level, const 
char* message, ... )
 {
     celix_status_t status = CELIX_SUCCESS;
diff --git a/bundles/pubsub/pubsub_serializer_avrobin/CMakeLists.txt 
b/bundles/pubsub/pubsub_serializer_avrobin/CMakeLists.txt
index c283e50..1352e82 100644
--- a/bundles/pubsub/pubsub_serializer_avrobin/CMakeLists.txt
+++ b/bundles/pubsub/pubsub_serializer_avrobin/CMakeLists.txt
@@ -24,11 +24,12 @@ add_celix_bundle(celix_pubsub_serializer_avrobin
         SOURCES
         src/ps_avrobin_serializer_activator.c
         src/pubsub_avrobin_serializer_impl.c
-        )
+        src/pubsub_avrobin_serialization_provider.c
+)
 target_include_directories(celix_pubsub_serializer_avrobin PRIVATE
         src
         ${JANSSON_INCLUDE_DIR}
-        )
+)
 set_target_properties(celix_pubsub_serializer_avrobin PROPERTIES INSTALL_RPATH 
"$ORIGIN")
 target_link_libraries(celix_pubsub_serializer_avrobin PRIVATE Celix::framework 
Celix::dfi ${JANSSON_LIBRARIES} Celix::log_helper)
 target_link_libraries(celix_pubsub_serializer_avrobin PRIVATE 
Celix::pubsub_spi Celix::pubsub_utils )
@@ -36,3 +37,7 @@ target_link_libraries(celix_pubsub_serializer_avrobin PRIVATE 
Celix::pubsub_spi
 install_celix_bundle(celix_pubsub_serializer_avrobin EXPORT celix COMPONENT 
pubsub)
 
 add_library(Celix::pubsub_serializer_avrobin ALIAS 
celix_pubsub_serializer_avrobin)
+
+if (ENABLE_TESTING)
+    add_subdirectory(gtest)
+endif(ENABLE_TESTING)
\ No newline at end of file
diff --git a/bundles/pubsub/pubsub_serializer_json/gtest/CMakeLists.txt 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/CMakeLists.txt
similarity index 53%
copy from bundles/pubsub/pubsub_serializer_json/gtest/CMakeLists.txt
copy to bundles/pubsub/pubsub_serializer_avrobin/gtest/CMakeLists.txt
index 276aefe..0987526 100644
--- a/bundles/pubsub/pubsub_serializer_json/gtest/CMakeLists.txt
+++ b/bundles/pubsub/pubsub_serializer_avrobin/gtest/CMakeLists.txt
@@ -15,8 +15,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
-add_celix_bundle(pubsub_seriailizer_json_descriptors NO_ACTIVATOR VERSION 
1.0.0)
-celix_bundle_files(pubsub_seriailizer_json_descriptors
+add_celix_bundle(pubsub_avrobin_serialization_descriptor NO_ACTIVATOR VERSION 
1.0.0)
+celix_bundle_files(pubsub_avrobin_serialization_descriptor
        ${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/garbage.descriptor
        ${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poi1.descriptor
        ${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poi1_invalid1.descriptor
@@ -28,16 +28,16 @@ celix_bundle_files(pubsub_seriailizer_json_descriptors
        DESTINATION "META-INF/descriptors"
 )
 
-add_executable(test_pubsub_serializer_json
-               src/PubSubJsonSerializationProviderTestSuite.cc
+add_executable(test_pubsub_serializer_avrobin
+        src/PubSubAvrobinSerializationProviderTestSuite.cc
 )
-target_link_libraries(test_pubsub_serializer_json PRIVATE Celix::framework 
Celix::pubsub_serializer_json Celix::pubsub_utils GTest::GTest GTest::Main)
-target_compile_options(test_pubsub_serializer_json PRIVATE -std=c++14) #Note 
test code is allowed to be C++14
+target_link_libraries(test_pubsub_serializer_avrobin PRIVATE Celix::framework 
Celix::dfi Celix::pubsub_utils GTest::GTest GTest::Main)
+target_compile_options(test_pubsub_serializer_avrobin PRIVATE -std=c++14) 
#Note test code is allowed to be C++14
 
-add_dependencies(test_pubsub_serializer_json 
celix_pubsub_serializer_json_bundle pubsub_seriailizer_json_descriptors_bundle)
-target_compile_definitions(test_pubsub_serializer_json PRIVATE 
-DSER_BUNDLE=\"$<TARGET_PROPERTY:celix_pubsub_serializer_json,BUNDLE_FILE>\")
-target_compile_definitions(test_pubsub_serializer_json PRIVATE 
-DDESCRIPTOR_BUNDLE=\"$<TARGET_PROPERTY:pubsub_seriailizer_json_descriptors,BUNDLE_FILE>\")
+add_dependencies(test_pubsub_serializer_avrobin 
celix_pubsub_serializer_avrobin_bundle 
pubsub_avrobin_serialization_descriptor_bundle)
+target_compile_definitions(test_pubsub_serializer_avrobin PRIVATE 
-DSER_BUNDLE=\"$<TARGET_PROPERTY:celix_pubsub_serializer_avrobin,BUNDLE_FILE>\")
+target_compile_definitions(test_pubsub_serializer_avrobin PRIVATE 
-DDESCRIPTOR_BUNDLE=\"$<TARGET_PROPERTY:pubsub_avrobin_serialization_descriptor,BUNDLE_FILE>\")
 
-add_test(NAME test_pubsub_serializer_json COMMAND test_pubsub_serializer_json)
-SETUP_TARGET_FOR_COVERAGE(test_pubsub_serializer_json_cov 
test_pubsub_serializer_json 
${CMAKE_BINARY_DIR}/coverage/pubsub/pubsub_serializer_json ..)
+add_test(NAME test_pubsub_serializer_avrobin COMMAND 
test_pubsub_serializer_avrobin)
+SETUP_TARGET_FOR_COVERAGE(test_pubsub_serializer_avrobin_cov 
test_pubsub_serializer_avrobin 
${CMAKE_BINARY_DIR}/coverage/pubsub/pubsub_serializer_avrobin ..)
 
diff --git 
a/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/garbage.descriptor
 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/garbage.descriptor
new file mode 100644
index 0000000..88c65ef
--- /dev/null
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/garbage.descriptor
@@ -0,0 +1 @@
+this is garbage
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1.descriptor
similarity index 82%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
copy to 
bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1.descriptor
index e26d31e..705cf29 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1.descriptor
@@ -7,4 +7,4 @@ classname=org.example.PointOfInterest
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
similarity index 67%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
copy to 
bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
index 32e9ee4..a91e29d 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
@@ -5,8 +5,8 @@ version=1.0.0
 :annotations
 classname=org.example.PointOfInterest
 msgId=42
-invalid_reason=same fqn different msg id
+invalid_reason=same_fqn_different_msg_id
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid2.descriptor
similarity index 61%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
copy to 
bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid2.descriptor
index e26d31e..9bca522 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid2.descriptor
@@ -1,10 +1,11 @@
 :header
 type=message
 name=poi1
-version=1.0.0
+version=1.1.0
 :annotations
 classname=org.example.PointOfInterest
+invalid_reason=different_version
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
similarity index 65%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
copy to 
bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
index cda4c58..3b03ee8 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
@@ -5,8 +5,8 @@ version=1.0.0
 :annotations
 classname=org.example.PointOfInterest
 msgId=42
-invalid_reason=same msg id, different msg fqn
+invalid_reason=same_msg_id_different_msg_fqn
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid4.descriptor
similarity index 55%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
copy to 
bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid4.descriptor
index 32870e8..99fbe43 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi1_invalid4.descriptor
@@ -1,11 +1,12 @@
 :header
 type=message
-name=poi2
+name=poi2_2
 version=1.0.0
 :annotations
 classname=org.example.PointOfInterest
 msgId=5555
+invalid_reason=same_msg_id_different_msg_fqn
 :types
 location={DD lat lon}
 :message
-{llocation;tttt location name description extra data}
+{llocation;tttt location name description extra data}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi2.descriptor
similarity index 72%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
copy to 
bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi2.descriptor
index 32870e8..0136271 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poi2.descriptor
@@ -8,4 +8,4 @@ msgId=5555
 :types
 location={DD lat lon}
 :message
-{llocation;tttt location name description extra data}
+{llocation;tttt location name description extra data}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poiCmd.descriptor
 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poiCmd.descriptor
similarity index 90%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poiCmd.descriptor
copy to 
bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poiCmd.descriptor
index f4f263c..5b674f2 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poiCmd.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/msg_descriptors/msg_poiCmd.descriptor
@@ -5,4 +5,4 @@ version=1.0.0
 :annotations
 classname=org.example.PointOfInterestCommand
 :message
-{t command}
+{t command}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/src/PubSubJsonSerializationProviderTestSuite.cc
 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/src/PubSubAvrobinSerializationProviderTestSuite.cc
similarity index 52%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/src/PubSubJsonSerializationProviderTestSuite.cc
copy to 
bundles/pubsub/pubsub_serializer_avrobin/gtest/src/PubSubAvrobinSerializationProviderTestSuite.cc
index b1db143..ecd4d0a 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/src/PubSubJsonSerializationProviderTestSuite.cc
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/gtest/src/PubSubAvrobinSerializationProviderTestSuite.cc
@@ -24,9 +24,9 @@
 #include <celix_api.h>
 #include "pubsub_message_serialization_service.h"
 
-class PubSubJsonSerializationProviderTestSuite : public ::testing::Test {
+class PubSubAvrobinSerializationProviderTestSuite : public ::testing::Test {
 public:
-    PubSubJsonSerializationProviderTestSuite() {
+    PubSubAvrobinSerializationProviderTestSuite() {
         auto* props = celix_properties_create();
         celix_properties_set(props, OSGI_FRAMEWORK_FRAMEWORK_STORAGE, 
".pubsub_json_serializer_cache");
         auto* fwPtr = celix_frameworkFactory_createFramework(props);
@@ -34,84 +34,80 @@ public:
         fw = std::shared_ptr<celix_framework_t>{fwPtr, [](auto* f) 
{celix_frameworkFactory_destroyFramework(f);}};
         ctx = std::shared_ptr<celix_bundle_context_t>{ctxPtr, 
[](auto*){/*nop*/}};
 
+        const char* descBundleFile = DESCRIPTOR_BUNDLE;
+        const char* serBundleFile = SER_BUNDLE;
         long bndId;
 
-        bndId = celix_bundleContext_installBundle(ctx.get(), 
DESCRIPTOR_BUNDLE, true);
+        bndId = celix_bundleContext_installBundle(ctx.get(), descBundleFile, 
true);
         EXPECT_TRUE(bndId >= 0);
 
-        bndId = celix_bundleContext_installBundle(ctx.get(), SER_BUNDLE, true);
+        bndId = celix_bundleContext_installBundle(ctx.get(), serBundleFile, 
true);
         EXPECT_TRUE(bndId >= 0);
     }
 
-    std::shared_ptr<celix_framework_t> fw;
-    std::shared_ptr<celix_bundle_context_t> ctx;
+    std::shared_ptr<celix_framework_t> fw{};
+    std::shared_ptr<celix_bundle_context_t> ctx{};
 };
 
 
-TEST_F(PubSubJsonSerializationProviderTestSuite, CreateDestroy) {
+TEST_F(PubSubAvrobinSerializationProviderTestSuite, CreateDestroy) {
     //checks if the bundles are started and stopped correctly (no mem leaks).
 }
 
-TEST_F(PubSubJsonSerializationProviderTestSuite, FindSerializationMarkerSvc) {
+TEST_F(PubSubAvrobinSerializationProviderTestSuite, 
FindSerializationMarkerSvc) {
     auto* services = celix_bundleContext_findServices(ctx.get(), 
PUBSUB_MESSAGE_SERIALIZATION_MARKER_NAME);
     EXPECT_EQ(1, celix_arrayList_size(services));
     celix_arrayList_destroy(services);
 }
 
-TEST_F(PubSubJsonSerializationProviderTestSuite, FindSerializationServices) {
+TEST_F(PubSubAvrobinSerializationProviderTestSuite, FindSerializationServices) 
{
     auto* services = celix_bundleContext_findServices(ctx.get(), 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_NAME);
     EXPECT_EQ(3, celix_arrayList_size(services)); //3 valid, 5 invalid
     celix_arrayList_destroy(services);
 }
 
-struct poi1 {
-    struct {
-        double lat;
-        double lon;
-    } location;
-    const char *name;
-};
+TEST_F(PubSubAvrobinSerializationProviderTestSuite, 
SerializeAndDeserializeTest) {
+    struct poi1 {
+        struct {
+            double lat;
+            double lon;
+        } location;
+        const char *name;
+    };
+
+    struct data {
+        poi1* input;
+        poi1* output;
+    };
 
-TEST_F(PubSubJsonSerializationProviderTestSuite, SerializeTest) {
-    poi1 p;
-    p.location.lat = 42;
-    p.location.lon = 43;
-    p.name = "test";
+    poi1 input;
+    input.location.lat = 42;
+    input.location.lon = 43;
+    input.name = "test";
+
+    poi1 output;
+    memset(&output, 0, sizeof(output));
+
+    data dataHandle;
+    dataHandle.input = &input;
+    dataHandle.output = &output;
 
     celix_service_use_options_t opts{};
     opts.filter.serviceName = PUBSUB_MESSAGE_SERIALIZATION_SERVICE_NAME;
     opts.filter.filter = "(msg.fqn=poi1)";
-    opts.callbackHandle = static_cast<void*>(&p);
+    opts.callbackHandle = static_cast<void*>(&dataHandle);
     opts.use = [](void *handle, void *svc) {
-        //auto *poi = static_cast<poi1*>(handle);
+        auto *dh = static_cast<data*>(handle);
         auto* ser = static_cast<pubsub_message_serialization_service_t*>(svc);
-        struct iovec* outVec;
-        size_t outSize;
-        ser->serialize(ser->handle, handle, &outVec, &outSize);
-        EXPECT_TRUE(strstr(static_cast<char*>(outVec->iov_base), "\"lat\":42") 
!= NULL);
-        ser->freeSerializedMsg(ser->handle, outVec, outSize);
-    };
-    bool called = celix_bundleContext_useServiceWithOptions(ctx.get(), &opts);
-    EXPECT_TRUE(called);
-}
+        struct iovec* serVec;
+        size_t serSize;
+        ser->serialize(ser->handle, dh->input, &serVec, &serSize);
+        ser->deserialize(ser->handle, serVec, serSize, (void**)(&dh->output));
 
-TEST_F(PubSubJsonSerializationProviderTestSuite, DeserializeTest) {
-    celix_service_use_options_t opts{};
-    opts.filter.serviceName = PUBSUB_MESSAGE_SERIALIZATION_SERVICE_NAME;
-    opts.filter.filter = "(msg.fqn=poi1)";
-    opts.callbackHandle = nullptr;
-    opts.use = [](void *, void *svc) {
-        auto* ser = static_cast<pubsub_message_serialization_service_t*>(svc);
-        const char* data = 
R"({"location":{"lat":42.0,"lon":43.0},"name":"test"})";
-        poi1 *p = nullptr;
-        iovec inVec;
-        inVec.iov_base = static_cast<void*>(const_cast<char*>(data));
-        inVec.iov_len = strlen(data) + 1;
-        ser->deserialize(ser->handle, &inVec, 1, (void**)(&p));
-        EXPECT_EQ(42,p->location.lat);
-        EXPECT_EQ(43,p->location.lon);
-        EXPECT_STREQ("test", p->name);
-        ser->freeDeserializedMsg(ser->handle, p);
+        EXPECT_EQ(42, dh->output->location.lat);
+
+        ser->freeSerializedMsg(ser->handle, serVec, serSize);
+        ser->freeDeserializedMsg(ser->handle, dh->output);
     };
     bool called = celix_bundleContext_useServiceWithOptions(ctx.get(), &opts);
     EXPECT_TRUE(called);
diff --git 
a/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c
 
b/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c
index e27d5ee..275a72d 100644
--- 
a/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/src/ps_avrobin_serializer_activator.c
@@ -22,10 +22,12 @@
 
 #include "celix_api.h"
 #include "pubsub_avrobin_serializer_impl.h"
+#include "pubsub_avrobin_serialization_provider.h"
 
 typedef struct psav_activator {
     pubsub_avrobin_serializer_t *serializer;
     pubsub_serializer_service_t serializerSvc;
+    pubsub_serialization_provider_t* avrobinSerializationProvider;
     long serializerSvcId;
 } psav_activator_t;
 
@@ -33,6 +35,7 @@ static int psav_start(psav_activator_t *act, 
celix_bundle_context_t *ctx) {
     act->serializerSvcId = -1L;
 
     celix_status_t status = pubsubAvrobinSerializer_create(ctx, 
&(act->serializer));
+    act->avrobinSerializationProvider = 
pubsub_avrobinSerializationProvider_create(ctx);
     if (status == CELIX_SUCCESS) {
         act->serializerSvc.handle = act->serializer;
 
@@ -52,6 +55,7 @@ static int psav_stop(psav_activator_t *act, 
celix_bundle_context_t *ctx) {
     celix_bundleContext_unregisterService(ctx, act->serializerSvcId);
     act->serializerSvcId = -1L;
     pubsubAvrobinSerializer_destroy(act->serializer);
+    
pubsub_avrobinSerializationProvider_destroy(act->avrobinSerializationProvider);
     return CELIX_SUCCESS;
 }
 
diff --git 
a/bundles/pubsub/pubsub_serializer_avrobin/src/pubsub_avrobin_serialization_provider.c
 
b/bundles/pubsub/pubsub_serializer_avrobin/src/pubsub_avrobin_serialization_provider.c
new file mode 100644
index 0000000..1848e5d
--- /dev/null
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/src/pubsub_avrobin_serialization_provider.c
@@ -0,0 +1,117 @@
+/**
+ *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 "pubsub_avrobin_serialization_provider.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "avrobin_serializer.h"
+#include "dyn_message.h"
+#include "log_helper.h"
+#include "pubsub_message_serialization_service.h"
+
+static void dfi_log(void *handle, int level, const char *file, int line, const 
char *msg, ...) {
+    va_list ap;
+    log_helper_t *log = handle;
+    char *logStr = NULL;
+    va_start(ap, msg);
+    vasprintf(&logStr, msg, ap);
+    va_end(ap);
+    logHelper_log(log, level, "FILE:%s, LINE:%i, MSG:%s", file, line, logStr);
+    free(logStr);
+}
+
+
+static celix_status_t 
pubsub_avrobinSerializationProvider_serialize(pubsub_serialization_entry_t* 
entry, const void* msg, struct iovec** output, size_t* outputIovLen) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (*output == NULL) {
+        *output = calloc(1, sizeof(struct iovec));
+        *outputIovLen = 1;
+    } else {
+        return CELIX_ILLEGAL_ARGUMENT;
+    }
+
+    uint8_t *serializedOutput = NULL;
+    size_t serializedOutputLen;
+    dyn_type* dynType;
+    dynMessage_getMessageType(entry->msgType, &dynType);
+
+    if (avrobinSerializer_serialize(dynType, msg, &serializedOutput, 
&serializedOutputLen) != 0) {
+        status = CELIX_BUNDLE_EXCEPTION;
+    }
+
+    if (status == CELIX_SUCCESS) {
+        (**output).iov_base = (void*)serializedOutput;
+        (**output).iov_len  = serializedOutputLen;
+    }
+
+    return status;
+}
+
+void 
pubsub_avrobinSerializationProvider_freeSerializeMsg(pubsub_serialization_entry_t*
 entry, struct iovec* input, size_t inputIovLen) {
+    if (input != NULL) {
+        if (entry->msgType != NULL) {
+            for (int i = 0; i < inputIovLen; i++) {
+                if (input[i].iov_base) {
+                    free(input[i].iov_base);
+                }
+                input[i].iov_base = NULL;
+                input[i].iov_len = 0;
+            }
+        }
+        free(input);
+    }
+}
+
+celix_status_t 
pubsub_avrobinSerializationProvider_deserialize(pubsub_serialization_entry_t* 
entry, const struct iovec* input, size_t inputIovLen __attribute__((unused)), 
void **out) {
+    celix_status_t status = CELIX_SUCCESS;
+    if (input == NULL) return CELIX_BUNDLE_EXCEPTION;
+    void *msg = NULL;
+    dyn_type* dynType;
+    dynMessage_getMessageType(entry->msgType, &dynType);
+
+    if (avrobinSerializer_deserialize(dynType, (uint8_t *)input->iov_base, 
input->iov_len, &msg) != 0) {
+        status = CELIX_BUNDLE_EXCEPTION;
+    } else{
+        *out = msg;
+    }
+
+    return status;
+}
+
+void 
pubsub_avrobinSerializationProvider_freeDeserializeMsg(pubsub_serialization_entry_t*
 entry, void *msg) {
+    if (entry->msgType != NULL) {
+        dyn_type* dynType;
+        dynMessage_getMessageType(entry->msgType, &dynType);
+        dynType_free(dynType, msg);
+    }
+}
+
+pubsub_serialization_provider_t* 
pubsub_avrobinSerializationProvider_create(celix_bundle_context_t* ctx)  {
+    pubsub_serialization_provider_t* provider = 
pubsub_serializationProvider_create(ctx, "avrobin", 
pubsub_avrobinSerializationProvider_serialize, 
pubsub_avrobinSerializationProvider_freeSerializeMsg, 
pubsub_avrobinSerializationProvider_deserialize, 
pubsub_avrobinSerializationProvider_freeDeserializeMsg);
+    avrobinSerializer_logSetup(dfi_log, 
pubsub_serializationProvider_getLogHelper(provider), 1);;
+    return provider;
+}
+
+void 
pubsub_avrobinSerializationProvider_destroy(pubsub_serialization_provider_t* 
provider) {
+    pubsub_serializationProvider_destroy(provider);
+}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_avrobin/src/pubsub_avrobin_serialization_provider.h
 
b/bundles/pubsub/pubsub_serializer_avrobin/src/pubsub_avrobin_serialization_provider.h
new file mode 100644
index 0000000..b8ed98a
--- /dev/null
+++ 
b/bundles/pubsub/pubsub_serializer_avrobin/src/pubsub_avrobin_serialization_provider.h
@@ -0,0 +1,40 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CELIX_PUBSUB_AVROBIN_SERIALIZATION_PROVIDER_H
+#define CELIX_PUBSUB_AVROBIN_SERIALIZATION_PROVIDER_H
+
+#include "pubsub_serialization_provider.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+pubsub_serialization_provider_t* 
pubsub_avrobinSerializationProvider_create(celix_bundle_context_t *ctx);
+
+/**
+ * Destroys the provided AVRO-bin Serialization Provider.
+ */
+void 
pubsub_avrobinSerializationProvider_destroy(pubsub_serialization_provider_t 
*provider);
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif //CELIX_PUBSUB_AVROBIN_SERIALIZATION_PROVIDER_H
diff --git a/bundles/pubsub/pubsub_serializer_json/CMakeLists.txt 
b/bundles/pubsub/pubsub_serializer_json/CMakeLists.txt
index d1e9eb2..d91112c 100644
--- a/bundles/pubsub/pubsub_serializer_json/CMakeLists.txt
+++ b/bundles/pubsub/pubsub_serializer_json/CMakeLists.txt
@@ -25,7 +25,7 @@ add_celix_bundle(celix_pubsub_serializer_json
     SOURCES
         src/ps_json_serializer_activator.c
         src/pubsub_serializer_impl.c
-        src/pubsub_json_serialization_provider.c
+        src/pubsub_avrobin_serialization_provider.c
 )
 target_include_directories(celix_pubsub_serializer_json PRIVATE
     src
diff --git a/bundles/pubsub/pubsub_serializer_json/gtest/CMakeLists.txt 
b/bundles/pubsub/pubsub_serializer_json/gtest/CMakeLists.txt
index 276aefe..0e7104d 100644
--- a/bundles/pubsub/pubsub_serializer_json/gtest/CMakeLists.txt
+++ b/bundles/pubsub/pubsub_serializer_json/gtest/CMakeLists.txt
@@ -15,8 +15,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
-add_celix_bundle(pubsub_seriailizer_json_descriptors NO_ACTIVATOR VERSION 
1.0.0)
-celix_bundle_files(pubsub_seriailizer_json_descriptors
+add_celix_bundle(pubsub_json_serialization_descriptor NO_ACTIVATOR VERSION 
1.0.0)
+celix_bundle_files(pubsub_json_serialization_descriptor
        ${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/garbage.descriptor
        ${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poi1.descriptor
        ${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poi1_invalid1.descriptor
@@ -31,12 +31,12 @@ celix_bundle_files(pubsub_seriailizer_json_descriptors
 add_executable(test_pubsub_serializer_json
                src/PubSubJsonSerializationProviderTestSuite.cc
 )
-target_link_libraries(test_pubsub_serializer_json PRIVATE Celix::framework 
Celix::pubsub_serializer_json Celix::pubsub_utils GTest::GTest GTest::Main)
+target_link_libraries(test_pubsub_serializer_json PRIVATE Celix::framework 
Celix::dfi Celix::pubsub_utils GTest::GTest GTest::Main)
 target_compile_options(test_pubsub_serializer_json PRIVATE -std=c++14) #Note 
test code is allowed to be C++14
 
-add_dependencies(test_pubsub_serializer_json 
celix_pubsub_serializer_json_bundle pubsub_seriailizer_json_descriptors_bundle)
+add_dependencies(test_pubsub_serializer_json 
celix_pubsub_serializer_json_bundle pubsub_json_serialization_descriptor_bundle)
 target_compile_definitions(test_pubsub_serializer_json PRIVATE 
-DSER_BUNDLE=\"$<TARGET_PROPERTY:celix_pubsub_serializer_json,BUNDLE_FILE>\")
-target_compile_definitions(test_pubsub_serializer_json PRIVATE 
-DDESCRIPTOR_BUNDLE=\"$<TARGET_PROPERTY:pubsub_seriailizer_json_descriptors,BUNDLE_FILE>\")
+target_compile_definitions(test_pubsub_serializer_json PRIVATE 
-DDESCRIPTOR_BUNDLE=\"$<TARGET_PROPERTY:pubsub_json_serialization_descriptor,BUNDLE_FILE>\")
 
 add_test(NAME test_pubsub_serializer_json COMMAND test_pubsub_serializer_json)
 SETUP_TARGET_FOR_COVERAGE(test_pubsub_serializer_json_cov 
test_pubsub_serializer_json 
${CMAKE_BINARY_DIR}/coverage/pubsub/pubsub_serializer_json ..)
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
index e26d31e..705cf29 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
@@ -7,4 +7,4 @@ classname=org.example.PointOfInterest
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
index 32e9ee4..a91e29d 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
@@ -5,8 +5,8 @@ version=1.0.0
 :annotations
 classname=org.example.PointOfInterest
 msgId=42
-invalid_reason=same fqn different msg id
+invalid_reason=same_fqn_different_msg_id
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid2.descriptor
 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid2.descriptor
index dbf0a00..9bca522 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid2.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid2.descriptor
@@ -1 +1,11 @@
-this is garbage
\ No newline at end of file
+:header
+type=message
+name=poi1
+version=1.1.0
+:annotations
+classname=org.example.PointOfInterest
+invalid_reason=different_version
+:types
+location={DD lat lon}
+:message
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
index cda4c58..3b03ee8 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
@@ -5,8 +5,8 @@ version=1.0.0
 :annotations
 classname=org.example.PointOfInterest
 msgId=42
-invalid_reason=same msg id, different msg fqn
+invalid_reason=same_msg_id_different_msg_fqn
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid4.descriptor
 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid4.descriptor
index cda4c58..99fbe43 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid4.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid4.descriptor
@@ -1,12 +1,12 @@
 :header
 type=message
-name=poi2
+name=poi2_2
 version=1.0.0
 :annotations
 classname=org.example.PointOfInterest
-msgId=42
-invalid_reason=same msg id, different msg fqn
+msgId=5555
+invalid_reason=same_msg_id_different_msg_fqn
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;tttt location name description extra data}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
index 32870e8..0136271 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
@@ -8,4 +8,4 @@ msgId=5555
 :types
 location={DD lat lon}
 :message
-{llocation;tttt location name description extra data}
+{llocation;tttt location name description extra data}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poiCmd.descriptor
 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poiCmd.descriptor
index f4f263c..5b674f2 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poiCmd.descriptor
+++ 
b/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poiCmd.descriptor
@@ -5,4 +5,4 @@ version=1.0.0
 :annotations
 classname=org.example.PointOfInterestCommand
 :message
-{t command}
+{t command}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/src/PubSubJsonSerializationProviderTestSuite.cc
 
b/bundles/pubsub/pubsub_serializer_json/gtest/src/PubSubJsonSerializationProviderTestSuite.cc
index b1db143..1a635e5 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/src/PubSubJsonSerializationProviderTestSuite.cc
+++ 
b/bundles/pubsub/pubsub_serializer_json/gtest/src/PubSubJsonSerializationProviderTestSuite.cc
@@ -34,17 +34,19 @@ public:
         fw = std::shared_ptr<celix_framework_t>{fwPtr, [](auto* f) 
{celix_frameworkFactory_destroyFramework(f);}};
         ctx = std::shared_ptr<celix_bundle_context_t>{ctxPtr, 
[](auto*){/*nop*/}};
 
+        const char* descBundleFile = DESCRIPTOR_BUNDLE;
+        const char* serBundleFile = SER_BUNDLE;
         long bndId;
 
-        bndId = celix_bundleContext_installBundle(ctx.get(), 
DESCRIPTOR_BUNDLE, true);
+        bndId = celix_bundleContext_installBundle(ctx.get(), descBundleFile, 
true);
         EXPECT_TRUE(bndId >= 0);
 
-        bndId = celix_bundleContext_installBundle(ctx.get(), SER_BUNDLE, true);
+        bndId = celix_bundleContext_installBundle(ctx.get(), serBundleFile, 
true);
         EXPECT_TRUE(bndId >= 0);
     }
 
-    std::shared_ptr<celix_framework_t> fw;
-    std::shared_ptr<celix_bundle_context_t> ctx;
+    std::shared_ptr<celix_framework_t> fw{};
+    std::shared_ptr<celix_bundle_context_t> ctx{};
 };
 
 
diff --git 
a/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c 
b/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c
index 88db57f..075aaf1 100644
--- a/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c
+++ b/bundles/pubsub/pubsub_serializer_json/src/ps_json_serializer_activator.c
@@ -26,7 +26,7 @@
 
 typedef struct psjs_activator {
     pubsub_json_serializer_t* serializer;
-    pubsub_json_serialization_provider_t *provider;
+    pubsub_serialization_provider_t *provider;
 
     pubsub_serializer_service_t serializerSvc;
     long serializerSvcId;
diff --git 
a/bundles/pubsub/pubsub_serializer_json/src/pubsub_avrobin_serialization_provider.c
 
b/bundles/pubsub/pubsub_serializer_json/src/pubsub_avrobin_serialization_provider.c
new file mode 100644
index 0000000..026c6c6
--- /dev/null
+++ 
b/bundles/pubsub/pubsub_serializer_json/src/pubsub_avrobin_serialization_provider.c
@@ -0,0 +1,116 @@
+/**
+ *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 "pubsub_json_serialization_provider.h"
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+
+#include "json_serializer.h"
+#include "dyn_message.h"
+#include "log_helper.h"
+#include "pubsub_message_serialization_service.h"
+
+static void dfi_log(void *handle, int level, const char *file, int line, const 
char *msg, ...) {
+    va_list ap;
+    log_helper_t *log = handle;
+    char *logStr = NULL;
+    va_start(ap, msg);
+    vasprintf(&logStr, msg, ap);
+    va_end(ap);
+    logHelper_log(log, level, "FILE:%s, LINE:%i, MSG:%s", file, line, logStr);
+    free(logStr);
+}
+
+
+static celix_status_t 
pubsub_jsonSerializationProvider_serialize(pubsub_serialization_entry_t* entry, 
const void* msg, struct iovec** output, size_t* outputIovLen) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (*output == NULL) {
+        *output = calloc(1, sizeof(struct iovec));
+        *outputIovLen = 1;
+    } else {
+        return CELIX_ILLEGAL_ARGUMENT;
+    }
+
+    char *jsonOutput = NULL;
+    dyn_type* dynType;
+    dynMessage_getMessageType(entry->msgType, &dynType);
+
+    if (jsonSerializer_serialize(dynType, msg, &jsonOutput) != 0) {
+        status = CELIX_BUNDLE_EXCEPTION;
+    }
+
+    if (status == CELIX_SUCCESS) {
+        (**output).iov_base = (void*)jsonOutput;
+        (**output).iov_len  = strlen(jsonOutput) + 1;
+    }
+
+    return status;
+}
+
+void 
pubsub_jsonSerializationProvider_freeSerializeMsg(pubsub_serialization_entry_t* 
entry, struct iovec* input, size_t inputIovLen) {
+    if (input != NULL) {
+        if (entry->msgType != NULL) {
+            for (int i = 0; i < inputIovLen; i++) {
+                if (input[i].iov_base) {
+                    free(input[i].iov_base);
+                }
+                input[i].iov_base = NULL;
+                input[i].iov_len = 0;
+            }
+        }
+        free(input);
+    }
+}
+
+celix_status_t 
pubsub_jsonSerializationProvider_deserialize(pubsub_serialization_entry_t* 
entry, const struct iovec* input, size_t inputIovLen __attribute__((unused)), 
void **out) {
+    celix_status_t status = CELIX_SUCCESS;
+    if (input == NULL) return CELIX_BUNDLE_EXCEPTION;
+    void *msg = NULL;
+    dyn_type* dynType;
+    dynMessage_getMessageType(entry->msgType, &dynType);
+
+    if (jsonSerializer_deserialize(dynType, (const char*)input->iov_base, 
&msg) != 0) {
+        status = CELIX_BUNDLE_EXCEPTION;
+    } else{
+        *out = msg;
+    }
+
+    return status;
+}
+
+void 
pubsub_jsonSerializationProvider_freeDeserializeMsg(pubsub_serialization_entry_t*
 entry, void *msg) {
+    if (entry->msgType != NULL) {
+        dyn_type* dynType;
+        dynMessage_getMessageType(entry->msgType, &dynType);
+        dynType_free(dynType, msg);
+    }
+}
+
+pubsub_serialization_provider_t* 
pubsub_jsonSerializationProvider_create(celix_bundle_context_t* ctx)  {
+    pubsub_serialization_provider_t* provider = 
pubsub_serializationProvider_create(ctx, "json", 
pubsub_jsonSerializationProvider_serialize, 
pubsub_jsonSerializationProvider_freeSerializeMsg, 
pubsub_jsonSerializationProvider_deserialize, 
pubsub_jsonSerializationProvider_freeDeserializeMsg);
+    jsonSerializer_logSetup(dfi_log, 
pubsub_serializationProvider_getLogHelper(provider), 1);;
+    return provider;
+}
+
+void pubsub_jsonSerializationProvider_destroy(pubsub_serialization_provider_t* 
provider) {
+    pubsub_serializationProvider_destroy(provider);
+}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/src/pubsub_json_serialization_provider.h
 
b/bundles/pubsub/pubsub_serializer_json/src/pubsub_json_serialization_provider.h
index 20f77e0..8c7fc72 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/src/pubsub_json_serialization_provider.h
+++ 
b/bundles/pubsub/pubsub_serializer_json/src/pubsub_json_serialization_provider.h
@@ -20,50 +20,18 @@
 #ifndef CELIX_PUBSUB_JSON_SERIALIZATION_PROVIDER_H
 #define CELIX_PUBSUB_JSON_SERIALIZATION_PROVIDER_H
 
-#include "celix_bundle_context.h"
+#include "pubsub_serialization_provider.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-typedef struct pubsub_json_serialization_provider 
pubsub_json_serialization_provider_t; //opaque
-
-/**
- * Creates JSON Serialization Provider.
- *
- * The provider monitors bundles and creates pubsub message serialization 
services for every unique descriptor found.
- *
- * Descriptors can be DFI descriptors or AVPR descriptors (FIXE #158).
- *
- * The provider will look for descriptors in META-INF/descriptors directory of 
every installed bundle.
- * If a framework config CELIX_FRAMEWORK_EXTENDER_PATH is set, this path will 
also be used to search for descriptor files.
- *
- * For every unique and valid descriptor found a 
pubsub_message_serialization_service will be registered for the 'json' 
serialization type.
- * The provider will also register a single pubsub_serialization_marker 
service which 'marks' the existing of the a json serialization support.
- *
- * Lastly a celix command shell will be register with the command name 
'celix::json_message_serialization' which can be used to interactively
- * query the provided serialization services.
- *
- * @param ctx   The bundle context.
- * @return      A JSON Serialization Provider.
- */
-pubsub_json_serialization_provider_t 
*pubsub_jsonSerializationProvider_create(celix_bundle_context_t *ctx);
+pubsub_serialization_provider_t* 
pubsub_jsonSerializationProvider_create(celix_bundle_context_t *ctx);
 
 /**
  * Destroys the provided JSON Serialization Provider.
  */
-void 
pubsub_jsonSerializationProvider_destroy(pubsub_json_serialization_provider_t 
*provider);
-
-
-/**
- * Returns the number of valid entries.
- */
-size_t 
pubsub_jsonSerializationProvider_nrOfEntries(pubsub_json_serialization_provider_t
 *provider);
-
-/**
- * Returns the number of invalid entries.
- */
-size_t 
pubsub_jsonSerializationProvider_nrOfInvalidEntries(pubsub_json_serialization_provider_t
 *provider);
+void pubsub_jsonSerializationProvider_destroy(pubsub_serialization_provider_t 
*provider);
 
 #ifdef __cplusplus
 };
diff --git a/bundles/pubsub/pubsub_utils/CMakeLists.txt 
b/bundles/pubsub/pubsub_utils/CMakeLists.txt
index 48bc0f6..6a73114 100644
--- a/bundles/pubsub/pubsub_utils/CMakeLists.txt
+++ b/bundles/pubsub/pubsub_utils/CMakeLists.txt
@@ -19,6 +19,7 @@ add_library(pubsub_utils STATIC
         src/pubsub_utils.c
         src/pubsub_utils_url.c
         src/pubsub_serializer_handler.c
+        src/pubsub_serialization_provider.c
 )
 
 set_target_properties(pubsub_utils PROPERTIES OUTPUT_NAME "celix_pubsub_utils")
@@ -26,7 +27,7 @@ target_include_directories(pubsub_utils PUBLIC
         $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
         $<INSTALL_INTERFACE:include/celix/pubsub_utils>
 )
-target_link_libraries(pubsub_utils PUBLIC Celix::framework Celix::pubsub_api 
Celix::pubsub_spi Celix::log_helper)
+target_link_libraries(pubsub_utils PUBLIC Celix::framework Celix::pubsub_api 
Celix::pubsub_spi Celix::log_helper Celix::shell_api)
 
 add_library(Celix::pubsub_utils ALIAS pubsub_utils)
 
diff --git a/bundles/pubsub/pubsub_utils/gtest/CMakeLists.txt 
b/bundles/pubsub/pubsub_utils/gtest/CMakeLists.txt
index 0cea076..79f10bd 100644
--- a/bundles/pubsub/pubsub_utils/gtest/CMakeLists.txt
+++ b/bundles/pubsub/pubsub_utils/gtest/CMakeLists.txt
@@ -15,11 +15,27 @@
 # specific language governing permissions and limitations
 # under the License.
 
+add_celix_bundle(pubsub_serialization_provider_descriptors NO_ACTIVATOR 
VERSION 1.0.0)
+celix_bundle_files(pubsub_serialization_provider_descriptors
+               ${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/garbage.descriptor
+               ${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poi1.descriptor
+               
${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poi1_invalid1.descriptor
+               
${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poi1_invalid2.descriptor
+               
${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poi1_invalid3.descriptor
+               
${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poi1_invalid4.descriptor
+               ${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poi2.descriptor
+               
${CMAKE_CURRENT_SOURCE_DIR}/msg_descriptors/msg_poiCmd.descriptor
+               DESTINATION "META-INF/descriptors"
+)
+
 add_executable(test_pubsub_utils
-               src/PubSubMsgSerializationTestSuite.cc
+               src/PubSubSerializationHandlerTestSuite.cc
+               src/PubSubSerializationProviderTestSuite.cc
 )
 target_link_libraries(test_pubsub_utils PRIVATE Celix::framework 
Celix::pubsub_utils GTest::GTest GTest::Main)
 target_compile_options(test_pubsub_utils PRIVATE -std=c++14) #Note test code 
is allowed to be C++14
 add_test(NAME test_pubsub_utils COMMAND test_pubsub_utils)
 SETUP_TARGET_FOR_COVERAGE(test_pubsub_utils_cov test_pubsub_utils 
${CMAKE_BINARY_DIR}/coverage/pubsub/pubsub_utils ..)
 
+add_dependencies(test_pubsub_utils 
pubsub_serialization_provider_descriptors_bundle)
+target_compile_definitions(test_pubsub_utils PRIVATE 
-DDESCRIPTOR_BUNDLE=\"$<TARGET_PROPERTY:pubsub_serialization_provider_descriptors,BUNDLE_FILE>\")
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/garbage.descriptor 
b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/garbage.descriptor
new file mode 100644
index 0000000..88c65ef
--- /dev/null
+++ b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/garbage.descriptor
@@ -0,0 +1 @@
+this is garbage
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
 b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1.descriptor
similarity index 82%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
copy to bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1.descriptor
index e26d31e..705cf29 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
+++ b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1.descriptor
@@ -7,4 +7,4 @@ classname=org.example.PointOfInterest
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
 
b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
similarity index 67%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
copy to 
bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
index 32e9ee4..a91e29d 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
+++ 
b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid1.descriptor
@@ -5,8 +5,8 @@ version=1.0.0
 :annotations
 classname=org.example.PointOfInterest
 msgId=42
-invalid_reason=same fqn different msg id
+invalid_reason=same_fqn_different_msg_id
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
 
b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid2.descriptor
similarity index 61%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
copy to 
bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid2.descriptor
index e26d31e..9bca522 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1.descriptor
+++ 
b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid2.descriptor
@@ -1,10 +1,11 @@
 :header
 type=message
 name=poi1
-version=1.0.0
+version=1.1.0
 :annotations
 classname=org.example.PointOfInterest
+invalid_reason=different_version
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
 
b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
similarity index 65%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
copy to 
bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
index cda4c58..3b03ee8 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
+++ 
b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid3.descriptor
@@ -5,8 +5,8 @@ version=1.0.0
 :annotations
 classname=org.example.PointOfInterest
 msgId=42
-invalid_reason=same msg id, different msg fqn
+invalid_reason=same_msg_id_different_msg_fqn
 :types
 location={DD lat lon}
 :message
-{llocation;t location name}
+{llocation;t location name}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
 
b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid4.descriptor
similarity index 55%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
copy to 
bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid4.descriptor
index 32870e8..99fbe43 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
+++ 
b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi1_invalid4.descriptor
@@ -1,11 +1,12 @@
 :header
 type=message
-name=poi2
+name=poi2_2
 version=1.0.0
 :annotations
 classname=org.example.PointOfInterest
 msgId=5555
+invalid_reason=same_msg_id_different_msg_fqn
 :types
 location={DD lat lon}
 :message
-{llocation;tttt location name description extra data}
+{llocation;tttt location name description extra data}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
 b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi2.descriptor
similarity index 72%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
copy to bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi2.descriptor
index 32870e8..0136271 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poi2.descriptor
+++ b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poi2.descriptor
@@ -8,4 +8,4 @@ msgId=5555
 :types
 location={DD lat lon}
 :message
-{llocation;tttt location name description extra data}
+{llocation;tttt location name description extra data}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poiCmd.descriptor
 b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poiCmd.descriptor
similarity index 90%
copy from 
bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poiCmd.descriptor
copy to bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poiCmd.descriptor
index f4f263c..5b674f2 100644
--- 
a/bundles/pubsub/pubsub_serializer_json/gtest/msg_descriptors/msg_poiCmd.descriptor
+++ b/bundles/pubsub/pubsub_utils/gtest/msg_descriptors/msg_poiCmd.descriptor
@@ -5,4 +5,4 @@ version=1.0.0
 :annotations
 classname=org.example.PointOfInterestCommand
 :message
-{t command}
+{t command}
\ No newline at end of file
diff --git 
a/bundles/pubsub/pubsub_utils/gtest/src/PubSubMsgSerializationTestSuite.cc 
b/bundles/pubsub/pubsub_utils/gtest/src/PubSubSerializationHandlerTestSuite.cc
similarity index 88%
rename from 
bundles/pubsub/pubsub_utils/gtest/src/PubSubMsgSerializationTestSuite.cc
rename to 
bundles/pubsub/pubsub_utils/gtest/src/PubSubSerializationHandlerTestSuite.cc
index 1d06f01..b2e9644 100644
--- a/bundles/pubsub/pubsub_utils/gtest/src/PubSubMsgSerializationTestSuite.cc
+++ 
b/bundles/pubsub/pubsub_utils/gtest/src/PubSubSerializationHandlerTestSuite.cc
@@ -24,9 +24,9 @@
 #include <celix_api.h>
 #include "pubsub_serializer_handler.h"
 
-class PubSubMsgSerializationTestSuite : public ::testing::Test {
+class PubSubSerializationHandlerTestSuite : public ::testing::Test {
 public:
-    PubSubMsgSerializationTestSuite() {
+    PubSubSerializationHandlerTestSuite() {
         auto* props = celix_properties_create();
         celix_properties_set(props, OSGI_FRAMEWORK_FRAMEWORK_STORAGE, 
".pubsub_utils_cache");
         auto* fwPtr = celix_frameworkFactory_createFramework(props);
@@ -36,21 +36,21 @@ public:
 
         msgSerSvc.handle = this;
         msgSerSvc.serialize = [](void* handle, const void*, struct iovec**, 
size_t*) -> celix_status_t {
-            auto* suite = 
static_cast<PubSubMsgSerializationTestSuite*>(handle);
+            auto* suite = 
static_cast<PubSubSerializationHandlerTestSuite*>(handle);
             suite->serializeCallCount += 1;
             return CELIX_SUCCESS;
         };
         msgSerSvc.freeSerializedMsg = [](void* handle, struct iovec* , size_t) 
{
-            auto* suite = 
static_cast<PubSubMsgSerializationTestSuite*>(handle);
+            auto* suite = 
static_cast<PubSubSerializationHandlerTestSuite*>(handle);
             suite->freeSerializedMsgCallCount += 1;
         };
         msgSerSvc.deserialize = [](void* handle, const struct iovec*, size_t, 
void**) -> celix_status_t {
-            auto* suite = 
static_cast<PubSubMsgSerializationTestSuite*>(handle);
+            auto* suite = 
static_cast<PubSubSerializationHandlerTestSuite*>(handle);
             suite->deserializeCallCount += 1;
             return CELIX_SUCCESS;
         };
         msgSerSvc.freeDeserializedMsg = [](void* handle, void*) {
-            auto* suite = 
static_cast<PubSubMsgSerializationTestSuite*>(handle);
+            auto* suite = 
static_cast<PubSubSerializationHandlerTestSuite*>(handle);
             suite->freeDeserializedMsgCallCount += 1;
         };
     }
@@ -69,8 +69,8 @@ public:
         return celix_bundleContext_registerServiceWithOptions(ctx.get(), 
&opts);
     }
 
-    std::shared_ptr<celix_framework_t> fw;
-    std::shared_ptr<celix_bundle_context_t> ctx;
+    std::shared_ptr<celix_framework_t> fw{};
+    std::shared_ptr<celix_bundle_context_t> ctx{};
     pubsub_message_serialization_service_t  msgSerSvc{};
 
     size_t serializeCallCount = 0;
@@ -80,19 +80,21 @@ public:
 };
 
 
-TEST_F(PubSubMsgSerializationTestSuite, CreateDestroy) {
+TEST_F(PubSubSerializationHandlerTestSuite, CreateDestroy) {
     auto *handler = pubsub_serializerHandler_create(ctx.get(), "json", true);
     ASSERT_TRUE(handler != nullptr);
     pubsub_serializerHandler_destroy(handler);
 }
 
-TEST_F(PubSubMsgSerializationTestSuite, SerializationServiceFound) {
+TEST_F(PubSubSerializationHandlerTestSuite, SerializationServiceFound) {
     auto *handler = pubsub_serializerHandler_create(ctx.get(), "json", true);
     long svcId = registerSerSvc("json", 42, "example::Msg", "1.0.0");
 
     EXPECT_EQ(1, 
pubsub_serializerHandler_messageSerializationServiceCount(handler));
     EXPECT_EQ(42, pubsub_serializerHandler_getMsgId(handler, "example::Msg"));
-    EXPECT_STREQ("example::Msg", pubsub_serializerHandler_getMsgFqn(handler, 
42));
+    auto *fqn = pubsub_serializerHandler_getMsgFqn(handler, 42);
+    EXPECT_STREQ("example::Msg",  fqn);
+    free(fqn);
     EXPECT_TRUE(pubsub_serializerHandler_supportMsg(handler, 42, 1, 0));
     EXPECT_FALSE(pubsub_serializerHandler_supportMsg(handler, 42, 2, 0));
 
@@ -102,7 +104,7 @@ TEST_F(PubSubMsgSerializationTestSuite, 
SerializationServiceFound) {
     pubsub_serializerHandler_destroy(handler);
 }
 
-TEST_F(PubSubMsgSerializationTestSuite, DifferentTypeOfSerializationService) {
+TEST_F(PubSubSerializationHandlerTestSuite, 
DifferentTypeOfSerializationService) {
     auto *handler = pubsub_serializerHandler_create(ctx.get(), "json", true);
     long svcId = registerSerSvc("avrobin", 42, "example::Msg", "1.0.0");
     EXPECT_EQ(0, 
pubsub_serializerHandler_messageSerializationServiceCount(handler));
@@ -110,7 +112,7 @@ TEST_F(PubSubMsgSerializationTestSuite, 
DifferentTypeOfSerializationService) {
     pubsub_serializerHandler_destroy(handler);
 }
 
-TEST_F(PubSubMsgSerializationTestSuite, MutipleSerializationServices) {
+TEST_F(PubSubSerializationHandlerTestSuite, MutipleSerializationServices) {
     auto *handler = pubsub_serializerHandler_create(ctx.get(), "json", true);
     long svcId1 = registerSerSvc("json", 43, "example::Msg1", "1.0.0");
     long svcId2 = registerSerSvc("json", 44, "example::Msg2", "1.0.0");
@@ -128,7 +130,7 @@ TEST_F(PubSubMsgSerializationTestSuite, 
MutipleSerializationServices) {
     pubsub_serializerHandler_destroy(handler);
 }
 
-TEST_F(PubSubMsgSerializationTestSuite, ClashingId) {
+TEST_F(PubSubSerializationHandlerTestSuite, ClashingId) {
     auto *handler = pubsub_serializerHandler_create(ctx.get(), "json", true);
 
     testing::internal::CaptureStderr();
@@ -143,7 +145,7 @@ TEST_F(PubSubMsgSerializationTestSuite, ClashingId) {
     pubsub_serializerHandler_destroy(handler);
 }
 
-TEST_F(PubSubMsgSerializationTestSuite, MultipleVersions) {
+TEST_F(PubSubSerializationHandlerTestSuite, MultipleVersions) {
     auto *handler = pubsub_serializerHandler_create(ctx.get(), "json", true);
 
     testing::internal::CaptureStderr();
@@ -166,7 +168,7 @@ TEST_F(PubSubMsgSerializationTestSuite, MultipleVersions) {
     pubsub_serializerHandler_destroy(handler);
 }
 
-TEST_F(PubSubMsgSerializationTestSuite, NoBackwardsCompatbile) {
+TEST_F(PubSubSerializationHandlerTestSuite, NoBackwardsCompatbile) {
     auto *handler = pubsub_serializerHandler_create(ctx.get(), "json", false);
 
     long svcId1 = registerSerSvc("json", 42, "example::Msg1", "1.0.0");
@@ -182,7 +184,7 @@ TEST_F(PubSubMsgSerializationTestSuite, 
NoBackwardsCompatbile) {
     pubsub_serializerHandler_destroy(handler);
 }
 
-TEST_F(PubSubMsgSerializationTestSuite, CallServiceMethods) {
+TEST_F(PubSubSerializationHandlerTestSuite, CallServiceMethods) {
     auto *handler = pubsub_serializerHandler_create(ctx.get(), "json", false);
 
     long svcId1 = registerSerSvc("json", 42, "example::Msg1", "1.0.0");
@@ -205,7 +207,7 @@ TEST_F(PubSubMsgSerializationTestSuite, CallServiceMethods) 
{
     pubsub_serializerHandler_destroy(handler);
 }
 
-TEST_F(PubSubMsgSerializationTestSuite, MismatchedCallServiceMethods) {
+TEST_F(PubSubSerializationHandlerTestSuite, MismatchedCallServiceMethods) {
     auto *handler = pubsub_serializerHandler_create(ctx.get(), "json", false);
 
     long svcId1 = registerSerSvc("json", 42, "example::Msg1", "1.0.0");
@@ -229,7 +231,7 @@ TEST_F(PubSubMsgSerializationTestSuite, 
MismatchedCallServiceMethods) {
     pubsub_serializerHandler_destroy(handler);
 }
 
-TEST_F(PubSubMsgSerializationTestSuite, BackwardsCompatibleCall) {
+TEST_F(PubSubSerializationHandlerTestSuite, BackwardsCompatibleCall) {
     auto *handler = pubsub_serializerHandler_create(ctx.get(), "json", true);
 
     long svcId1 = registerSerSvc("json", 42, "example::Msg1", "1.0.0");
diff --git 
a/bundles/pubsub/pubsub_utils/gtest/src/PubSubSerializationProviderTestSuite.cc 
b/bundles/pubsub/pubsub_utils/gtest/src/PubSubSerializationProviderTestSuite.cc
new file mode 100644
index 0000000..8507160
--- /dev/null
+++ 
b/bundles/pubsub/pubsub_utils/gtest/src/PubSubSerializationProviderTestSuite.cc
@@ -0,0 +1,75 @@
+/**
+ *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 <memory>
+
+#include <celix_api.h>
+#include "pubsub_serialization_provider.h"
+
+class PubSubSerializationProviderTestSuite : public ::testing::Test {
+public:
+    PubSubSerializationProviderTestSuite() {
+        auto* props = celix_properties_create();
+        celix_properties_set(props, OSGI_FRAMEWORK_FRAMEWORK_STORAGE, 
".pubsub_serialization_provider_cache");
+        auto* fwPtr = celix_frameworkFactory_createFramework(props);
+        auto* ctxPtr = celix_framework_getFrameworkContext(fwPtr);
+        fw = std::shared_ptr<celix_framework_t>{fwPtr, [](auto* f) 
{celix_frameworkFactory_destroyFramework(f);}};
+        ctx = std::shared_ptr<celix_bundle_context_t>{ctxPtr, 
[](auto*){/*nop*/}};
+
+        long bndId;
+
+        bndId = celix_bundleContext_installBundle(ctx.get(), 
DESCRIPTOR_BUNDLE, true);
+        EXPECT_TRUE(bndId >= 0);
+    }
+
+    std::shared_ptr<celix_framework_t> fw{};
+    std::shared_ptr<celix_bundle_context_t> ctx{};
+};
+
+
+TEST_F(PubSubSerializationProviderTestSuite, CreateDestroy) {
+    //checks if the bundles are started and stopped correctly (no mem leaks).
+    auto* provider = pubsub_serializationProvider_create(ctx.get(), "test", 
nullptr, nullptr, nullptr, nullptr);
+    pubsub_serializationProvider_destroy(provider);
+}
+
+TEST_F(PubSubSerializationProviderTestSuite, FindSerializationMarkerSvc) {
+    auto* provider = pubsub_serializationProvider_create(ctx.get(), "test", 
nullptr, nullptr, nullptr, nullptr);
+    auto* services = celix_bundleContext_findServices(ctx.get(), 
PUBSUB_MESSAGE_SERIALIZATION_MARKER_NAME);
+    EXPECT_EQ(1, celix_arrayList_size(services));
+    celix_arrayList_destroy(services);
+    pubsub_serializationProvider_destroy(provider);
+}
+
+TEST_F(PubSubSerializationProviderTestSuite, FindSerializationServices) {
+    auto* provider = pubsub_serializationProvider_create(ctx.get(), "test", 
nullptr, nullptr, nullptr, nullptr);
+
+    size_t nrEntries = pubsub_serializationProvider_nrOfEntries(provider);
+    EXPECT_EQ(3, nrEntries);
+    size_t nrOfInvalidEntries = 
pubsub_serializationProvider_nrOfInvalidEntries(provider);
+    EXPECT_EQ(4, nrOfInvalidEntries);
+
+    auto* services = celix_bundleContext_findServices(ctx.get(), 
PUBSUB_MESSAGE_SERIALIZATION_SERVICE_NAME);
+    EXPECT_EQ(3, celix_arrayList_size(services)); //3 valid, 5 invalid
+    celix_arrayList_destroy(services);
+
+    pubsub_serializationProvider_destroy(provider);
+}
diff --git 
a/bundles/pubsub/pubsub_utils/include/pubsub_serialization_provider.h 
b/bundles/pubsub/pubsub_utils/include/pubsub_serialization_provider.h
new file mode 100644
index 0000000..5dec0f5
--- /dev/null
+++ b/bundles/pubsub/pubsub_utils/include/pubsub_serialization_provider.h
@@ -0,0 +1,107 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CELIX_PUBSUB_SERIALIZATION_PROVIDER_H
+#define CELIX_PUBSUB_SERIALIZATION_PROVIDER_H
+
+#include "log_helper.h"
+#include "celix_bundle_context.h"
+#include "pubsub_message_serialization_service.h"
+#include "dyn_message.h"
+#include "celix_version.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct pubsub_serialization_provider pubsub_serialization_provider_t; 
//opaque
+
+typedef struct {
+    log_helper_t *log;
+    long svcId;
+    pubsub_message_serialization_service_t  svc;
+    char* descriptorContent;
+    dyn_message_type *msgType;
+    unsigned int msgId;
+    const char* msgFqn;
+    celix_version_t *msgVersion;
+    char *msgVersionStr;
+
+    long readFromBndId;
+    char* readFromEntryPath;
+    size_t nrOfTimesRead; //nr of times read from different bundles.
+
+    bool valid;
+    const char* invalidReason;
+} pubsub_serialization_entry_t;
+
+/**
+ * Creates A (descriptor based) Serialization Provider.
+ *
+ * The provider monitors bundles and creates pubsub message serialization 
services for every unique descriptor found.
+ *
+ * Descriptors can be DFI descriptors or AVPR descriptors (FIXE #158).
+ *
+ * The provider will look for descriptors in META-INF/descriptors directory of 
every installed bundle.
+ * If a framework config CELIX_FRAMEWORK_EXTENDER_PATH is set, this path will 
also be used to search for descriptor files.
+ *
+ * For every unique and valid descriptor found a 
pubsub_message_serialization_service will be registered for the 'json' 
serialization type.
+ * The provider will also register a single pubsub_serialization_marker 
service which 'marks' the existing of the a json serialization support.
+ *
+ * Lastly a celix command shell will be register with the command name 
'celix::<serialization_type>_message_serialization' which can be used to 
interactively
+ * query the provided serialization services.
+ *
+ * @param ctx   The bundle context.
+ * @return      A JSON Serialization Provider.
+ */
+pubsub_serialization_provider_t *pubsub_serializationProvider_create(
+        celix_bundle_context_t *ctx,
+        const char* serializationType,
+        celix_status_t (*serialize)(pubsub_serialization_entry_t* entry, const 
void* msg, struct iovec** output, size_t* outputIovLen),
+        void (*freeSerializeMsg)(pubsub_serialization_entry_t* entry, struct 
iovec* input, size_t inputIovLen),
+        celix_status_t (*deserialize)(pubsub_serialization_entry_t* entry, 
const struct iovec* input, size_t inputIovLen __attribute__((unused)), void 
**out),
+        void (*freeDeserializeMsg)(pubsub_serialization_entry_t* entry, void 
*msg));
+
+/**
+ * Destroys the provided JSON Serialization Provider.
+ */
+void pubsub_serializationProvider_destroy(pubsub_serialization_provider_t 
*provider);
+
+
+/**
+ * Returns the number of valid entries.
+ */
+size_t 
pubsub_serializationProvider_nrOfEntries(pubsub_serialization_provider_t 
*provider);
+
+/**
+ * Returns the number of invalid entries.
+ */
+size_t 
pubsub_serializationProvider_nrOfInvalidEntries(pubsub_serialization_provider_t 
*provider);
+
+/**
+ * Returns the log helper of the serialization provider.
+ */
+log_helper_t* 
pubsub_serializationProvider_getLogHelper(pubsub_serialization_provider_t 
*provider);
+
+
+#ifdef __cplusplus
+};
+#endif
+
+#endif //CELIX_PUBSUB_SERIALIZATION_PROVIDER_H
diff --git a/bundles/pubsub/pubsub_utils/include/pubsub_serializer_handler.h 
b/bundles/pubsub/pubsub_utils/include/pubsub_serializer_handler.h
index 9c8797b..4434e10 100644
--- a/bundles/pubsub/pubsub_utils/include/pubsub_serializer_handler.h
+++ b/bundles/pubsub/pubsub_utils/include/pubsub_serializer_handler.h
@@ -20,13 +20,16 @@
 #ifndef CELIX_PUBSUB_SERIALIZER_HANDLER_H
 #define CELIX_PUBSUB_SERIALIZER_HANDLER_H
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+#include <stdint.h>
 
 #include "celix_api.h"
 #include "pubsub_message_serialization_service.h"
 
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 typedef struct pubsub_serializer_handler pubsub_serializer_handler_t; //opaque 
type
 
 
diff --git a/bundles/pubsub/pubsub_utils/src/pubsub_serializer_handler.c 
b/bundles/pubsub/pubsub_utils/src/pubsub_serializer_handler.c
index d827b10..6e09414 100644
--- a/bundles/pubsub/pubsub_utils/src/pubsub_serializer_handler.c
+++ b/bundles/pubsub/pubsub_utils/src/pubsub_serializer_handler.c
@@ -156,6 +156,7 @@ void 
pubsub_serializerHandler_destroy(pubsub_serializer_handler_t* handler) {
             celix_arrayList_destroy(entries);
         }
         hashMap_destroy(handler->serializationServices, false, false);
+        logHelper_destroy(&handler->logHelper);
         free(handler);
     }
 }
diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c
index 50eceee..9056e74 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -1547,6 +1547,7 @@ celix_status_t fw_addBundleListener(framework_pt 
framework, bundle_pt bundle, bu
         fw_bundleEntry_decreaseUseCount(entry);
     }
     fw_bundleListener_decreaseUseCount(bundleListener);
+    celix_arrayList_destroy(installedBundles);
 
     return status;
 }

Reply via email to