404 error after upgrade to Struts 2.3.32 - java

I upgraded Struts2 version,include
free-marker-2.3.22.jar
ognl-3.0.19.jar
struts2-core-2.3.32.jar
struts2-json-plugin-2.3.32.jar
struts2-junit-plugin-2.3.32.jar
struts2-spring-plugin-2.3.32.jar
xwork-core-2.3.32.jar
and added the code to struts.xml
<constant name="struts.enable.DynamicMethodInvocation" value="true"/>
<constant name="struts.convention.action.mapallmatches" value="true"/>
I did not use freemarker but I also added the jar to the "WEB-INF/lib"
the pom.xml was upgraded too.
There was no Exception when the tomcat started.
but my project always showed "404",the console showed no messages.
what should I do ?

Keys are case sensitive in properties file. The same keys are used in struts.xml. See docs Class PropertyResourceBundle.
<constant name="struts.convention.action.mapAllMatches" value="true"/>

Related

Struts2 Convention Plugin #Actions not mapping with Spring Boot

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
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 :
a fat JAR with an embedded Tomcat server, which is the default behavior
a WAR in an external Tomcat Server
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 [...]
Having stepped through spring2-convention-plugin the class PackageBasedActionConfigBuilder has a method buildUrlSet which gets all the urls to classes that need to be scanned for Actions this was removing the urls to my classes and hence nothing was being scanned.
There is a condition excludeParentClassLoader which needs to be set to false (line 415).
Solution
Set below constant's to -
<constant name="struts.convention.exclude.parentClassLoader" value="false" />
<constant name="struts.convention.action.fileProtocols" value="jar,code-source" />

Eclipse launch configuration: resolve active profiles in project

