"IllegalArgumentException: Can not set [EJB interface] field [managed bean field] to com.sun.proxy.$Proxy[some number]" 与 OmniFaces 的@Eager

"IllegalArgumentException: Can not set [EJB interface] field [managed bean field] to com.sun.proxy.$Proxy[some number]" with OmniFaces' @Eager

将 EJB 注入多模块 Maven 中的 JSF 托管 bean Java EE 7 项目在 Payara 4.x 和 5.x 以及 Glassfish 4.x 和 5.x 以及 WildFly 11.0.0.Final 这让我觉得这不是我最初认为的 Payara/Glassfish 错误 [1].

WAR 模块中的一个简单的 JSF 支持 bean

@Named
@ApplicationScoped
@Eager
public class Init {
    @EJB
    private InitService initService;

    public Init() {
    }

    @PostConstruct
    public void init() {
        initService.init();
    }
}

在 JAR 模块中使用 EJB 接口

@Local
public interface InitService {

    void init();
}

以及 EJB 模块中的实现

@Stateless
public class DefaultInitService implements InitService {
    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public void init() {
        Long id = 1L;
        MyEntity myEntity0 = entityManager.find(MyEntity.class, id);
        if(myEntity0 == null) {
            myEntity0 = new MyEntity(Long.MIN_VALUE, "myProperty");
            entityManager.persist(myEntity0);
        }
    }
}

由于

