EAP 7.3:java.lang.ClassNotFoundException:# 在独立模式下才有的一个或多个许可证归Apache软件基金会所有

12

我们有一个Web应用程序(war),它在使用默认配置的情况下成功部署到JBoss EAP 7.3域模式下,但是在单机模式下(基于默认standalone.xml配置)部署失败,并出现以下错误:

14:47:40,342 ERROR [org.jboss.msc.service.fail] (ServerService Thread Pool -- 88) MSC000001: Failed to start service jboss.deployment.unit."app.war".undertow-deployment: org.jboss.msc.service.StartException in service jboss.deployment.unit."app.war".undertow-deployment: java.lang.RuntimeException: javax.el.ELException: Provider # Licensed to the Apache Software Foundation (ASF) under one or more not found
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:81)
        at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
        at java.util.concurrent.FutureTask.run(FutureTask.java:266)
        at org.jboss.threads.ContextClassLoaderSavingRunnable.run(ContextClassLoaderSavingRunnable.java:35)
        at org.jboss.threads.EnhancedQueueExecutor.safeRun(EnhancedQueueExecutor.java:1982)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.doRunTask(EnhancedQueueExecutor.java:1486)
        at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1377)
        at java.lang.Thread.run(Thread.java:748)
        at org.jboss.threads.JBossThread.run(JBossThread.java:485)
Caused by: java.lang.RuntimeException: javax.el.ELException: Provider # Licensed to the Apache Software Foundation (ASF) under one or more not found
        at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:254)
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentService.startContext(UndertowDeploymentService.java:96)
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentService$1.run(UndertowDeploymentService.java:78)
        ... 8 more
Caused by: javax.el.ELException: Provider # Licensed to the Apache Software Foundation (ASF) under one or more not found
        at javax.el.FactoryFinder.newInstance(FactoryFinder.java:64)
        at javax.el.FactoryFinder.find(FactoryFinder.java:103)
        at javax.el.ExpressionFactory.newInstance(ExpressionFactory.java:140)
        at javax.el.ELUtil.getExpressionFactory(ELUtil.java:185)
        at javax.el.ELManager.getExpressionFactory(ELManager.java:38)
        at org.apache.jasper.runtime.JspApplicationContextImpl.<init>(JspApplicationContextImpl.java:49)
        at org.apache.jasper.runtime.JspApplicationContextImpl.getInstance(JspApplicationContextImpl.java:78)
        at org.apache.jasper.runtime.JspFactoryImpl.getJspApplicationContext(JspFactoryImpl.java:218)
        at org.wildfly.extension.undertow.deployment.JspInitializationListener.contextInitialized(JspInitializationListener.java:51)
        at io.undertow.servlet.core.ApplicationListeners.contextInitialized(ApplicationListeners.java:187)
        at io.undertow.servlet.core.DeploymentManagerImpl$1.call(DeploymentManagerImpl.java:217)
        at io.undertow.servlet.core.DeploymentManagerImpl$1.call(DeploymentManagerImpl.java:186)
        at io.undertow.servlet.core.ServletRequestContextThreadSetupAction$1.call(ServletRequestContextThreadSetupAction.java:42)
        at io.undertow.servlet.core.ContextClassLoaderSetupAction$1.call(ContextClassLoaderSetupAction.java:43)
        at org.wildfly.extension.undertow.security.SecurityContextThreadSetupAction.lambda$create$0(SecurityContextThreadSetupAction.java:105)
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
        at org.wildfly.extension.undertow.deployment.UndertowDeploymentInfoService$UndertowThreadSetupAction.lambda$create$0(UndertowDeploymentInfoService.java:1504)
        at io.undertow.servlet.core.DeploymentManagerImpl.deploy(DeploymentManagerImpl.java:252)
        ... 10 more
Caused by: java.lang.ClassNotFoundException: # Licensed to the Apache Software Foundation (ASF) under one or more from [Module "deployment.app.war" from Service Module Loader]
        at org.jboss.modules.ModuleClassLoader.findClass(ModuleClassLoader.java:255)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClassUnchecked(ConcurrentClassLoader.java:410)
        at org.jboss.modules.ConcurrentClassLoader.performLoadClass(ConcurrentClassLoader.java:398)
        at org.jboss.modules.ConcurrentClassLoader.loadClass(ConcurrentClassLoader.java:116)
        at javax.el.FactoryFinder.newInstance(FactoryFinder.java:48)
        ... 29 more

