Struts2 не может инициализировать Dispatcher в войне исполняемых файлов — Embedded Tomcat

Я переношу веб-приложение с JBoss на Embedded Tomcat. Он работает на intellij, но когда я запускаю файл war с java -jar myapplication.war, он показывает следующую ошибку. Погуглив, я не нашел решения. Эта проблема выглядит так, будто у меня есть две банки struts2-core или некоторые конфликтующие зависимости, но у меня есть только одна банка.

Пример проекта здесь.

Ошибка:

 2017-12-11 10:58:24.527 ERROR 10296 --- [nio-8080-exec-1] o.apache.struts2.dispatcher.Dispatcher   : Dispatcher initialization failed
 
 com.opensymphony.xwork2.config.ConfigurationException: Unable to load configuration.
         at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:70) ~[xwork-core-2.3.34.jar!/:2.3.34]
         at org.apache.struts2.dispatcher.Dispatcher.getContainer(Dispatcher.java:978) ~[struts2-core-2.3.34.jar!/:2.3.34]
         at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:446) ~[struts2-core-2.3.34.jar!/:2.3.34]
         at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:490) ~[struts2-core-2.3.34.jar!/:2.3.34]
         at org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:74) [struts2-core-2.3.34.jar!/:2.3.34]
         at org.apache.struts2.dispatcher.ng.servlet.StrutsServlet.init(StrutsServlet.java:54) [struts2-core-2.3.34.jar!/:2.3.34]
         at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1183) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.catalina.core.StandardWrapper.allocate(StandardWrapper.java:795) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:133) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:478) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:80) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:342) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:799) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1455) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0_131]
         at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0_131]
         at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61) [tomcat-embed-core-8.5.14.jar!/:8.5.14]
         at java.lang.Thread.run(Thread.java:748) [na:1.8.0_131]
 Caused by: com.opensymphony.xwork2.config.ConfigurationException: Unable to load bean: type: class:com.opensymphony.xwork2.ObjectFactory
         at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.register(XmlConfigurationProvider.java:247) ~[xwork-core-2.3.34.jar!/:2.3.34]
         at org.apache.struts2.config.StrutsXmlConfigurationProvider.register(StrutsXmlConfigurationProvider.java:102) ~[struts2-core-2.3.34.jar!/:2.3.34]
         at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:240) ~[xwork-core-2.3.34.jar!/:2.3.34]
         at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67) ~[xwork-core-2.3.34.jar!/:2.3.34]
         ... 23 common frames omitted
 Caused by: com.opensymphony.xwork2.config.ConfigurationException: Bean type class com.opensymphony.xwork2.ObjectFactory with the name struts has already been loaded by bean - jar:file:/C:/workspaces/workspace/pessoal/spring-boot-struts2/target/spring-boot-struts2-0.0.1-SNAPSHOT.war!/WEB-INF/lib/struts2-core-2.3.34.jar!/struts-default.xml:65:72
         at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.register(XmlConfigurationProvider.java:231) ~[xwork-core-2.3.34.jar!/:2.3.34]
         ... 26 common frames omitted

Мои релевантные материалы:

Сервлет Struts

@WebServlet(urlPatterns = { "*.do" })
public class SBSStrutsServlet extends StrutsServlet {

    private static final long serialVersionUID = 4919365268043339311L;

}

Application.java

@SpringBootApplication
@ServletComponentScan
public class Application extends SpringBootServletInitializer {

    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}

struts.xml

<!DOCTYPE struts PUBLIC
        "-//Apache Software Foundation//DTD Struts Configuration 2.3//EN"
        "http://struts.apache.org/dtds/struts-2.3.dtd">

<struts>

    <constant name="struts.objectFactory" value="spring"/>

    <package name="sbs" namespace="/sbs" extends="struts-default">
        <action name="welcome" class="com.gbarbosa.sbs.controller.HelloWorldAction">
            <result name="success">welcome.jsp</result>
        </action>
    </package>
</struts>

WEB-INF\lib

asm-3.3.jar
asm-commons-3.3.jar
asm-tree-3.3.jar
classmate-1.3.3.jar
commons-fileupload-1.3.2.jar
commons-io-2.2.jar
commons-lang3-3.2.jar
ecj-4.5.1.jar
freemarker-2.3.26-incubating.jar
hibernate-validator-5.3.5.Final.jar
jackson-annotations-2.8.0.jar
jackson-core-2.8.8.jar
jackson-databind-2.8.8.jar
javassist-3.11.0.GA.jar
jboss-logging-3.3.1.Final.jar
jcl-over-slf4j-1.7.25.jar
jstl-1.2.jar
jul-to-slf4j-1.7.25.jar
log4j-api-2.7.jar
log4j-core-2.8.2.jar
log4j-over-slf4j-1.7.25.jar
logback-classic-1.1.11.jar
logback-core-1.1.11.jar
ognl-3.0.21.jar
slf4j-api-1.7.25.jar
snakeyaml-1.17.jar
spring-aop-4.3.8.RELEASE.jar
spring-beans-4.3.8.RELEASE.jar
spring-boot-1.5.3.RELEASE.jar
spring-boot-autoconfigure-1.5.3.RELEASE.jar
spring-boot-starter-1.5.3.RELEASE.jar
spring-boot-starter-logging-1.5.3.RELEASE.jar
spring-boot-starter-web-1.5.3.RELEASE.jar
spring-context-4.3.8.RELEASE.jar
spring-core-4.3.8.RELEASE.jar
spring-expression-4.3.8.RELEASE.jar
spring-web-4.3.8.RELEASE.jar
spring-webmvc-4.3.8.RELEASE.jar
struts2-core-2.3.34.jar
struts2-spring-plugin-2.3.34.jar
tomcat-embed-core-8.5.14.jar
tomcat-embed-el-8.5.14.jar
tomcat-embed-jasper-8.5.9.jar
validation-api-1.1.0.Final.jar
xwork-core-2.3.34.jar

