Summary
Jackson annotations applied to POJOs exported through an OSGi depdendency does not work when the POJO is serialized in an importing bundle at Runtime. If the POJO is placed in the using bundle directly, or tested in a Unit Test (in either bundle), everything works as expected.
Does anyone know what could make the runtime serialization ignore the Jackson-annotations at runtime in the importing OSGi-bundle?
This is a looong question. I have tried to create an as simple example as possible. If anything is unclear, please let me know, and I will try to elaborate.
Contents
Inside Exporting Bundle
- POJO
- Unit test (which works)
- Runtime test (which works)
Inside Importing Bundle
- Unit test (which works)
- Runtime test (which FAILS)
Runtime environment details
- Bundle manifests (simplified)
Simplified example:
Let's assume we have want to serialize a simple POJO exported and imported over OSGi. The JSON-annotations should work both in the importing and exporting bundle, both runtime and during unit tests (runtime fails in the when imported).
Inside Exporting Bundle:
Both runtime and unit tests of the Jackson serialization works just fine in the bundle where the POJO itself is declared.
POJO to serialize
The @JsonProperty
-annotation should make any serialized version of this POJO look something like {"correctSerializedName":"someName"}
and not {"javaName":"someName"}
:
package exporting.osgi.bundle.models;
import com.fasterxml.jackson.annotation.JsonProperty;
public class DependencyModel {
private String javaName;
@JsonProperty("correctSerializedName")
public String getJavaName() {
return javaName;
}
public DependencyModel(String javaName) {
this.javaName = javaName;
}
}
Correct behaviour: Unit test
import com.fasterxml.jackson.*;
import org.junit.jupiter.*;
class ExportingBundleTests {
@Test
void serialize_inDepdendencyProject_getsCorrectJsonName() {
DependencyModel dependencyModel = new DependencyModel("name");
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(dependencyModel);
// Asserts True -> serialization works as expected
assertEquals(jsonString, "{\"correctSerializedName\":\"name\"}");
}
}
Correct behaviour: Runtime
public void runtimeFromDepdendency() {
DependencyModel dependencyModel = new DependencyModel("name");
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(dependencyModel);
// jsonString = {"correctSerializedName":"name"}
}
Inside the importing OSGi bundle
Correct behaviour: Unit test
import exporting.osgi.bundle.models.DependencyModel;
import com.fasterxml.jackson.*;
import org.junit.jupiter.api.*;
class ImportingBundleTests {
@Test
void serialize_inUsingProject_getsCorrectJsonName() {
DependencyModel dependencyModel = new DependencyModel("name");
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(dependencyModel);
// Asserts True -> serialization works as expected
assertEquals(jsonString, "{\"correctSerializedName\":\"name\"}");
}
}
FAILS: Runtime
import exporting.osgi.bundle.models.DependencyModel;
import com.fasterxml.jackson.*;
public Response runsFromUsingProject() throws JsonProcessingException {
DependencyModel dependencyModel = new DependencyModel("name");
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(dependencyModel);
// jsonString = {"javaName":"name"} <---- WHICH IS WRONG
}
Runtime environment
- Jira 7.2.2 OSGi (based on Apache Felix)
- Maven 3.2.1
- Java 1.8
- Jackson 2.9.3
Exporting plugin Bundle Manifest (simplified)
Created-By: Apache Maven Bundle Plugin
Manifest-Version: 1.0
Build-Jdk: 1.8.0_111
Bundle-ManifestVersion: 2
Export-Package:
...
exporting.osgi.bundle;version="1.0.0";
uses:="exporting.osgi.bundle.models",
...
Originally-Created-By: Apache Maven Bundle Plugin
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Spring-Context: *
Tool: Bnd-2.4.1.201501161923
Importing plugin Bundle Manifest (simplified)
Created-By: Apache Maven Bundle Plugin
Manifest-Version: 1.0
Build-Jdk: 1.8.0_111
Bundle-ManifestVersion: 2
Archiver-Version: Plexus Archiver
Bundle-ClassPath: .,META-INF/lib/gt-epsg-hsql-18.1.jar,META-INF/lib/sq
lite-jdbc-3.8.11.1.jar
Import-Package:
...
exporting.osgi.bundle.models
...
com.fasterxml.jackson.dataformat.xml;resolution:=optional,
com.fasterxml.jackson.dataformat.xml.deser;resolution:=optional,
com.fasterxml.jackson.dataformat.xml.ser;resolution:=optional,
org.codehaus.jackson;resolution:=optional,
org.codehaus.jackson.annotate;resolution:=optional,
org.codehaus.jackson.map;resolution:=optional,
org.codehaus.jackson.map.annotate;resolution:=optional,
...
Originally-Created-By: Apache Maven Bundle Plugin
Require-Capability: osgi.ee;filter:="(&(osgi.ee=JavaSE)(version=1.8))"
Spring-Context: *
Tool: Bnd-2.4.1.201501161923
As illustrated above, the @JsonProperty
-annotation is ignored at runtime in the importing depdendency, but everything else works as expected. Again, I don't think this is a Jackson-version issue, although I might have overlooked something.
Have I perhaps missed some fundamental OSGi-behaviour?