0. Create a project by archetype
Reference: http://blog.csdn.net/derek_zhang_/article/details/8142417
1. In order to use @Result, it's necessary to add this dependency in Maven's POM:
org.apache.struts
struts2-convention-plugin
${struts2.version}
2. Preparable Interface
You could understand its meaning as stupid as practical.
3. paramsPrepareParamsStack
Take updating scenario for example, some params were sent from front page, included in the Request object, we need one param to retrieve the domain object, once the object is prepared, other params should be used to override the retrieved object for updating.The framework does the override job automatically for us, otherwise we would have to do it manually, thank god. Make sense?
4. ObjectFactory
Quoted from Apache official site: The Struts-Spring Plugin works by overriding the Struts ObjectFactory to enhance the creation of core framework objects. When an object is to be created, it uses the class attribute in the Struts configuration to correspond to the id attribute in the Spring configuration. If not found, the class will try to be created as usual, then be autowired by Spring. In the case of Actions, Spring 2's bean scope feature can be used to scope an Action instance to the session, application, or a custom scope, providing advanced customization above the default per-request scoping.
5. Case: dependencies version collision when integrating Spring 2.5.6 with Hibernate 3.2.6
java.lang.NoClassDefFoundError: org/objectweb/asm/FieldVisitor
This error is caused by Spring-Hibernate integration, spring's asm dependencies collides with hibernate's asm version.
Solution Reference: http://stackoverflow.com/questions/9797334/maven-detect-multiple-versions-of-the-same-dependency
org.hibernate
hibernate
3.2.1.ga
asm
asm
asm
asm-attrs
cglib
cglib
cglib
cglib-nodep
2.2
6. SEVERE: Dispatcher initialization failed
Unable to load configuration [unknown location]
LESSON: Look for the 'Caused by' sentence, DO NOT just google 'Struts 2 Unable to load configuration', Seriously! Find the 'Caused by' on screen you would get the more informative description. In my case, one of my result type set to an incorrect value caused the problem, totally different with all scenarios on the internet.
7. >>> FilterDispatcher <<< is deprecated!
It's really disappointing that strutsarchetypestarter 2.3.7 still uses FilterDispatcher, so we always get this annoying deprecation warning until we do this replacement:
action2
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
8. org.apache.struts2.config.Result cannot be resolved
Try this:
org.apache.struts2.config.convention.annotation.Result
9. The type Validation is deprecated
Since Struts 2.1, class level @Validation annotation is no longer necessary, just remove it, no replacement annotation. We just need to annotate type level for validators.
10. Struts 2 Spring Integration Error, BeanCreationException
Cause: In my case, there is a field in SomeAction named 'service', whereas in the applicationContext.xml it's 'userService', they are not identical name, can't be autowired.
11. Since 2.1 CodeBehind plugin has been deprecated in favor of the Convention Plugin.
Reference: http://struts.apache.org/2.1.6/docs/convention-plugin.html
Reference: Rails
12. java.io.IOException: Stream closed
Check the jsp content and warnings from console:
LESSON: We can't ignore WARNINGs sometimes.
For the first warning, we can handle it via adding a corresponding i18n entry;
For the second, let's look at the action's configuration first:
@ParentPackage("enterEvent")
@Results( value={
@Result(type= "redirect", location="selectContestants"),
@Result(name="input", location="/WEB-INF/jsp/event/selectContestants-input.jsp")
})
public class RemoveContestantsAction extends BaseEventAction {
Given that our struts version is 2.3.4, and convention plugin as well, so we couldn't use 'removeContestants', we have to code it as 'remove-contestants', as shown below:
<%-- --%>
LESSON: Take care of the convention!
13. WARNING: Parameter [namespace] is on the excludeParams list of patterns!
14. Unknown Error: No result defined for action xxx
Reference: http://guimingyue.iteye.com/blog/854628
15. SLF4J: Failed to load class "org.slf4j.impl.StaticLoggerBinder".
Solutions on the internet are all negative for me.
16. log4j:WARN No appenders could be found for logger
17. Struts 2 Freemarker Integration
Reference: http://struts.apache.org/2.3.7/docs/using-freemarker-templates.html
To configure the FreeMarker engine, just add a file freemarker.properties to the classpath.
Tags distributed with Struts are automatically made available to FreeMarker templates. To use any tag add "@s." in front of the tag name.
Freemarker Editor Eclipse Plugin
jEdit 4.1 is a Free programmer's text editor written in Java, supports FreeMarker out-of-the-box
18. Struts 2 Debug Tips
(1) Historic: (Deprecated)Make use of
(2) Comtemtary: One tool is the Struts 2 configuration plugin and the other is the debugging interceptor.
For debugging interceptor: Add '?debug=browser' to your url.
Reference: http://struts.apache.org/2.3.7/docs/debugging-struts.html
(3) Eclipse Debug Setting
Prerequisities: struts2-starter-archetype 2.3.7
Critical point is jetty setting:
Aftermath, at last, we are able to add break points and debug, enjoy your journey!
19. Exception: There is no Action mapped for namespace
Case URL:
http://localhost:8086/simple/saveSupplierHeader.action
Caused by incorrect action name in struts.xml. Struts.xml:
/tpl/supplier-header-input.ftl
/tpl/supplier-header-input.ftl
/tpl/supplier-header-success.ftl
Solution: change the name to 'saveSupplierHeader'
20. The Model in Action Object is null
public class SupplierHeaderAction extends ActionSupport implements ModelDriven {
private static final long serialVersionUID = 1L;
@Autowired
protected SupplierHeaderService supplierHeaderServiceImpl;
protected SupplierHeader sh;
public SupplierHeader getModel(){
return sh;
}
public String inputSupplierHeader(){
return INPUT;
}
public String saveSupplierHeader(){
supplierHeaderServiceImpl.save(sh);
return SUCCESS;
}
}
when saveSupplierHeader() method executed, the sh is null, debug it!
Here is the struts.xml:
/tpl/index.ftl
/jsp/index.jsp
/jsp/helloWorld.jsp
/jsp/index.jsp
/tpl/hello-freemarker.ftl
/tpl/supplier-header-input.ftl
/tpl/supplier-header-input.ftl
/tpl/supplier-header-success.ftl
/tpl/supplier-header-input.ftl
Below is quoted from
Providing access to the domain object is achieved by creating a model driven action. There are two steps to enable this process. The first step is to have the action extend the ModelDriven interface. The second step is to ensure that the modelDriven interceptor is being applied to the action implementing the ModelDriven interface.
If there is a strange bug, a NullPointerException, or data not present on a property that should have an assigned value, there is a good chance that it may have something to do with interceptors. Interceptors in the wrong order or missing interceptors are problems that can have consequences that do not point immediately to interceptors. The good news is that spelling mistakes in the interceptor or interceptor-ref attributes names will cause the initialization of Struts2 to be aborted, and the problem can be quickly rectified.
Now, we see that struts-default's default interceptor stack doesn't include modeldriven interceptor, so we add it first.
After adding Preparable, we got another situation: the sh is not null, but all the fields' value is null!
this empty sh object was created by prepare(), so the fact is ParametersInterceptor failed to set form values into ValueStack.
At last, found the bug was caused by lack of model's getter/setter, add this snippet to action then joy comes:
public SupplierHeader getSh() {
return sh;
}
public void setSh(SupplierHeader sh) {
this.sh = sh;
}