I'm trying to migrate a web application with spring boot and struts 2 (struts.xml file) from Jboss 7.1.1 to tomcat embedded.
Now, my configurations is like that:
Application.java
@SpringBootApplication()
@ServletComponentScan()
public class Application extends JbossDefaultPropertiesInitializer {
public static void main(String[] args) {
configureApplication(new SpringApplicationBuilder()).run(args);
}
@Override
protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
setRegisterErrorPageFilter(false);
return configureApplication(builder);
}
private static SpringApplicationBuilder configureApplication(SpringApplicationBuilder builder) {
builder.initializers(new DefaultPropertiesInitializer());
return builder.sources(Application.class);
}
}
pom.xml
<resources>
<resource>
<directory>src/main/webapp</directory>
<targetPath>/static</targetPath>
<excludes>
<exclude>**/*.jsp</exclude>
</excludes>
</resource>
<resource>
<directory>src/main/webapp</directory>
<targetPath>/WEB-INF/jsp</targetPath>
<includes>
<include>**/*.jsp</include>
</includes>
</resource>
</resources>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<version>2.4</version>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>1.5.6.RELEASE</version>
<configuration>
<mainClass>com.myapplication.Application</mainClass>
<executable>true</executable>
<layout>WAR</layout>
</configuration>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
struts.devMode=true
Every filter, servlet and listener were migrated from web.xml to @WebFilter, @WebListener and @WebServlets.
Everything seems to works fine when I start tomcat and I'm able to get some static resources like html, css and js.
When I call some struts page like http://localhost:8080/myapplication/login.go, everything happens fine, the filters and servlets are called, my action is called but when the action returns "success" to call the "/myapplication/jsp/login.jsp" It doesn't rendered. The jsp file is not called or there is some error and I don't get nothing in console.
The log before my action call the jsp page:
2017-11-28 13:03:19.881 INFO 7376 --- [nio-8080-exec-3] c.o.x.c.p.XmlConfigurationProvider : Parsing configuration file [struts-default.xml]
2017-11-28 13:03:19.933 WARN 7376 --- [nio-8080-exec-3] com.opensymphony.xwork2.util.DomHelper : Local DTD is missing for publicID: -//Apache Software Foundation//DTD Struts Configuration 2.5//EN - defined mappings: {-//Apache Struts//XWork 1.1.1//EN=xwork-1.1.1.dtd, -//Apache Software Foundation//DTD Struts Configuration 2.0//EN=struts-2.0.dtd, -//Apache Struts//XWork 1.0//EN=xwork-1.0.dtd, -//Apache Software Foundation//DTD Struts Configuration 2.1//EN=struts-2.1.dtd, -//Apache Struts//XWork 1.1//EN=xwork-1.1.dtd, -//Apache Struts//XWork 2.1.3//EN=xwork-2.1.3.dtd, -//Apache Software Foundation//DTD Struts Configuration 2.3//EN=struts-2.3.dtd, -//Apache Struts//XWork 2.0//EN=xwork-2.0.dtd, -//Apache Software Foundation//DTD Struts Configuration 2.1.7//EN=struts-2.1.7.dtd, -//Apache Struts//XWork 2.1//EN=xwork-2.1.dtd, -//Apache Struts//XWork 2.3//EN=xwork-2.3.dtd}
2017-11-28 13:03:20.220 INFO 7376 --- [nio-8080-exec-3] c.o.x.c.p.XmlConfigurationProvider : Parsing configuration file [struts-plugin.xml]
2017-11-28 13:03:20.301 INFO 7376 --- [nio-8080-exec-3] c.o.x.c.p.XmlConfigurationProvider : Parsing configuration file [struts.xml]
2017-11-28 13:03:20.304 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (spring) for (com.opensymphony.xwork2.ObjectFactory)
2017-11-28 13:03:20.304 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.factory.ActionFactory)
2017-11-28 13:03:20.304 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.factory.ResultFactory)
2017-11-28 13:03:20.304 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.factory.ConverterFactory)
2017-11-28 13:03:20.304 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.factory.InterceptorFactory)
2017-11-28 13:03:20.304 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.factory.ValidatorFactory)
2017-11-28 13:03:20.304 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.factory.UnknownHandlerFactory)
2017-11-28 13:03:20.304 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.FileManagerFactory)
2017-11-28 13:03:20.305 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.XWorkConverter)
2017-11-28 13:03:20.305 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.CollectionConverter)
2017-11-28 13:03:20.305 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.ArrayConverter)
2017-11-28 13:03:20.305 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.DateConverter)
2017-11-28 13:03:20.305 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.NumberConverter)
2017-11-28 13:03:20.305 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.impl.StringConverter)
2017-11-28 13:03:20.305 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.ConversionPropertiesProcessor)
2017-11-28 13:03:20.305 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.ConversionFileProcessor)
2017-11-28 13:03:20.305 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.ConversionAnnotationProcessor)
2017-11-28 13:03:20.305 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.TypeConverterCreator)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.TypeConverterHolder)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.TextProvider)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.LocaleProvider)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.ActionProxyFactory)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.conversion.ObjectTypeDeterminer)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (org.apache.struts2.dispatcher.mapper.ActionMapper)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (jakarta) for (org.apache.struts2.dispatcher.multipart.MultiPartRequest)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (org.apache.struts2.views.freemarker.FreemarkerManager)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (org.apache.struts2.views.velocity.VelocityManager)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (org.apache.struts2.components.UrlRenderer)
2017-11-28 13:03:20.306 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.validator.ActionValidatorManager)
2017-11-28 13:03:20.307 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.util.ValueStackFactory)
2017-11-28 13:03:20.307 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.util.reflection.ReflectionProvider)
2017-11-28 13:03:20.307 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.util.reflection.ReflectionContextFactory)
2017-11-28 13:03:20.307 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.util.PatternMatcher)
2017-11-28 13:03:20.307 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (org.apache.struts2.util.ContentTypeMatcher)
2017-11-28 13:03:20.307 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (org.apache.struts2.dispatcher.StaticContentLoader)
2017-11-28 13:03:20.307 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.UnknownHandlerManager)
2017-11-28 13:03:20.307 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (org.apache.struts2.views.util.UrlHelper)
2017-11-28 13:03:20.308 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.util.TextParser)
2017-11-28 13:03:20.308 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (org.apache.struts2.dispatcher.DispatcherErrorHandler)
2017-11-28 13:03:20.308 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.security.ExcludedPatternsChecker)
2017-11-28 13:03:20.308 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.AbstractBeanSelectionProvider : Choosing bean (struts) for (com.opensymphony.xwork2.security.AcceptedPatternsChecker)
2017-11-28 13:03:20.310 INFO 7376 --- [nio-8080-exec-3] o.a.s.c.DefaultBeanSelectionProvider : Loading global messages from [messageResources]
2017-11-28 13:03:20.699 INFO 7376 --- [nio-8080-exec-3] c.o.xwork2.spring.SpringObjectFactory : Setting autowire strategy to name
2017-11-28 13:03:21.764 ERROR 7376 --- [nio-8080-exec-3] c.o.x.interceptor.ParametersInterceptor : Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting 'cp' on 'class com.myapplication.account.actions.LoginNavigationAction: Error setting expression 'cp' with value ['false', ]
2017-11-28 13:03:21.769 ERROR 7376 --- [nio-8080-exec-3] c.o.x.interceptor.ParametersInterceptor : Developer Notification (set struts.devMode to false to disable this message):
Unexpected Exception caught setting 'forwardURL' on 'class com.myapplication.account.actions.LoginNavigationAction: Error setting expression 'forwardURL' with value ['/myapplication/html/login.html', ]
2017-11-28 13:03:21.844 INFO 7376 --- [nio-8080-exec-3] c.m.account.actions.LoginPageAction : ========================= Result from LoginPageAction: success
UPDATE
When I try java -jar myapplication.war, I could access my static pages but I've got another error accessing struts pages:
2017-11-29 08:55:41.536 WARN 7968 --- [nio-8080-exec-8] c.o.xwork2.util.fs.JarEntryRevision : Could not create JarEntryRevision for [jar:file:/C:/workspaces/workspace/dev/myapplication/target/myapplication-war-0.0.0.war]!
java.lang.NullPointerException: null
at com.opensymphony.xwork2.util.fs.JarEntryRevision.build(JarEntryRevision.java:52)
at com.opensymphony.xwork2.util.fs.DefaultFileManager.monitorFile(DefaultFileManager.java:97)
at com.opensymphony.xwork2.util.fs.DefaultFileManager.loadFile(DefaultFileManager.java:74)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadConfigurationFiles(XmlConfigurationProvider.java:1015)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.loadDocuments(XmlConfigurationProvider.java:167)
at com.opensymphony.xwork2.config.providers.XmlConfigurationProvider.init(XmlConfigurationProvider.java:134)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:239)
....
2017-11-29 08:55:41.636 WARN 7968 --- [nio-8080-exec-8] c.o.xwork2.util.fs.JarEntryRevision : Could not create JarEntryRevision for [jar:war:file:/C:/workspaces/workspace/dev/myapplication/target/myapplication-war-0.0.0.war*/WEB-INF/lib/struts2-core-2.3.34.jar]!
java.io.FileNotFoundException: war:file:\C:\workspaces\workspace\dev\myapplication\target\myapplication-war-0.0.0.war*\WEB-INF\lib\struts2-core-2.3.34.jar (The filename, directory name, or volume label syntax is incorrect)
at java.util.zip.ZipFile.open(Native Method)
at java.util.zip.ZipFile.<init>(ZipFile.java:219)
at java.util.zip.ZipFile.<init>(ZipFile.java:149)
at java.util.jar.JarFile.<init>(JarFile.java:166)
at java.util.jar.JarFile.<init>(JarFile.java:130)
at com.opensymphony.xwork2.util.fs.JarEntryRevision.build(JarEntryRevision.java:50)
...
2017-11-29 08:55:41.690 INFO 7968 --- [nio-8080-exec-8] c.o.x.c.p.XmlConfigurationProvider : Parsing configuration file [struts-default.xml]
2017-11-29 08:55:41.802 ERROR 7968 --- [nio-8080-exec-8] 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)
at org.apache.struts2.dispatcher.Dispatcher.getContainer(Dispatcher.java:978)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:446)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:490)
at org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:74)
...
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)
at org.apache.struts2.config.StrutsXmlConfigurationProvider.register(StrutsXmlConfigurationProvider.java:102)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:240)
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67)
... 65 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/dev/myapplication/target/myapplication-war-0.0.0.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)
... 68 common frames omitted
Please, any idea?
I could fix it after three days of research.
Before start to migrate my legacy application I created some applications to test Spring Boot, Struts 2 and Tomcat and all of them worked fine. The problem was my legacy system has its own parent. I wasn't using the following spring boot parent.
I can't use it:
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.3.RELEASE</version>
</parent>
So, as per Spring Boot documentation:
"Not everyone likes inheriting from the spring-boot-starter-parent POM. You may have your own corporate standard parent that you need to use or you may prefer to explicitly declare all your Maven configuration.
If you do not want to use the spring-boot-starter-parent, you can still keep the benefit of the dependency management (but not the plugin management) by using a scope=import dependency, as follows:"
<dependencyManagement>
<dependencies>
<dependency>
<!-- Import dependency management from Spring Boot -->
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>2.0.0.BUILD-SNAPSHOT</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Now, the application is able to show every jsp/struts page.
NOTE: I didn't need to put any special configuration like ViewResolver or my own DispatcherServlet. I just added the above dependency and copied every static and jsp page to "META-INF/resources" as per @Sébastien PRAT's sugestion. Other folder options are "resources/", "static/" and "public/".
UPDATE
This following error occurs because the embedded tomcat container provides two different paths to xwork api of the same file (struts-default.xml), then xwork api fails because try to initialize the same bean twice. So, you should change struts dependencies scope from compile to provided. Spring boot maven plugin will copy your struts dependencies under the web-inf/lib-provided folder. It will work fine as a executable war file but if you need both, executable and deployeable, you should create different profiles to generate different files.
com.opensymphony.xwork2.config.ConfigurationException: Unable to load configuration.
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:70)
at org.apache.struts2.dispatcher.Dispatcher.getContainer(Dispatcher.java:978)
at org.apache.struts2.dispatcher.Dispatcher.init_PreloadConfiguration(Dispatcher.java:446)
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:490)
at org.apache.struts2.dispatcher.ng.InitOperations.initDispatcher(InitOperations.java:74)
...
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)
at org.apache.struts2.config.StrutsXmlConfigurationProvider.register(StrutsXmlConfigurationProvider.java:102)
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reloadContainer(DefaultConfiguration.java:240)
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:67)
... 65 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/dev/myapplication/target/myapplication-war-0.0.0.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)
... 68 common frames omitted
Struts 2 Scope:
<dependency>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-spring-plugin</artifactId>
<version>2.3.34</version>
<scope>provided</scope>
<exclusions>
<exclusion>
<groupId>org.apache.struts</groupId>
<artifactId>struts-core</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.struts.xwork</groupId>
<artifactId>xwork-core</artifactId>
</exclusion>
</exclusions>
</dependency>
Now, I can generate a executable war and run with java -jar myapplication.war.
I hope It helps.