I have several .launch files for Eclipse (I'm using Eclipse Oxygen), here is an example
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.m2e.Maven2LaunchConfigurationType">
<booleanAttribute key="M2_DEBUG_OUTPUT" value="false" />
<stringAttribute key="M2_GOALS" value="clean com.google.cloud.tools:appengine-maven-plugin:deploy" />
<booleanAttribute key="M2_NON_RECURSIVE" value="false" />
<booleanAttribute key="M2_OFFLINE" value="false" />
<stringAttribute key="M2_PROFILES" value="" />
<listAttribute key="M2_PROPERTIES" />
<stringAttribute key="M2_RUNTIME" value="EMBEDDED" />
<booleanAttribute key="M2_SKIP_TESTS" value="true" />
<intAttribute key="M2_THREADS" value="1" />
<booleanAttribute key="M2_UPDATE_SNAPSHOTS" value="false" />
<stringAttribute key="M2_USER_SETTINGS" value="" />
<booleanAttribute key="M2_WORKSPACE_RESOLUTION" value="false" />
<stringAttribute key="org.eclipse.jdt.launching.WORKING_DIRECTORY" value="${project_loc}" />
</launchConfiguration>
Note that I'm using ${project_loc} variable in order to make it usable for any project.
I'm using this kind of files because I can share those with my team. Also the most used Maven Build configurations are ready to go w/o configuring every time a new launch profile.
The problem I'm facing is related to the profile value
<stringAttribute key="M2_PROFILES" value="" />
With the CTRL+ALT+P shortcut on a project, I can select the proper profile to load (Select Maven Profiles... function). I'm using different profile to discern the environment for the deploy (development, stage o production).
I'm trying to "inject" the profile I enabled for the project into the generic launch profile configuration, something like the ${project_loc} variable but related to the current Maven profile.
If this cannot be made I need to create a launch profile for each environment, which means 3 files per every goal to launch.
Is there a way to use/create an Eclipse variable that can be resolved with the Maven profile I activated on the project?
Something like
<stringAttribute key="M2_PROFILES" value="${maven.profile.id}" />
You'll need to create an Eclipse plugin (or contribute to Eclipse m2e project) in order to define a variable using the dedicated extension-point.

I am not using freemarker for struts2, but I see lots of logging generated by freemarker

I am using struts 2 and jsp for my web application, but I am seeing a lot of freemarker debugging message generated on my console.
I have turn off the logging using slf4j and log4j2 configurations. However, looking deeper into the configurations.
It seems that freemarker is included in the struts-default package, and by extending it, I will include freemarker support in my web application as well.
Did I misconfigure my struts.xml configuration? Is disabling the output to console the only way to go?
How do I "remove" freemarker from my application?
my struts.xml
<package name="test" namespace="/" extends="struts-default">
struts-default.xml
<package name="struts-default" abstract="true" strict-method-invocation="true">
<result-types>
<result-type name="chain" class="com.opensymphony.xwork2.ActionChainResult"/>
<result-type name="dispatcher" class="org.apache.struts2.result.ServletDispatcherResult" default="true"/>
<result-type name="freemarker" class="org.apache.struts2.views.freemarker.FreemarkerResult"/>
<result-type name="httpheader" class="org.apache.struts2.result.HttpHeaderResult"/>
<result-type name="redirect" class="org.apache.struts2.result.ServletRedirectResult"/>
<result-type name="redirectAction" class="org.apache.struts2.result.ServletActionRedirectResult"/>
<result-type name="stream" class="org.apache.struts2.result.StreamResult"/>
<result-type name="velocity" class="org.apache.struts2.result.VelocityResult"/>
<result-type name="xslt" class="org.apache.struts2.views.xslt.XSLTResult"/>
<result-type name="plainText" class="org.apache.struts2.result.PlainTextResult" />
<result-type name="postback" class="org.apache.struts2.result.PostbackResult" />
</result-types>
Struts2 uses THEMEs to generate code from Struts tags;
a THEME is a collection of TEMPLATEs (one for each tag);
this TEMPLATEs (in struts2-core-xxx.jar -> template) are FreeMarker Templates.
Then you are not using Freemarker directly (for example in place of the JSPs), but Struts2 uses Freemarker implicitly, and you cannot remove it.
XY: your logging-pollution problem can be resolved by raising the server level to ERROR, and your application to DEBUG, instead of having the whole server to DEBUG.

Why does SuperDevMode only provides LogLevel SEVERE?

I use GWT 2.7 and want to provide logging with Level INFO and WARNUNG in my app. In my gwt.xml file I have:
<inherits name="com.google.gwt.logging.Logging"/>
<set-property name="gwt.logging.logLevel" value="INFO"/>
It works perfect in Dev mode but in SuperDevMode I only get Log level SEVERE to be logged.
Why does SuperDevMode only provides LogLevel SEVERE?
I just checked one of my applications (which uses GXT) and there I see the log message:
I use this lines inside my module descriptor:
<!-- values are: severe, warning, info, config, fine, finer, finest -->
<set-property name="gwt.logging.logLevel" value="INFO"/>
<set-property name="gwt.logging.enabled" value="TRUE" />
<!-- Write messages to browser consoles and to the jvm and dev mode -->
<!-- Note that these are the defaults, so we don’t actually need to list them -->
<set-property name="gwt.logging.consoleHandler" value="ENABLED"/>
<set-property name="gwt.logging.developmentModeHandler" value="ENABLED"/>
<set-property name="gwt.logging.systemHandler" value="ENABLED"/>
<!-- Leave RPC logging disabled, as we aren’t setting that up in this example -->
<set-property name="gwt.logging.simpleRemoteHandler" value="DISABLED"/>
<!-- Ask GXT to log all internal details -->
<set-property name="gxt.logging.enabled" value="true"/>
and add this code to my presenter:
private static final Logger logger = logger.getLogger(ShellPresenter.class.getName());
logger.log(Level.INFO, "Starting module Hermes");
I don't spent time to find out which one of the configurations enables logging nor if it is related to GXT.
And some more informations:
groups.google.com/forum/#!topic/google-web-toolkit/BRZNt1_qEjg
To change log level in SDM, add this option to command line when running it:
-logLevel (ERROR|WARN|INFO|TRACE|DEBUG|SPAM|ALL)

Struts2 Action Regular Expression/Wild card for URL

I am new to Struts2 but so far I have made decent progress using the API. However, I am stuck at something which I need to get out from. I am using Struts2 with Spring integration. I am writing my Action classes with annotation as like many of you I love annotations.
My requirement is that URLs will be in the following nature:
http://<DOMAIN>/program/program1.jspx
http://<DOMAIN>/program/program2.jspx
http://<DOMAIN>/program/program3.jspx
As you can see there is a certain pattern in the URL with program1, program2 and program3 varying and the rest are all static. I have very easily handled similar situation with Spring MVC (I don't have the option of using Spring MVC for the current project) like "/program/{program_name}.jspx" in my other project.
But when I use the same in struts2 I get the error. My Action class is as follows:
#Result(name="program", location="program", type="tiles")
public class ProgramAction extends ActionSupport {
#Action("program/{programName}")
public String getProgramPage() {
// few more lines of code
return "program";
}
}
The error is
2013-02-28 15:46:35.591 WARN [http-bio-8080-exec-3] CommonsLogger.java:60
Could not find action or result
com.opensymphony.xwork2.config.ConfigurationException: There is no Action mapped for namespace / and action name program1.
at com.opensymphony.xwork2.DefaultActionProxy.prepare(DefaultActionProxy.java:189) ~[xwork-core-2.2.1.jar:2.2.1]
at org.apache.struts2.impl.StrutsActionProxy.prepare(StrutsActionProxy.java:61) ~[struts2-core-2.2.1.jar:2.2.1]
at org.apache.struts2.impl.StrutsActionProxyFactory.createActionProxy(StrutsActionProxyFactory.java:39) ~[struts2-core-2.2.1.jar:2.2.1]
at com.opensymphony.xwork2.DefaultActionProxyFactory.createActionProxy(DefaultActionProxyFactory.java:58) ~[xwork-core-2.2.1.jar:2.2.1]
at org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:475) ~[struts2-core-2.2.1.jar:2.2.1]
....
....
My struts.xml file is as follows:
<struts>
<constant name="struts.convention.default.parent.package" value="default"/>
<constant name="struts.action.extension" value="jspx" />
<constant name="struts.mapper.alwaysSelectFullNamespace" value="false" />
<constant name="struts.enable.DynamicMethodInvocation" value="true" />
<package name="default" extends="struts-default, json-default, rest-default" namespace="/">
<result-types>
<result-type name="tiles" class="org.apache.struts2.views.tiles.TilesResult"/>
<result-type name="json" class="org.apache.struts2.json.JSONResult"/>
</result-types>
</package>
</struts>
You have a slash in your action name. struts by default does not like this to correct that add:
<constant name="struts.enable.SlashesInActionNames" value="true"/>
This is because you defined the action annotation on method. Try <s:a namespace="/" action="program/program1" method="programPage" /> in the JSP.

Categories