Как правильно установить и настроить библиотеки JSF через Maven?

Я пытаюсь развернуть приложение на основе 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 для JSF хорош только для компиляции и не подходит для развертывания.

1 ответ

Решение

Когда вы сталкиваетесь со "странным" исключением, предполагающим, что классы / методы / файлы / компоненты / теги отсутствуют или отличаются, в то время как они явно явно включены в веб-приложение, такое как приведенные ниже,

java.lang.ClassFormatError: отсутствует атрибут кода в методе, который не является нативным или абстрактным в файле класса javax/ Faces/ WebApp / FacesServlet

java.util.MissingResourceException: не удается найти пакет javax.faces.LogStrings

com.sun.faces.vendor.WebContainerInjectionProvider не может быть приведен к com.sun.faces.spi.InjectionProvider

com.sun.faces.config.ConfigurationException: CONFIGURATION FAILED

Для тега с именем inputFile из пространства имен http://xmlns.jcp.org/jsf/html определен нулевой класс обработчика.

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

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

или когда вы сталкиваетесь со "странным" поведением во время выполнения, таким как прерванные сеансы HTTP (jsessionid появляется в URL-адресах ссылок повсюду), и / или поврежденной области просмотра JSF (она ведет себя как область запроса), и / или поврежденных ресурсах CSS/JS/image, тогда велика вероятность того, что путь к классам во время выполнения веб-приложения будет загрязнен дубликатами, версионные файлы JAR.

В вашем конкретном случае с ClassFormatError на FacesServlet, это означает, что файл JAR, содержащий упомянутый класс, был найден впервые, на самом деле является файлом JAR API "плана", предназначенным для поставщиков реализации (таких как разработчики, работающие на Mojarra и MyFaces). Он содержит файлы классов только с сигнатурами классов и методов, без каких-либо тел кода и файлов ресурсов. Это именно то, что означает "отсутствующий атрибут кода". Это чисто предназначено для javadocs и компиляции.

Всегда отмечать предоставленные сервером библиотеки как provided

Все зависимости отмечены как " Спецификации Java" в Maven и имеют -api суффикс в идентификаторе артефакта - это те же API-интерфейсы чертежей. Вы абсолютно не должны иметь их в classpath времени выполнения. Вы должны всегда отмечать их <scope>provided</scope> если вам действительно нужно иметь его в помпе. Хорошо известным примером является API Java EE (Web):

<dependency>
    <groupId>javax</groupId>
    <artifactId>javaee-web-api</artifactId>
    <version><!-- 6.0 or 7.0 or newer --></version>
    <scope>provided</scope>
</dependency>

Если provided область действия отсутствует, тогда этот JAR будет в конечном итоге в веб-приложения /WEB-INF/lib, вызывая все проблемы, с которыми вы сталкиваетесь сейчас. Этот JAR также содержит класс проекта FacesServlet,

В вашем конкретном случае у вас есть ненужная зависимость JSF API:

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

Это вызывает проблемы, потому что это содержит класс проекта FacesServlet, Удаление этого и полагаясь на provided Java EE (Web) API, как показано выше, должно решить эту проблему.

Tomcat, являясь базовым контейнером JSP/Servlet, уже предоставляет JSP, Servlet и EL (а с 8 также WebSocket) из коробки. Так что стоит пометить хотя бы jsp-api, servlet-api, а также el-api как provided, Tomcat только не предоставляет JSF (и JSTL) из коробки. Так что вам нужно установить его через веб-приложение.

Полноценные серверы Java EE, такие как WildFly, TomEE, GlassFish, Payara, WebSphere и т. Д., Уже предоставляют полный комплект API Java EE, включая JSF. Таким образом, вам абсолютно не нужно устанавливать JSF через веб-приложение. Это приведет только к конфликтам, если сервер уже предоставляет другую реализацию и / или версию из коробки. Единственная зависимость, которая вам нужна, это javaee-web-api именно так, как показано здесь выше.

Установка JSF на Tomcat

Правильный способ установки JSF в Tomcat упоминается в нашей вики JSF - Установка JSF. Есть 2 реализации JSF, Mojarra и MyFaces. Вы должны установить один из них, а не оба.

Установка Mojarra на Tomcat:

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>javax.faces</artifactId>
    <version><!-- Check https://javaserverfaces.github.io --></version>
</dependency>

Вы также можете проверить org.glassfish:javax.faces хранилище для текущей последней версии выпуска (которая в настоящее время 2.2.13). Смотрите также инструкции по установке Mojarra.

Установка MyFaces на Tomcat:

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

Вы также можете проверить org.apache.myfaces.core:myfaces-bundle хранилище для текущей последней версии выпуска (которая в настоящее время 2.2.10).

Обратите внимание, что Tomcat 6 как контейнер Servlet 2.5 поддерживает максимум JSF 2.1. Кстати, не забудьте установить JSTL. Смотрите также нашу вики JSF - Установка JSF.

Смотрите также:

Другие вопросы по тегам