在运行时忽略 OSGi 依赖项中的 POJO 导入的杰克逊注释



摘要

当 POJO 在运行时在导入捆绑包中序列化时,应用于通过 OSGi depdendency 导出的 POJO 的杰克逊注释不起作用。如果将 POJO 直接放置在使用捆绑包中,或在单元测试中进行测试(在任一捆绑包中(,则一切按预期工作。

有谁知道什么会使运行时序列化在导入 OSGi 捆绑包中忽略运行时的杰克逊注释?


这是一个悬而未决的问题。我试图创建一个尽可能简单的例子。如果有什么不清楚的地方,请告诉我,我会尽力详细说明。

内容

  • 导出捆绑包内部

    • 波乔
    • 单元测试(有效(
    • 运行时测试(有效(
  • 导入捆绑包内部

    • 单元测试(有效(
    • 运行时测试(失败(
  • 运行时环境详细信息

  • 捆绑清单(简化(

简化示例:

假设我们想序列化一个通过OSGi导出和导入的简单POJO。JSON 注释应该在导入和导出捆绑包中工作,无论是运行时还是在单元测试期间(运行时在导入时失败(。


导出捆绑包内部:

Jackson 序列化的运行时测试和单元测试在声明 POJO 本身的捆绑包中都可以正常工作。

要序列化的 POJO

@JsonProperty注释应该使此 POJO 的任何序列化版本看起来像{"correctSerializedName":"someName"}而不是{"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;
}
}

正确行为:单元测试

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"}");
}    
}

正确行为:运行时

public void runtimeFromDepdendency() {
DependencyModel dependencyModel = new DependencyModel("name");
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(dependencyModel);
// jsonString = {"correctSerializedName":"name"}
}

在导入 OSGi 捆绑包内部

正确行为:单元测试

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"}");
}
}

失败:运行时

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
}

运行时环境

  • Jira 7.2.2 OSGi(基于 Apache Felix(
  • Maven 3.2.1
  • 爪哇 1.8
  • 杰克逊 2.9.3

导出插件捆绑包清单(简化(

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

导入插件捆绑包清单(简化(

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

如上所示,@JsonProperty-注释在导入过程中在运行时被忽略,但其他所有内容都按预期工作。同样,我不认为这是杰克逊版本的问题,尽管我可能忽略了一些东西。

我是否错过了一些基本的OSGi行为?

根据我的评论和您的反馈:

问题是您的两个捆绑包具有不同的杰克逊注释类实例。当 Jackson 框架扫描类以查找批注时,它会查找它使用的特定批注类实例。如果捆绑包具有同一类的自己的实例,则不会识别注释。(在OSGi中,每个捆绑包都有一个单独的类加载器,每个类加载器可以包含给定类的自己的实例。

您可以通过两种方式解决此问题:

  1. 将 jackson2 作为单独的捆绑包部署到 OSGi 容器中,并确保导入和导出捆绑包都Import-Package相关的 jackson 包。最核心的捆绑包是:jackson-annotationsjackson-corejackson-databind。在这种情况下,请对两个捆绑包中的 jackson2 依赖项使用范围provided
  2. 从其中一个捆绑包中
  3. 导出 jackson2 包,并将其导入到另一个捆绑包中。这将为您提供额外的工作,以确定和维护要导出的包。在这种情况下,请在导出捆绑包中使用 jackson2 的作用域compile,在导入捆绑包中使用作用域provided

就我而言,有杰克逊的进口,我没有考虑到。看到您的评论后,我只是将它们添加到pom中。它工作得很好。

最新更新