¿Cómo instalar y configurar correctamente las bibliotecas JSF a través de Maven?

Resuelto scphantm asked hace 12 años • 1 respuestas

Estoy intentando implementar una aplicación basada en JSF en Tomcat 6. Por la forma en que está configurado mi sistema de compilación, WAR en sí no tiene bibliotecas, porque este servidor sirve un total de 43 aplicaciones. En cambio, las bibliotecas se copian en una carpeta de biblioteca compartida y se comparten entre las aplicaciones. Cuando lo implemento, aparece este error

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)

Ahora, en mi investigación, veo que se supone que esto se resuelve descargando el código fuente JSF y compilándolo yo mismo. Esa es una solución horrible en mi caso. Eso causará grandes problemas en mi equipo con las diversas configuraciones con las que tendremos que lidiar. ¿Existe otra solución para esto?

Aquí está mi 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>

Tiene que haber una solución aquí. No puedo creer ni por un segundo que Maven distribuible para JSF solo sea bueno para compilar y no para implementación.

scphantm avatar Nov 10 '11 21:11 scphantm
Aceptado

Cuando se enfrenta a una excepción "extraña" que sugiere que las clases/métodos/archivos/componentes/etiquetas están ausentes o son diferentes mientras aparentemente están incluidos explícitamente en la aplicación web, como las que se muestran a continuación,

java.lang.ClassFormatError: atributo de código ausente en un método que no es nativo ni abstracto en el archivo de clase javax/faces/webapp/FacesServlet

java.util.MissingResourceException: no se puede encontrar el paquete javax.faces.LogStrings

com.sun.faces.vendor.WebContainerInjectionProvider no se puede transmitir a com.sun.faces.spi.InjectionProvider

com.sun.faces.config.ConfigurationException: FALLÓ LA CONFIGURACIÓN

La etiqueta denominada inputFile del espacio de nombres http://xmlns.jcp.org/jsf/html tiene una clase de controlador nula definida.

java.lang.NullPointerException en javax.faces.CurrentThreadToServletContext.getFallbackFactory

java.lang.AbstractMethodError en javax.faces.application.ViewHandlerWrapper.getWebsocketURL

java.lang.NullPointerException en com.sun.faces.config.InitFacesContext.cleanupInitMaps

o cuando se enfrenta a un comportamiento de tiempo de ejecución "extraño", como sesiones HTTP rotas ( jsessionidaparecen en las URL de los enlaces en todas partes) y/o alcance de vista de Caras roto (se comporta como un alcance de solicitud) y/o CSS/JS/imagen roto recursos, entonces existe una gran posibilidad de que el classpath de tiempo de ejecución de la aplicación web esté contaminado con archivos JAR duplicados con diferentes versiones.

En su caso específico con el ClassFormatErroren FacesServlet, significa que el archivo JAR que contiene la clase mencionada se encontró por primera vez es en realidad un archivo JAR API "modelo", destinado a proveedores de implementación (como desarrolladores que trabajan para Mojarra y MyFaces) . Contiene archivos de clase con firmas de clases y métodos únicamente, sin cuerpos de código ni archivos de recursos. Eso es exactamente lo que significa "atributo de código ausente". Está destinado exclusivamente a javadocs y compilación.

Marque siempre las bibliotecas proporcionadas por el servidor comoprovided

