Struts2 Convention Plugin @Actions not mapping with Spring Boot

clD :

When upgrading my application to use Spring Boot version 2.1.8.RELEASE + struts2-convention-plugin with Struts2-core version 2.5.20 the actions are not being mapped correctly and I am getting the error

com.opensymphony.xwork2.config.ConfigurationException: There is no Action mapped for namespace [/] and action name [home] associated with context path [].

If I decalre the actions in struts.xml they work perfectly.

Below is my current configuration, why are they not mapping?

I have tried many diffrent configs and nothing seems to work, the StrutsPrepareAndExecuteFilter is firing but not actions are found, as if Spring has not scanned them. Could this be a dependency version issue?

application.yaml

  server:
    port: 8080
    servlet:
      context-path: /

Struts2.xml

    <struts>
        <constant name="struts.devMode" value="false" />
        <constant name="struts.convention.action.packages" value="com.myactions.action" />
        <constant name="struts.convention.action.includeJars" value=".*?/myjar.*?jar(!/)?,.*?/myjar*?jar(!/)?" />
        <constant name="struts.objectFactory" value="spring" />
        <constant name="struts.objectFactory.spring.autoWire" value="name" />
        <constant name="struts.multipart.maxSize" value="100000000" />
        <constant name="struts.convention.default.parent.package" value="struts-default"/>

    ## THIS WORKS
    <!--    <package name="home"  extends="struts-default">-->
    <!--        <action name="actionHome" class="com.myactions.action.HomeController" method="actionHome">-->
    <!--            <result name="success">home.jsp</result>-->
    <!--        </action>-->
    <!--    </package>-->

    </struts>

Controller

@Namespace("/")
public class HomeController extends BaseController {

    @Action("home")
    public String actionHome() throws Exception {           
        return SUCCESS;
    }   
}

Main

@SpringBootApplication
@ServletComponentScan
public class Application extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder springApplicationBuilder) {
        return springApplicationBuilder.sources(Application.class);
    }

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

}

Struts2 Filter

@WebFilter("/*")
public class Struts2Filter extends StrutsPrepareAndExecuteFilter {

}

UPDATE

Dependencies

Marc Tarin :

After a couple days of trials and errors, here are a few clues.

Spring Boot 2.1.8 with Struts 2.5.20 configured with struts.xml works. Your projet POM requires at least the following dependencies:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.1.8</version>
</dependency>
...
<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-core</artifactId>
    <version>${struts2.version}</version>
</dependency>
<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-spring-plugin</artifactId>
    <version>2.5.20</version>
</dependency>

I would also recommend adding the Config Browser Plugin to easily list the available actions:

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-config-browser-plugin</artifactId>
    <version>2.5.20</version>
</dependency>

It works when you package :

To get rid of struts.xml and configure your actions only through Java classes, the Convention plugin is required:

<dependency>
    <groupId>org.apache.struts</groupId>
    <artifactId>struts2-convention-plugin</artifactId>
    <version>2.5.20</version>
</dependency>

Notes :

  • the constant defined in struts.xml can also be migrated to the struts.properties file (default values listed here)
  • struts.xml takes precedence over the Convention plugin and struts.properties

When struts.xml is removed, the Convention plugin takes over and Action classes are mapped using the name of packages and classes. The default conventions (action-to-URL mappings, result path...) can also be overridden thanks to a set of annotations.

Still, as mentioned by the OP, configuration through annotations does NOT work out of the box with an embedded Tomcat (it does with an external Tomcat, though).

Best I could do so far, is make it work using an embedded Jetty instead of Tomcat, and adding the recommended configuration to struts.properties:

struts.convention.exclude.parentClassLoader=false
struts.convention.action.fileProtocols=jar,code-source

The starting log still shows errors, but I'm able to access the configured actions with no more XML.

UPDATE

After the OP's update, I digged in a bit more. It turns out the Convention Plugin works fine with Tomcat embedded and no XML needed, by doing the following:

  • Adding the following line to the struts.properties

    struts.convention.exclude.parentClassLoader=false
    
  • Upgrading asm modules asm, asm-commons and asm-tree to release 6.2 or later to prevent errors similar to

    ERROR org.apache.struts2.convention.DefaultClassFinder.<init>:95 - Unable to read class [...]
    

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=309558&siteId=1