tomcat 如何通过Maven正确地安装和配置JSF库?

thtygnil  于 2022-11-13  发布在  Maven
关注(0)|答案(1)|浏览(158)

我正在尝试将一个基于JSF的应用程序部署到Tomcat 6。按照我的构建系统的设置方式,WAR本身没有任何库,因为该服务器总共为43个应用程序提供服务。相反,这些库被复制到一个共享库文件夹中,并在应用程序之间共享。当我进行部署时,出现以下错误

SEVERE: Error deploying configuration descriptor SSOAdmin.xml
java.lang.ClassFormatError: Absent Code attribute in method that is not native or abstract in class file javax/faces/webapp/FacesServlet
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.lang.ClassLoader.defineClassCond(ClassLoader.java:631)
    at java.lang.ClassLoader.defineClass(ClassLoader.java:615)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:141)
    at java.net.URLClassLoader.defineClass(URLClassLoader.java:283)
    at java.net.URLClassLoader.access$000(URLClassLoader.java:58)
    at java.net.URLClassLoader$1.run(URLClassLoader.java:197)
    at java.security.AccessController.doPrivileged(Native Method)
    at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1667)
    at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
    at org.apache.catalina.startup.WebAnnotationSet.loadApplicationServletAnnotations(WebAnnotationSet.java:108)
    at org.apache.catalina.startup.WebAnnotationSet.loadApplicationAnnotations(WebAnnotationSet.java:58)
    at org.apache.catalina.startup.ContextConfig.applicationAnnotationsConfig(ContextConfig.java:297)
    at org.apache.catalina.startup.ContextConfig.start(ContextConfig.java:1078)
    at org.apache.catalina.startup.ContextConfig.lifecycleEvent(ContextConfig.java:261)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
    at org.apache.catalina.core.StandardContext.start(StandardContext.java:4611)
    at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:799)
    at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:779)
    at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:601)
    at org.apache.catalina.startup.HostConfig.deployDescriptor(HostConfig.java:675)
    at org.apache.catalina.startup.HostConfig.deployDescriptors(HostConfig.java:601)
    at org.apache.catalina.startup.HostConfig.deployApps(HostConfig.java:502)
    at org.apache.catalina.startup.HostConfig.start(HostConfig.java:1315)
    at org.apache.catalina.startup.HostConfig.lifecycleEvent(HostConfig.java:324)
    at org.apache.catalina.util.LifecycleSupport.fireLifecycleEvent(LifecycleSupport.java:142)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1061)
    at org.apache.catalina.core.StandardHost.start(StandardHost.java:840)
    at org.apache.catalina.core.ContainerBase.start(ContainerBase.java:1053)
    at org.apache.catalina.core.StandardEngine.start(StandardEngine.java:463)
    at org.apache.catalina.core.StandardService.start(StandardService.java:525)
    at org.apache.catalina.core.StandardServer.start(StandardServer.java:754)
    at org.apache.catalina.startup.Catalina.start(Catalina.java:595)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.apache.catalina.startup.Bootstrap.start(Bootstrap.java:289)
    at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:414)