14:47:40,351 ERROR [org.jboss.as.controller.management-operation] (Controller Boot Thread) WFLYCTL0013: Operation ("deploy") failed - address: ([("deployment" => "app.war")]) - failure description: {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"app.war\".undertow-deployment" => "java.lang.RuntimeException: javax.el.ELException: Provider # Licensed to the Apache Software Foundation (ASF) under one or more not found
    Caused by: java.lang.RuntimeException: javax.el.ELException: Provider # Licensed to the Apache Software Foundation (ASF) under one or more not found
    Caused by: javax.el.ELException: Provider # Licensed to the Apache Software Foundation (ASF) under one or more not found
    Caused by: java.lang.ClassNotFoundException: # Licensed to the Apache Software Foundation (ASF) under one or more from [Module \"deployment.app.war\" from Service Module Loader]"}}

在这两种情况下,战争和应用程序配置是相同的。

JBoss配置在两种情况下尽可能接近。在域模式下,它基于默认配置文件配置,并仅添加了一些资源。在独立模式下,它基于默认的standalone.xml配置文件,并添加了相同的一组资源。因此,从这个角度来看,我找不到导致行为差异的任何原因。

到目前为止,我们已经跟踪到 tomcat-embed-el-9.0.39.jar 这个JAR包由于某些第三方依赖而包含在我们的WAR包中。这个JAR包包含一个名为META-INF/services/javax.el.ExpressionFactory 的文件,其中包含以下内容:

# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

org.apache.el.ExpressionFactoryImpl

问题显然是第一行被读取并处理为实际条目(例如类名),尽管它只是一条注释。 因此,这类似于影响 EAP 6 的以下旧问题: https://access.redhat.com/solutions/1270603(需要 Red Hat 登录)。

但奇怪的是,这仅在独立模式下发生。 这可以被视为一个错误吗?

注意:我们在 JBoss EAP 7.3.0 和 7.3.6 上进行了测试,结果相同。


你尝试过排除那个库吗?JBoss EAP自带一个EL实现。 - James R. Perkins
是的,那么它当然会成功部署。然而,我的主要关注点是:
  1. 独立模式和域模式之间存在奇怪的差异。
  2. 该注释被错误地读作实际内容。
- Petr H
当您部署到域时,您是否正在部署到活动服务器?至于为什么评论被读取,那看起来像是EL工厂的问题。 - James R. Perkins
是的,我们通常会在目标服务器停止时重新部署,但我刚刚尝试了对正在运行的服务器进行干净的部署,它仍然成功完成(在域中)。 - Petr H
那肯定很奇怪。它应该通过所有的处理器进行处理。 - James R. Perkins
我不能确切地给出答案,但我遇到了一个类似的问题,即将Spring Boot 2.5应用程序部署到Wildfly 23。该问题的直接原因似乎是Tomcat EL实现违反了https://docs.oracle.com/javaee/7/api/javax/el/ExpressionFactory.html#newInstance--中规范所述的规范,其中说:使用服务API(如JAR规范中详细说明)。如果存在名称为META-INF / services / javax.el.ExpressionFactory的资源,则其第一行(如果存在)将用作实现类的UTF-8编码名称。而它的第一行是Apache文本。 - stevestorey
2个回答

3
这是ExpressionFactory实现和ExpressionFactory提供程序文件(META-INF/services/javax.el.ExpressionFactory)之间的错误/不匹配。 ExpressionFactory.newInstance()方法应该使用JAR服务API来查找实现类的名称:

使用服务API(如JAR规范中所述)。如果存在一个名为META-INF/services/javax.el.ExpressionFactory的资源,则使用它的第一行(如果存在)作为实现类的UTF-8编码名称。

这个描述有些含糊/不一致:
  • 它声称应该使用文件的第一行作为类名;
  • 另一方面,它说应该使用预计忽略注释的服务API。
在反编译我的ExpressionFactory实现时,我发现:
private static String getClassNameServices(final ClassLoader tccl) {
  InputStream is = null;
  if (tccl == null) {
    is = ClassLoader.getSystemResourceAsStream("META-INF/services/javax.el.ExpressionFactory");
  }
  else {
    is = tccl.getResourceAsStream("META-INF/services/javax.el.ExpressionFactory");
  }
  if (is != null) {
    String line = null;
    BufferedReader br = null;
    InputStreamReader isr = null;
    try {
      isr = new InputStreamReader(is, "UTF-8");
      br = new BufferedReader(isr);
      line = br.readLine();
      if (line != null && line.trim().length() > 0) {
        return line.trim();
      }
    }
    // [...]
  }
}

此实现不会忽略注释。 我的 META-INF/services/javax.el.ExpressionFactory(在 jasper-el.jar 中) 看起来实际上像这样:
# Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with
# the License.  You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

org.apache.el.ExpressionFactoryImpl 

因此,它试图加载一个名为“# Licensed to the Apache Software Foundation (ASF) under one or more”的类,但失败了。
相关的错误是bug 64097,修复方法在commit 9ed78bcc80565292cd9a343f4e6d0c2db305494e中找到。
一个(可怕的)快速修复方法是像这样打补丁META-INF/services/javax.el.ExpressionFactory文件:
mkdir -p META-INF/services/
echo org.apache.el.ExpressionFactoryImpl > META-INF/services/javax.el.ExpressionFactory
7z d ./jasper-el.jar META-INF/services/javax.el.ExpressionFactory
jar uf ./jasper-el.jar META-INF/services/javax.el.ExpressionFactory

感谢您指出正确的方向。 我刚遇到了本地Tomcat版本9.0.21的不愉快问题。最简单的解决方法就是将Tomcat升级到最新版本9.0.63,问题得以解决。 - informatik01

2
升级到Tomcat 9.0.63解决了这个问题。
用户informatik01另一个答案上的评论让我走上了这条路——感谢他们!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接