Как правильно установить и настроить библиотеки 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.