在带有 JBoss 的 EJB Jar (6.2.0 GA) 中忽略了 Jackson 2 注释 [英] Jackson 2 annotations ignored in EJB Jar with JBoss (6.2.0 GA)

查看:23
本文介绍了在带有 JBoss 的 EJB Jar (6.2.0 GA) 中忽略了 Jackson 2 注释的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将 Web 应用程序从 Websphere 7 (JEE5) 迁移到 JBoss EAP 6.2.0 (JEE6).它目前在 Glassfish 3 & 中运行良好.曾是.

Web 界面使用/生成 JSON - 所以我使用 Jackson2 和 Spring 3 MVC MappingJackson2HttpMessageConverter 在一个简单的控制器类中处理(反)序列化.

在 JBoss 中,我看到在 ejb 模块中忽略了 Jackson2 注释 @JsonProperty 等 -(它们仅应用于 JPA 实体),但是 正在 应用于网络模块.因此,对于 JBoss 中的某些对象,响应会返回不同的字段名称,这会导致我们的用户界面跳闸.

我已经尝试了 jboss-deployment-structure.xml 的每一个排列都无济于事(见下文).我知道 JBoss 附带了 Jackson 1.x 作为内部模块.然而,这似乎不是问题,否则 web 模块注释也会被忽略?例如:部署到 JBOSS 后忽略的 Jackson 注释

该应用程序由 3 个 maven 模块构成 - war、ejb (jar) &耳朵容器.

我将重构代码以从 JPA 实体中删除注释,但实际上最好找到一个连贯的解决方案,因为还有其他几个应用程序要迁移.

我在下面尝试过的 JBoss 描述符,没有区别.

<ear-subdeployments-isolated>false</ear-subdeployments-isolated><部署><排除事项><模块名称="org.codehaus.jackson.jackson-core-asl"/><模块名称="org.codehaus.jackson.jackson-mapper-asl"/></排除项></部署><子部署名称="my-war.war"><排除事项><模块名称="org.codehaus.jackson.jackson-core-asl"/><模块名称="org.codehaus.jackson.jackson-mapper-asl"/></排除项></子部署><子部署名称="my-ejbs.jar"><排除事项><模块名称="org.codehaus.jackson.jackson-core-asl"/><模块名称="org.codehaus.jackson.jackson-mapper-asl"/></排除项></子部署></jboss-deployment-structure>

初始解决方法(现已恢复)

虽然它没有解决最初的问题是由什么引起的,但我已经通过在 web 模块中添加一个 Jackson Mixin 来重命名/抑制相关字段来解决这个问题.我已经测试过了,效果很好.

这一切的重点是,通过使用 Jackson Mixin,序列化的定制范围被限制在 web 模块中,从而避免了由于 ejb-jar 可能导致的类加载问题.em> 子部署.没有使用 jboss-deployment-structure.xml.

添加一个混入

公共接口 MyMixin {@JsonIgnoreString getUnwantedField();@JsonProperty(value = "newName")字符串 getOldName();}

然后在我的 web 控制器启动时,我将 Mixin 连接到 Jackson ObjectMapper,它自动连接到控制器并在我的调度程序 servlet xml 配置中定义.

 @Autowired私有 ObjectMapper objectMapper;@PostConstructvoid configObjectMapper() {objectMapper.addMixInAnnotations(MyEjbJar.class, MyMixin.class);}

调度程序 servlet:

<预><代码>..<bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>

解决方案

我已经(通过 IDE 调试器和添加日志记录)追踪到用于 war 模块和 ejb jar 模块的不同类加载器.根据文档,这是 JBoss AS 7 的预期默认行为.war使用war ModuleLoader,ejb jar使用ear ModuleLoader.

注解的类会根据加载注解的类加载器而有所不同.另请参阅:类似问题所以

我所说的不同"是指它们是相同的注释,来自同一个 jar &版本,但根据 equals 的约定,它们不被视为等效,它们的哈希码不同,因此 JacksonAnnotationIntrospector 不会定位注释,即使它们显示为针对 JPA POJO 类.

解决方法

我已经解决了这个问题,让 Ear ModuleLoader 成为 jackson 2 的通用加载器.我通过让 com.fasterxml.jackson.core 数据绑定 依赖 提供 战争范围&ejb jar,并在ear POM 中将其标记为正常的编译范围依赖项.