在 Payara 4.1.2.174 上失败
WARN:   WELD-000718: No EEModuleDescriptor defined for bean archive with ID: payara-classloading-proxy-issue-web-1.0-SNAPSHOT_war.war. @Initialized and @Destroyed events for ApplicationScoped may be fired twice.
WARNUNG:   Could not instantiate eager application scoped beans. Possibly the CDI application scope is not active. This is known to be the case in certain Tomcat and Jetty based configurations.
java.lang.IllegalStateException: Exception attempting to inject Local ejb-ref name=richtercloud.payara.classloading.proxy.issue.jar.Init/initService,Local 3.x interface =richtercloud.payara.classloading.proxy.issue.jar.InitService resolved to intra-app EJB DefaultInitService in module payara-classloading-proxy-issue-ejb-1.0-SNAPSHOT.jar,ejb-link=payara-classloading-proxy-issue-ejb-1.0-SNAPSHOT.jar#DefaultInitService,lookup=,mappedName=,jndi-name=,refType=Session into class richtercloud.payara.classloading.proxy.issue.jar.Init: Can not set richtercloud.payara.classloading.proxy.issue.jar.InitService field richtercloud.payara.classloading.proxy.issue.jar.Init.initService to com.sun.proxy.$Proxy254
    at org.glassfish.weld.services.InjectionServicesImpl.aroundInject(InjectionServicesImpl.java:185)
    at org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:46)
    at org.jboss.weld.injection.producer.ResourceInjector.inject(ResourceInjector.java:72)
    at org.jboss.weld.injection.producer.BasicInjectionTarget.inject(BasicInjectionTarget.java:117)
    at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:159)
    at org.jboss.weld.context.AbstractContext.get(AbstractContext.java:96)
    at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.get(ContextualInstanceStrategy.java:100)
    at org.jboss.weld.bean.ContextualInstanceStrategy$ApplicationScopedContextualInstanceStrategy.get(ContextualInstanceStrategy.java:140)
    at org.jboss.weld.bean.ContextualInstance.get(ContextualInstance.java:50)
    at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:99)
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.getInstance(ProxyMethodHandler.java:125)
    at richtercloud.payara.classloading.proxy.issue.jar.Init$Proxy$_$$_WeldClientProxy.toString(Unknown Source)
    at org.omnifaces.cdi.eager.EagerBeansRepository.instantiateBeans(EagerBeansRepository.java:135)
    at org.omnifaces.cdi.eager.EagerBeansRepository.instantiateApplicationScoped(EagerBeansRepository.java:105)
    at org.omnifaces.cdi.eager.EagerBeansRepository$Proxy$_$$_WeldClientProxy.instantiateApplicationScoped(Unknown Source)
    at org.omnifaces.cdi.eager.EagerBeansRepository.instantiateApplicationScopedAndRegisterListenerIfNecessary(EagerBeansRepository.java:79)
    at org.omnifaces.ApplicationListener.contextInitialized(ApplicationListener.java:83)
    at org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:4991)
    at com.sun.enterprise.web.WebModule.contextListenerStart(WebModule.java:574)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:5560)
    at com.sun.enterprise.web.WebModule.start(WebModule.java:522)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:956)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:939)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:684)
    at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:2099)
    at com.sun.enterprise.web.WebContainer.loadWebModule(WebContainer.java:1745)
    at com.sun.enterprise.web.WebApplication.start(WebApplication.java:107)
    at org.glassfish.internal.data.EngineRef.start(EngineRef.java:122)
    at org.glassfish.internal.data.ModuleInfo.start(ModuleInfo.java:294)
    at org.glassfish.internal.data.ApplicationInfo.start(ApplicationInfo.java:357)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:501)
    at com.sun.enterprise.v3.server.ApplicationLifecycle.deploy(ApplicationLifecycle.java:220)
    at org.glassfish.deployment.admin.DeployCommand.execute(DeployCommand.java:508)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:544)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:540)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:360)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.execute(CommandRunnerImpl.java:539)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:570)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.run(CommandRunnerImpl.java:562)
    at java.security.AccessController.doPrivileged(Native Method)
    at javax.security.auth.Subject.doAs(Subject.java:360)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:561)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.doCommand(CommandRunnerImpl.java:1469)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl.access00(CommandRunnerImpl.java:111)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1851)
    at com.sun.enterprise.v3.admin.CommandRunnerImpl$ExecutionContext.execute(CommandRunnerImpl.java:1727)
    at com.sun.enterprise.v3.admin.AdminAdapter.doCommand(AdminAdapter.java:534)
    at com.sun.enterprise.v3.admin.AdminAdapter.onMissingResource(AdminAdapter.java:224)
    at org.glassfish.grizzly.http.server.StaticHttpHandlerBase.service(StaticHttpHandlerBase.java:189)
    at com.sun.enterprise.v3.services.impl.ContainerMapper$HttpHandlerCallable.call(ContainerMapper.java:483)
    at com.sun.enterprise.v3.services.impl.ContainerMapper.service(ContainerMapper.java:180)
    at org.glassfish.grizzly.http.server.HttpHandler.runService(HttpHandler.java:206)
    at org.glassfish.grizzly.http.server.HttpHandler.doHandle(HttpHandler.java:180)
    at org.glassfish.grizzly.http.server.HttpServerFilter.handleRead(HttpServerFilter.java:235)
    at org.glassfish.grizzly.filterchain.ExecutorResolver.execute(ExecutorResolver.java:119)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeFilter(DefaultFilterChain.java:284)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.executeChainPart(DefaultFilterChain.java:201)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.execute(DefaultFilterChain.java:133)
    at org.glassfish.grizzly.filterchain.DefaultFilterChain.process(DefaultFilterChain.java:112)
    at org.glassfish.grizzly.ProcessorExecutor.execute(ProcessorExecutor.java:77)
    at org.glassfish.grizzly.nio.transport.TCPNIOTransport.fireIOEvent(TCPNIOTransport.java:539)
    at org.glassfish.grizzly.strategies.AbstractIOStrategy.fireIOEvent(AbstractIOStrategy.java:112)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.run0(WorkerThreadIOStrategy.java:117)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy.access0(WorkerThreadIOStrategy.java:56)
    at org.glassfish.grizzly.strategies.WorkerThreadIOStrategy$WorkerThreadRunnable.run(WorkerThreadIOStrategy.java:137)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.doWork(AbstractThreadPool.java:593)
    at org.glassfish.grizzly.threadpool.AbstractThreadPool$Worker.run(AbstractThreadPool.java:573)
    at java.lang.Thread.run(Thread.java:748)
