IBM WAS 8.5.5.4:在不同 JAR 中具有接口和实现的 POJO 无法成功注入另一个 EJB jar 中的 EJB 3.1 bean

IBM WAS 8.5.5.4 : A POJO with interface and implementation in different JARs cannot be injected successfully inside an EJB 3.1 bean in another EJB jar

我正在开发 Java EE 6 应用程序,它必须在 JBoss WildFly 8.2.0 和 IBM WAS 8.5.5.4 中使用相同的 EAR 包工作。

应用程序结构非常简单。它基本上遵循以下一个:

耳朵
|__ /lib/
|____|__ API.jar
|____|__ IMPL.jar
|
|__ EJB.jar
|__ WebConsole.war
|____|__/库
|_______|__C.jar

在 EJB 模块中,我有一个 @Stateless 会话 bean 试图 @Inject 一个 POJO。
这里的特殊性在于 POJO 实现了一个位于 [API.jar] 中的接口,但实现位于 [IMPL.jar].

此外,POJO 实现用我们自己的 限定符 注释,即 @ServiceProvider. ,它只是定义为:

@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD,ElementType.PARAMETER})
public @interface ServiceProvider {

}

EJB 如下所示(仅显示相关代码):

@Stateless
@Local(SecurityServiceLocal.class)
public class SecurityService implements SecurityServiceLocal {

    @Inject @ServiceProvider
    IServiceProvider serviceProvider;
    ...
}

POJO 接口(在 API.jar 内)如下所示:

public interface IServiceProvider {

    public String sayHello();
}

POJO 实现(在 IMPL.jar 内)如下所示:

@Named
@ServiceProvider
public class ServiceProviderImpl implements IServiceProvider, Serializable {

   private static final long serialVersionUID = -1L;

   @Override
   public String sayHello() {
       return "Hello!";
   }

[API.jar][IMPL.jar]甚至[EJB.jar] 有一个空 [/META-INF/beans.xml] 以启用 CDI。

使用@Produces的Factory在[IMPL.jar]中也可用,如下图:

public class ServiceFactory {

    @Produces IServiceProvider getServiceProvider(@ServiceProvider IServiceProvider serviceProvider) {
        return serviceProvider;
    }
}

最后但同样重要的是,[EJB.jar] 引用了 [API.jar][IMPL.jar] 在 /META-INF/MANIFEST.MF Class-Path 属性.


现在,当 运行 这个示例应用程序在 WildFly 8.2.0.Final 中时,一切都按预期工作。用 @ServiceProvider 注释的 IServiceProvider 的实现被注入到 EJB 中。

或者换句话说,实现API.jar中接口的IMPL.jar中的POJO被注入到Stateless Session bean中EJB.jar

但是,当在 IBM WebSphere 8.5.5.4 中部署相同的应用程序时,注入失败并在启动期间显示以下消息:

javax.enterprise.inject.UnsatisfiedResolutionException: 
Api type [dummy.IServiceProvider] is not found with the qualifiers 
Qualifiers: [@dummy.qualifier.ServiceProvider()] for injection into Field Injection Point, field :  dummy.IServiceProvider dummy.securityplugin.service.SecurityService.serviceProvider, 
Bean Owner : [WSEjbBean [businessLocals=[interface dummy.securityplugin.service.SecurityServiceLocal], 
ejbName=SecurityService-975208151,Name:null,WebBeans Type:ENTERPRISE,
API Types:    [dummy.securityplugin.service.SecurityServiceLocal,java.lang.Object],
Qualifiers:[javax.enterprise.inject.Any,javax.enterprise.inject.Default]]
InjectionType   :  [interface dummy.IServiceProvider]
Annotated    :  [Annotated Field,Base Type : interface dummy.IServiceProvider,
Type Closures : [class java.lang.Object, interface dummy.IServiceProvider],
Annotations : [@dummy.qualifier.ServiceProvider(), @javax.inject.Inject()],
Java Member Name : serviceProvider]
Qualifiers   :  [[@dummy.qualifier.ServiceProvider()]]

IBM 知识中心有一个 link 提供了对此类异常的一些见解:

http://www-01.ibm.com/support/knowledgecenter/SSD28V_8.5.5/com.ibm.websphere.nd.doc/ae/tweb_troubleshoot_cdi.html

然而,据我所知,一切都配置正确(它在 WildFly 8 中运行!!)。

最后,我尝试其他方法:我 MOVE POJO 实现 FROM [IMPL.jar] [EJB.jar] ... 而这次注入 WORKS 正如 中预期的那样WebSphere 8.5.5.4

因此看起来,如果要注入 EJB 的 POJO class 驻留在 SAME ejb 模块中,则完全没有问题。

但是,在我们最终的代码结构中,我们必须具有[API.jar][IMPL.jar]分别.

因此,最后一个问题:我做错了什么? IBM WebSphere 8.5.5.4(可能还有其他 8.x 版本)是否存在某种错误?我需要回忆一下,EJB 模块在 Class-Path Manifest 属性中引用了 API 和 IMPL jar。

非常感谢有关此主题的帮助...谢谢 !!!

最终我找到了根本原因。 罪魁祸首是 application.xml

由于我使用 Maven 生成带有 maven-ear-plugin 的 EAR 包,事实证明,如果我们没有明确指定 Java EE 版本为 6,则默认 application.xml 针对旧的 J2EE 1.3 系统。

WildFly 8 似乎忽略了这一点,并且一切正常。 但是,在 WebSphere 8.x 中,如果 application.xml 没有指定 version="6" ,Classpath 设置就完全乱了。

换句话说,maven-ear-plugin 必须包含 6 标签,如下所示:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-ear-plugin</artifactId>
    <version>2.7</version>
    <configuration>            
        <version>6</version>
    ...

要为 application.xml 正确生成正确的版本:

<xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
                             http://java.sun.com/xml/ns/javaee/application_6.xsd" 
         version="6">