这种方法在这里得到某种认可JBoss AS 类加载 虽然它使用 jboss-deployment-structure 或 MANIFEST.MF 来实现几乎相同的事情.

I am migrating a web app from Websphere 7 (JEE5) to JBoss EAP 6.2.0 (JEE6). It currently works fine in Glassfish 3 & WAS.

The web interface consumes/produces JSON - so am using Jackson2 with Spring 3 MVC MappingJackson2HttpMessageConverter to handling (de)serialisation in a simple controller class.

In JBoss I see Jackson2 annotations @JsonProperty etc are being ignored in the ejb module - (they are applied to JPA entities only), but are being applied in the web module. So responses come back with different field names for some objects in JBoss which trips up our user interface.

I've tried every permuation of jboss-deployment-structure.xml to no avail (see below). I'm aware that JBoss ships with Jackson 1.x as an internal module. However, this doesn't seem to be the problem, otherwise the web module annotations would be ignored as well ? E.g.: Jackson annotations ignored after deployment to JBOSS

The app is structured as 3 maven modules - war, ejb (jar) & the ear container.

I'm going to refactor the code to remove the annotations from the JPA entities, but really it would be good to find a coherent solution, as there are several other apps to migrate.

JBoss descriptor I've tried below, makes no difference.

<jboss-deployment-structure>
    <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
    <deployment>
        <exclusions>
            <module name="org.codehaus.jackson.jackson-core-asl"/>
            <module name="org.codehaus.jackson.jackson-mapper-asl"/>
        </exclusions>
    </deployment>
    <sub-deployment name="my-war.war">
        <exclusions>
            <module name="org.codehaus.jackson.jackson-core-asl"/>
            <module name="org.codehaus.jackson.jackson-mapper-asl"/>
        </exclusions>
    </sub-deployment>
    <sub-deployment name="my-ejbs.jar">
        <exclusions>
            <module name="org.codehaus.jackson.jackson-core-asl"/>
            <module name="org.codehaus.jackson.jackson-mapper-asl"/>
        </exclusions>
    </sub-deployment>
</jboss-deployment-structure>

Initial Workaround (reverted now)

Whilst it does not address what the original problem was caused by, I have solved this by adding a Jackson Mixin within the web module to rename/suppress the fields concerned. I've tested this and it works fine.

The point about all this, is that by using a Jackson Mixin, the scope of the customisation of the serialisation has been confined to the web module, and thereby avoided possible class loading issues due to ejb-jar sub-deployment. No jboss-deployment-structure.xml is being used.

Add a Mixin

public interface MyMixin {


    @JsonIgnore
    String getUnwantedField();

    @JsonProperty(value = "newName")
    String getOldName();

}

Then in the startup of my web controller I wire in the Mixin to the Jackson ObjectMapper which is autowired into the controller and defined in my dispatcher servlet xml config.

 @Autowired
 private ObjectMapper objectMapper;

 @PostConstruct
    void configObjectMapper() {
        objectMapper.addMixInAnnotations(MyEjbJar.class, MyMixin.class);     
    }

Dispatcher servlet:

.
.
    <bean id="objectMapper" class="com.fasterxml.jackson.databind.ObjectMapper"/>

解决方案

I have tracked this down (via IDE debugger & adding logging) to different classloaders being used for the war module and ejb jar module. This is expected default behaviour with JBoss AS 7 according to the docs. The war uses the war ModuleLoader, and the ejb jar uses the ear ModuleLoader.

What happens is the Class for the annotation differs depending on which class loader loads the annotation. Also see: similar issue on SO

By "differs" I mean they are the same annotation, sourced from the same jar & version, but they are not deemed equivalent according to the contract for equals, their hashcodes differ, therefore the JacksonAnnotationIntrospector does not locate annotations even though they show as held against the JPA POJO class.

Workaround

I have worked around this by making the ear ModuleLoader be a common loader for jackson 2. I did this by making the com.fasterxml.jackson.core databind dependency provided scope in the war & ejb jar, and marking it as a normal compile scope dependency in the ear POM.

This kind of approach is sort of endorsed here JBoss AS classloading although it uses the jboss-deployment-structure or MANIFEST.MF to achieve pretty much the same thing.

这篇关于在带有 JBoss 的 EJB Jar (6.2.0 GA) 中忽略了 Jackson 2 注释的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