Caused by: com.sun.enterprise.container.common.spi.util.InjectionException: Exception attempting to inject Local ejb-ref name=richtercloud.payara.classloading.proxy.issue.jar.Init/initService,Local 3.x interface =richtercloud.payara.classloading.proxy.issue.jar.InitService resolved to intra-app EJB DefaultInitService in module payara-classloading-proxy-issue-ejb-1.0-SNAPSHOT.jar,ejb-link=payara-classloading-proxy-issue-ejb-1.0-SNAPSHOT.jar#DefaultInitService,lookup=,mappedName=,jndi-name=,refType=Session into class richtercloud.payara.classloading.proxy.issue.jar.Init: Can not set richtercloud.payara.classloading.proxy.issue.jar.InitService field richtercloud.payara.classloading.proxy.issue.jar.Init.initService to com.sun.proxy.$Proxy254
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:740)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.inject(InjectionManagerImpl.java:507)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl.injectInstance(InjectionManagerImpl.java:170)
    at org.glassfish.weld.services.InjectionServicesImpl.aroundInject(InjectionServicesImpl.java:175)
    ... 68 more
Caused by: java.lang.IllegalArgumentException: Can not set richtercloud.payara.classloading.proxy.issue.jar.InitService field richtercloud.payara.classloading.proxy.issue.jar.Init.initService to com.sun.proxy.$Proxy254
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.lang.reflect.Field.set(Field.java:764)
    at com.sun.enterprise.container.common.impl.util.InjectionManagerImpl._inject(InjectionManagerImpl.java:688)
    ... 71 more

和 WildFly 由于

04:52:16,873 WARNING [org.omnifaces.cdi.eager.EagerBeansRepository] (ServerService Thread Pool -- 81) Could not instantiate eager application scoped beans. Possibly the CDI application scope is not active. This is known to be the case in certain Tomcat and Jetty based configurations.: java.lang.IllegalArgumentException: Can not set richtercloud.payara.classloading.proxy.issue.jar.InitService field richtercloud.payara.classloading.proxy.issue.jar.Init.initService to richtercloud.payara.classloading.proxy.issue.jar.InitService$$$view3
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:167)
    at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:171)
    at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:81)
    at java.lang.reflect.Field.set(Field.java:764)
    at org.jboss.weld.injection.FieldResourceInjection.injectMember(FieldResourceInjection.java:62)
    at org.jboss.weld.injection.AbstractResourceInjection.injectResourceReference(AbstractResourceInjection.java:63)
    at org.jboss.weld.util.Beans.injectEEFields(Beans.java:331)
    at org.jboss.weld.injection.producer.ResourceInjector.proceed(ResourceInjector.java:69)
    at org.jboss.weld.injection.InjectionContextImpl.run(InjectionContextImpl.java:48)
    at org.jboss.weld.injection.producer.ResourceInjector.inject(ResourceInjector.java:72)
    at org.jboss.weld.injection.producer.BasicInjectionTarget.inject(BasicInjectionTarget.java:117)
    at org.jboss.weld.bean.ManagedBean.create(ManagedBean.java:159)
    at org.jboss.weld.context.AbstractContext.get(AbstractContext.java:96)
    at org.jboss.weld.bean.ContextualInstanceStrategy$DefaultContextualInstanceStrategy.get(ContextualInstanceStrategy.java:100)
    at org.jboss.weld.bean.ContextualInstanceStrategy$ApplicationScopedContextualInstanceStrategy.get(ContextualInstanceStrategy.java:140)
    at org.jboss.weld.bean.ContextualInstance.get(ContextualInstance.java:50)
    at org.jboss.weld.bean.proxy.ContextBeanInstance.getInstance(ContextBeanInstance.java:99)
    at org.jboss.weld.bean.proxy.ProxyMethodHandler.getInstance(ProxyMethodHandler.java:125)
    at richtercloud.payara.classloading.proxy.issue.jar.Init$Proxy$_$$_WeldClientProxy.toString(Unknown Source)
    at org.omnifaces.cdi.eager.EagerBeansRepository.instantiateBeans(EagerBeansRepository.java:135)
    at org.omnifaces.cdi.eager.EagerBeansRepository.instantiateApplicationScoped(EagerBeansRepository.java:105)
    at org.omnifaces.cdi.eager.EagerBeansRepository$Proxy$_$$_WeldClientProxy.instantiateApplicationScoped(Unknown Source)
    at org.omnifaces.cdi.eager.EagerBeansRepository.instantiateApplicationScopedAndRegisterListenerIfNecessary(EagerBeansRepository.java:79)
    at org.omnifaces.ApplicationListener.contextInitialized(ApplicationListener.java:83)
    at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:187)
    at io.undertow.servlet.core.DeploymentManagerImpl.call(DeploymentManagerImpl.java:205)
    at io.undertow.servlet.core.DeploymentManagerImpl.call(DeploymentManagerImpl.java:174)
    at io.undertow.servlet.core.ServletRequestContextThreadSetupAction.call(ServletRequestContextThreadSetupAction.java:42)
    at io.undertow.servlet.core.ContextClassLoaderSetupAction.call(ContextClassLoaderSetupAction.java:43)
    at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create[=15=](SecurityContextThreadSetupAction.java:105)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=15=](UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=15=](UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=15=](UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=15=](UndertowDeploymentInfoService.java:1508)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create[=15=](UndertowDeploymentInfoService.java:1508)
    at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:239)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:99)
    at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.run(UndertowDeploymentService.java:81)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
    at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)
    at org.jboss.threads.JBossThread.run(JBossThread.java:320)