Окончательная структура WAR

META-INF
org
sbs
WEB-INF

Я действительно застрял на этом, и на IntelliJ он отлично работает. Я понятия не имею, почему Struts уже создал bean-компонент с именем struts и типом com.opensymphony.xwork2.ObjectFactory.

Пожалуйста, у кого-нибудь есть идеи?


person George Barbosa    schedule 11.12.2017    source источник
comment
Он создается диспетчером при запуске фреймворка. Если это не удается, значит, у вас что-то не так с конфигурацией или зависимостями.   -  person Roman C    schedule 13.12.2017
comment
Я считаю, что это что-то в моей сборке упаковки на maven, потому что, когда я создаю исполняемый файл jar, Struts запускается хорошо, и действие вызывается, но я не могу использовать исполняемый файл jar, потому что он не обслуживает JSP-страницы, он просто находит JSP-страницы если я помещу свою папку src\main\webapp в тот же каталог, что и мой файл jar.   -  person George Barbosa    schedule 13.12.2017
comment
Вы не можете, потому что вы пропускаете их.   -  person Roman C    schedule 14.12.2017
comment
Извините, я не понял. Я хотел бы построить как исполняемый файл war. Разве это не возможно?   -  person George Barbosa    schedule 14.12.2017
comment
Как вы построили исполняемую войну?   -  person Roman C    schedule 14.12.2017
comment
Я использую плагин spring-boot-maven для его переупаковки.   -  person George Barbosa    schedule 15.12.2017


Ответы (2)


Я нашел решение.

Хотя это выглядит как дубликат jar, это не так. Проблема в том, что контейнер tomcat предоставляет два разных пути к одному и тому же файлу. Различные префиксы путей jar:file:/ и jar:war:file:/.

Класс типа бина com.opensymphony.xwork2.ObjectFactory с именем spring уже загружен бином — jar:file:/C:/target/spring-boot-struts2-0.0.1-SNAPSHOT.war!/WEB-INF/ lib/struts2-spring-plugin-2.3.34.jar!/struts-plugin.xml:29:132 - bean - jar:war:file:/C:/target/spring-boot-struts2-0.0.1-SNAPSHOT .war*/WEB-INF/lib/struts2-spring-plugin-2.3.34.jar!/struts-plugin.xml:29:132

Чтобы решить эту проблему, я просто изменил область действия struts2-core и struts2-spring-plugin с компиляции на предоставленную. Spring-boot-maven-plugin помещает эти файлы в WEB-INF/lib-provided, а затем, когда я запускаю java -jar myapplication.war, эти банки предоставляются во время выполнения.

person George Barbosa    schedule 17.12.2017

Чтобы сделать исполняемый файл jar или war из проекта maven, вы должны использовать

   <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <configuration>
            <executable>true</executable>
            <classifier>boot</classifier>
        </configuration>
    </plugin>

который позволяет вам перепаковать военный файл, чтобы сделать его загрузочным. Вы можете найти больше о Плагин Spring Boot Maven на этой странице или на Использование.

66.2 Упаковка исполняемых файлов jar и war

Как только spring-boot-maven-plugin будет включен в ваш pom.xml, он автоматически попытается перезаписать архивы, чтобы сделать их исполняемыми, используя цель spring-boot:repackage. Вы должны настроить свой проект для создания jar или war (в зависимости от ситуации) с использованием обычного элемента упаковки:

<?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/xsd/maven-4.0.0.xsd">
    <!-- ... -->
    <packaging>jar</packaging>
    <!-- ... -->
</project>

Ваш существующий архив будет расширен Spring Boot на этапе package. Основной класс, который вы хотите запустить, можно либо указать с помощью параметра конфигурации, либо обычным способом добавить атрибут Main-Class в манифест. Если вы не укажете основной класс, плагин будет искать класс с помощью метода public static void main(String[] args).

Чтобы создать и запустить артефакт проекта, вы можете ввести следующее:

$ mvn package
$ java -jar target/mymodule-0.0.1-SNAPSHOT.jar
person Roman C    schedule 16.12.2017
comment
Спасибо Роман С! Это именно то, что я делал, но это не сработало должным образом. - person George Barbosa; 18.12.2017
comment
Нет, ты этого не сделал. Это не сработало для вас, потому что вы не прочитали этот ответ должным образом. - person Roman C; 25.12.2017