现在,在我的研究中,我发现这个问题应该通过下载JSF源代码并自己编译来解决。在我的情况下,这是一个糟糕的解决方案。这将给我的团队带来巨大的问题,我们必须应对各种配置。有没有其他解决方案?
下面是我的pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.nms.sso</groupId>
  <artifactId>SSOAdmin</artifactId>
  <version>09142011-BETA</version>
  <packaging>war</packaging>
  <dependencies>
    <dependency>
      <groupId>asm</groupId>
      <artifactId>asm</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>cglib</groupId>
      <artifactId>cglib</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <!-- <dependency> -->
    <!-- <groupId>com.sun.faces</groupId> -->
    <!-- <artifactId>jsf-api</artifactId> -->
    <!-- <scope>${myExeScope}</scope> -->
    <!-- </dependency> -->
    <!-- <dependency> -->
    <!-- <groupId>com.sun.faces</groupId> -->
    <!-- <artifactId>jsf-impl</artifactId> -->
    <!-- <scope>${myExeScope}</scope> -->
    <!-- </dependency> -->
    <dependency>
      <groupId>commons-codec</groupId>
      <artifactId>commons-codec</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>javax</groupId>
      <artifactId>javaee-api</artifactId>
      <version>6.0</version>
      <scope>provided</scope>
    </dependency>
    <dependency>
      <groupId>javax.faces</groupId>
      <artifactId>javax.faces-api</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>net.sf.jt400</groupId>
      <artifactId>jt400</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>nmsc</groupId>
      <artifactId>nmsc_api</artifactId>
      <version>09142011-BETA</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.icefaces</groupId>
      <artifactId>icefaces</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.icefaces</groupId>
      <artifactId>icefaces-ace</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.icefaces</groupId>
      <artifactId>icefaces-compat</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.javassist</groupId>
      <artifactId>javassist</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.jibx</groupId>
      <artifactId>jibx-extras</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.jibx</groupId>
      <artifactId>jibx-run</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-context</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-orm</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-tx</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework</groupId>
      <artifactId>spring-web</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
    <dependency>
      <groupId>postgresql</groupId>
      <artifactId>postgresql</artifactId>
      <scope>${myExeScope}</scope>
    </dependency>
  </dependencies>
  <parent>
    <groupId>nmsc</groupId>
    <artifactId>nmsc_lib</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <relativePath>../libs</relativePath>
  </parent>
  <build>
    <finalName>SSOAdmin</finalName>
  </build>
  <name>SSOAdmin Maven Webapp</name>
</project>

这里必须有一个解决方案。我一点也不相信Maven distributable for JSF只适合编译而不适合部署。

4uqofj5v

4uqofj5v1#

当您遇到一个“奇怪”的异常,表明类/方法/文件/组件/标记不存在或不同,而它们似乎显式地包含在Web应用程序中,如下面所示,
java.lang.ClassFormatError:在类文件javax/faces/webapp/FacesServlet中,方法中缺少不是本机或抽象的代码属性
资源丢失异常:找不到javax.faces.logStrings包
无法将WebContainerInjectionProvider强制转换为
com.sun.faces.config.ConfigurationException:配置失败
命名空间www.example.com中名为inputFile的标记http://xmlns.jcp.org/jsf/html定义了空的处理程序类。
在运行时出现异常错误。
在javax.faces.application.视图处理程序 Package 器中出现错误
异常错误发生在服务器上。
或者当您面临“奇怪”的运行时行为(如中断的HTTP会话(jsessionid出现在所有位置的链接URL中)和/或中断的JSF视图作用域(它的行为与请求作用域相同)和/或中断的CSS/JS/图像资源)时,则Web应用程序的运行时类路径很可能被重复的不同版本的JAR文件污染。
FacesServlet上使用ClassFormatError的特定情况下,这意味着第一次发现的包含上述类的JAR文件实际上是一个“蓝图”APIJAR文件,旨在用于实现供应商(例如为Mojarra和MyFaces工作的开发人员)。它包含只有类和方法签名的类文件,没有任何代码体和资源文件。这正是“缺少代码属性”的意思。它纯粹是为了javadoc和编译。

始终将服务器提供的库标记为provided

所有在Maven中标记为“Java Specifications“并且在工件ID中具有-api后缀的依赖项都是蓝图API。您绝对不应该在运行时类路径中包含它们。如果您真的需要在pom中包含它们,您应该始终将它们标记为<scope>provided</scope>。一个著名的例子是Jakarta EE (Web) API(以前称为Java EE):

<dependency>
    <groupId>jakarta.platform</groupId>
    <artifactId>jakarta.jakartaee-api</artifactId>
    <version><!-- 8.0.0 or 9.0.0 or 9.1.0 or newer --></version>
    <scope>provided</scope>
</dependency>

如果没有provided作用域,那么这个JAR将在webapp的/WEB-INF/lib中结束,从而导致您现在所面临的所有麻烦。
在您的特定案例中,您有一个不必要的JSF API相依性:

<dependency>
    <groupId>jakarta.faces</groupId>
    <artifactId>jakarta.faces-api</artifactId>