Todas las dependencias marcadas como " Especificaciones de Java " en Maven y que tienen -apiun sufijo en el ID del artefacto son esas API de modelo. No deberías tenerlos en absoluto en el classpath del tiempo de ejecución. Siempre debes marcarlos <scope>provided</scope>si realmente necesitas tenerlo en tu pompón. Un ejemplo bien conocido es la API Jakarta EE (Web) (anteriormente conocida como 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 10.0.0 or newer --></version>
    <scope>provided</scope>
</dependency>

Si el providedalcance está ausente, entonces este JAR terminará en la aplicación web /WEB-INF/lib, causando todos los problemas que enfrenta ahora. Este JAR también contiene la clase de modelo de FacesServlet.

En su caso específico, tiene una dependencia innecesaria de Faces API :

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

Esto está causando problemas porque contiene la clase de modelo de FacesServlet. Eliminarlo y confiar en una providedAPI Jakarta EE (Web) como se muestra arriba debería resolverlo.

Tomcat, como contenedor JSP/Servlet básico, ya proporciona JSP, Servlet y EL (y desde 8 también WebSocket) listos para usar. Por lo tanto, debes marcar al menos jsp-api, servlet-apiy el-apicomo provided. Tomcat solo no proporciona Faces (ni JSTL ) listos para usar. Entonces necesitarás instalarlo a través de la aplicación web.

Los servidores completos de Jakarta EE, como WildFly, TomEE, GlassFish, Payara, WebSphere, etc., ya proporcionan toda la API de Jakarta EE lista para usar, incluido Faces. Por lo tanto, no es necesario instalar Faces a través de la aplicación web. Solo resultaría en conflictos si el servidor ya proporciona una implementación y/o versión diferente lista para usar. La única dependencia que necesita es jakartaee-apiexactamente como se muestra aquí arriba.

Consulte también ¿Cómo configurar correctamente las bibliotecas Jakarta EE en Maven pom.xml para Tomcat? para obtener explicaciones más detalladas y ejemplos de pom.xmlTomcat 10 y 9.

Instalación de Faces en Tomcat 10 o posterior

Tomcat 10.0.x es la primera versión que utiliza jakarta.*paquete en lugar de javax.*paquete. Por lo tanto, para Tomcat 10.0.x necesitará un mínimo de Faces 3.0 en lugar de 2.3 porque el javax.*nombre del paquete se cambió a jakarta.*Faces 3.0 únicamente. En caso de que tenga Tomcat 10.1.x, necesitará una versión mínima de Faces 4.0.

Hay dos implementaciones de Faces: Mojarra y MyFaces . Deberías optar por instalar uno de ellos y, por tanto, no ambos.

Instalación de Mojarra 3.0 o 4.0 en Tomcat 10 o posterior:

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

También puede consultar org.glassfish:jakarta.facesel repositorio para conocer la última versión actual 3.0.x o 4.0.x (que actualmente es 3.0.5y 4.0.3). Consulte también las instrucciones de instalación de Mojarra para otras dependencias necesarias (CDI, BV, JSONP).

Instalación de MyFaces 3.0 o 4.0 en Tomcat 10 o posterior:

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

También puede consultar org.apache.myfaces.core:myfaces-implel repositorio para conocer la última versión actual 3.0.x o 4.0.x (que actualmente es 3.0.2y 4.0.1).

Por cierto, no olvides instalar al menos la API JSTL. Esto también está ausente en Tomcat.

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

No, no necesariamente necesita la implementación JSTL como se indica en ¿ Cómo instalar JSTL? El uri absoluto: http://java.sun.com/jstl/core no se puede resolver . Esto sólo es necesario cuando también desea utilizar JSTL en archivos JSP. Facelets tiene su propia implementación JSTL incorporada. En caso de que desee utilizar Facelets y JSP, elimine la dependencia de la API JSTL e instale la implementación JSTL como se indica en el enlace mencionado anteriormente.

También tenga en cuenta que desde Faces 2.3, CDI se ha convertido en una dependencia obligatoria. Esto está disponible de fábrica en servidores normales de Yakarta EE, pero no en contenedores de servlet como Tomcat. En este caso, diríjase a ¿Cómo instalar y usar CDI en Tomcat?

Para ser claros, después de haber instalado la implementación de Faces Mojarra o MyFaces, no es necesario declarar la jakarta.faces-apidependencia por separado. Esto ya está incluido transitivamente a través de la implementación.

Instalación de Faces en Tomcat 9 o anterior

Solo puede usar como máximo Faces 2.3 en Tomcat 9 o anterior porque es la última versión que todavía usa javax.*el paquete.

Instalación de Mojarra 2.3 en Tomcat 9 o anterior:

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

También puede consultar org.glassfish:jakarta.facesel repositorio para conocer la última versión 2.3.x actual (que actualmente es 2.3.20). Consulte también las instrucciones de instalación de Mojarra para otras dependencias necesarias (CDI, BV, JSONP).

Instalación de MyFaces 2.3 en Tomcat 9 o anterior:

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

También puede consultar org.apache.myfaces.core:myfaces-implel repositorio para conocer la última versión 2.3.x actual (que actualmente es 2.3.10).

Tenga en cuenta que Tomcat 6, como contenedor de Servlet 2.5, admite como máximo Faces 2.1.

Por cierto, no olvides instalar la API JSTL. Esto también está ausente en Tomcat.

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

También tenga en cuenta que desde Faces 2.3, CDI se ha convertido en una dependencia obligatoria. Esto está disponible de fábrica en servidores normales de Yakarta EE, pero no en contenedores de servlet como Tomcat. En este caso, diríjase a ¿Cómo instalar y usar CDI en Tomcat?

Ver también:

  • ¿Qué es exactamente Java EE/Jakarta EE?
  • ¿Cómo instalar JSTL en Tomcat a través de Maven?
  • ¿Cómo instalar CDI en Tomcat a través de Maven?
  • FacesServlet devuelve una página en blanco/sin analizar
BalusC avatar Nov 10 '2011 14:11 BalusC