WAR 项目的 Maven 依赖项是

<dependency>
    <groupId>org.primefaces</groupId>
    <artifactId>primefaces</artifactId>
    <version>6.1</version>
</dependency>
<dependency>
    <groupId>richtercloud</groupId>
    <artifactId>payara-classloading-proxy-issue-jar</artifactId>
    <version>1.0-SNAPSHOT</version>
    <type>jar</type>
</dependency>
<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.omnifaces</groupId>
    <artifactId>omnifaces</artifactId>
    <version>2.6.7</version>
</dependency>

和 JAR

<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>eclipselink</artifactId>
    <version>2.5.2</version>
    <type>jar</type>
</dependency>
<dependency>
    <groupId>org.eclipse.persistence</groupId>
    <artifactId>org.eclipse.persistence.jpa.modelgen.processor</artifactId>
    <version>2.5.2</version>
</dependency>
<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-api</artifactId>
    <version>7.0</version>
    <scope>provided</scope>
</dependency>
<dependency>
    <groupId>org.apache.derby</groupId>
    <artifactId>derbyclient</artifactId>
    <version>10.14.1.0</version>
</dependency>

这是在 How to use OmniFaces @Eager annotation with PrimeFaces? 之前,但与 How to use OmniFaces @Eager annotation with PrimeFaces? 不同,因为在那个问题中,即使正确配置了日志记录,我也没有收到任何异常或其他反馈。

一个示例项目和 GitLab CI 输出在普通 docker 图像上重现问题可以通过参考问题轻松找到(不同分支上的不同 AS 和相应 [=50= 上的输出]管道部分)


[1] 在 https://github.com/payara/Payara/issues/2237 and https://github.com/javaee/glassfish/issues/22401 报告了一个更简化的示例,该示例也与代理 class 转换异常有关,但堆栈中没有焊接。

...Proxyclass强制转换异常问题是由 JAR 模块的 Maven compile 范围引起的(在包含 EJB 实现的 WEB 和 EJB 模块旁边包含实体和 EJB 接口)在 WEB 模块中。这会导致 EJB 接口 classes 被不同的 class 加载器加载(在这个 Java EE 设置中是正确的),因此根据定义它们被认为是不同的 class class 装载机的工作原理。

在 WEB 模块中将范围更改为 provided 可以避免此问题,没有任何缺点。

应用程序服务器(GlassFish 和 WildFly 以及可能的其他)的反馈与许多 (Java EE) 技术一样糟糕,我建议改进,尽管我明白黄金法则如果您的应用程序正常运行您已经完成了 20% 的工作,现在您需要处理剩余的 80% 以获得有用的反馈,在所有可能的情况下需要一些时间(即几十年)才能实现。