</dependency>

这会造成问题,因为它包含FacesServlet的蓝图类。删除它并依赖如上所示的provided Jakarta EE(Web)API应该可以解决这个问题。
Tomcat作为一个准系统的JSP/Servlet容器已经提供了JSP、Servlet和EL(因为8也提供了WebSocket)。所以你应该至少将jsp-apiservlet-apiel-api标记为provided。Tomcat只是不提供JSF(和JSTL)。所以你需要通过webapp安装它。
成熟的Jakarta EE服务器(如WildFly、TomEE、GlassFish、Payara、WebSphere等)已经提供了开箱即用的整个Jakarta EE API,包括JSF。因此您绝对不需要通过webapp安装JSF。如果服务器已经提供了不同的实现和/或现成的版本,这只会导致冲突。您需要的唯一依赖项是jakartaee-api,与上面所示完全相同。

在Tomcat 10或更高版本上安装JSF

您需要的最低JSF版本是3.0而不是2.3,因为javax.*包从3.0开始就被重命名为jakarta.*
在Tomcat 10或更高版本上安装Mojarra 3.0:

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>jakarta.faces</artifactId>
    <version><!-- Check https://eclipse-ee4j.github.io/mojarra --></version>
</dependency>

您也可以检查org.glassfish:jakarta.faces repository以取得目前最新的3.0.x出版版本(目前是3.0.2)。另请参阅Mojarra installation instructions以取得其他必要的相依性(CDI、BV、JSONP)。
在Tomcat 10或更高版本上安装MyFaces 3.0:

<dependency>
    <groupId>org.apache.myfaces.core</groupId>
    <artifactId>myfaces-impl</artifactId>
    <version><!-- Check http://myfaces.apache.org --></version>
</dependency>

您也可以检查org.apache.myfaces.core:myfaces-impl repository,了解当前最新的3.0.x发行版本(当前为3.0.2)。
顺便说一句,不要忘记安装JSTL API,Tomcat中也没有。

<dependency>
    <groupId>jakarta.servlet.jsp.jstl</groupId>
    <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
    <version>2.0.0</version>
</dependency>

另外请注意,从JSF 2.3开始,CDI已经成为一个必需的依赖项。这在普通的Jakarta EE服务器上是现成的,但在servlet容器(如Tomcat)上却不是。在这种情况下,请转到如何在Tomcat上安装和使用CDI?

在Tomcat 9或更早版本上安装JSF

有两种JSF实现:Mojarra and MyFaces。您应该选择安装其中一个,而不是两个都安装。
在Tomcat 9或更早版本上安装Mojarra 2.3:

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>jakarta.faces</artifactId>
    <version><!-- Check https://eclipse-ee4j.github.io/mojarra --></version>
</dependency>

您也可以检查org.glassfish:jakarta.faces repository以取得目前最新的2.3.x出版版本(目前是2.3.16)。另请参阅Mojarra installation instructions以取得其他必要的相依性(CDI、BV、JSONP)。
在Tomcat 9或更早版本上安装MyFaces 2.3:

<dependency>
    <groupId>org.apache.myfaces.core</groupId>
    <artifactId>myfaces-impl</artifactId>
    <version><!-- Check http://myfaces.apache.org --></version>
</dependency>

您也可以检查org.apache.myfaces.core:myfaces-impl repository,了解当前最新的2.3.x发行版本(当前为2.3.9)。
请注意,Tomcat 6作为Servlet 2.5容器支持最高JSF 2.1。
顺便说一句,不要忘记安装JSTL API,Tomcat中也没有。

<dependency>
    <groupId>jakarta.servlet.jsp.jstl</groupId>
    <artifactId>jakarta.servlet.jsp.jstl-api</artifactId>
    <version>1.2.7</version>
</dependency>

另外请注意,从JSF 2.3开始,CDI已经成为一个必需的依赖项。这在普通的Jakarta EE服务器上是现成的,但在servlet容器(如Tomcat)上却不是。在这种情况下,请转到如何在Tomcat上安装和使用CDI?

另请参阅:

相关问题