Struts 2.x migration - How to achieve same URL pattern as Struts 1.x - struts2

Currently I am working in Struts migration task from 1.x to 2.x. The major problem I am facing is that change in URL pattern.
In Struts 1, we use url pattern as below.
Note: multiple methods resides in each action class
https://<host-name>/xxx.do?method=begin
After struts 2, we are following below url pattern
https://<host-name>/xxx_begin.action
struts.xml:(used wildcard mapping)
<action name="xxx_*" method ="{1}" class = "foo.Myaction"><result name="success"> myjsp.jsp</result></action>
Question:
Is there any way to achieve the same url pattern as mentioned for Struts 1 in Struts 2?
Since its very big project, it is very complicated to update each and every place where the invocation happens.
I have searched through many sources and found, it is easy to configure .action extension to .do extension by simply adding the below config in struts.xml
<constant name="struts.action.extension" value="do"/>
But how to achieve the method invocation as same as Struts 1.
If there is solution, also please mention how to add the action mapping in struts.xml?

Struts actions are mapped using the ActionMapper. You can use different action mapper class configured to the application. The action mapper used by default is not able to map URLs to actions the same way you did in Struts 1. Some action mappers are available via plugins but it's not possible to map parameters to the action. Only action name and namespace are mapped.
It is important that before you write your own action mapper to understand What is the role of the action mapper in Struts 2 and its scope.
There's also special parameter used by DMI, which is using a method prefix parameter name. If you find a way how to change the parameter to use its value as a name and add a method: prefix. The documentation said that a method prefix can be somehow overridden.
With method-prefix, instead of calling baz action’s execute() method (by default if it isn’t overridden in struts.xml to be something else), the baz action’s anotherMethod() will be called.
Struts 2 can be extended via providing a custom action mapper.

Related

Custom ActionMapper in struts2

The issue I am facing has to do with the method handleSpecialParameters() inside org.apache.struts2.dispatcher.mapper.DefaultActionMapper class.
The problem is that the actionName should be "nameOfActionID" for example "name139".
But inside handleSpecialParameters() this name is changed and there is a 0 that is added at the end of the name ("name0"). That's why I have tried to create my own custom action mapper in order to skip this method.
Does anybody know how I can configure my struts.xml to use this custom action mapper?
I have seen the custom ActionMapper link but I got an error due to -bean when I started the server.
The application uses struts2 2.3.37

What is the role of the action mapper in Struts 2?

Can somebody explain the role of the Action Mapper in Struts 2?
The role of ActionMapper interface in Struts2 framework is to extract mapping from the request's URL.
When given an HttpServletRequest, the ActionMapper may return null if no action invocation request matches, or it may return an ActionMapping class that describes an action invocation for the framework to try.
You can read more about this feature here.
Th first method returns a mapping to try, it doesn't guarantee that this action will be executed.
The ActionMapping returned by the action mapper contains all necessary information to invoke an action if there's an action config corresponding to this mapping is available in runtime configuration.
Different implementation of this interface can be used to override the default behavior for mapping URLs to actions in Struts2.

How action mapping is done with struts with the help of struts-config.xml?

I would like to know how the action mapping is done by struts reading struts-config.xml file.
Will this differ between Struts1 and Struts2 - the way in which the action mapping is done?
Help me know about it.
In Struts1 action mapping is defined by the struts-config.xml action tag.
In Struts2 action mapping is defined by the struts.xml action tag.
Note, that action mapping implementation in Struts2 vary on which plugin provides it. The plugins also provide their own action configs.

Migration from Struts1 to Struts2 [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have my application in Struts1 and I have used Dispatch action in all my actions. Please tell me now how do I Shift to struts 2 and what are the modifications that should be made to change all my actions and form beans.
I will suggest you this document series:
http://www.infoq.com/articles/converting-struts-2-part1
http://www.infoq.com/articles/migrating-struts-2-part2
First link explains the topic and there is an example at second link. I wrote below an explanation taken from there:
Configuring the framework
The first, and most important configuration, is the one that enables the web application framework within the servlet containers web.xml file.
The configuration that everyone should be familiar with for Struts is:
<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/struts-config.xml</param-value>
</init-param>
<load-on-startup>2</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>
For Struts2 there are very few changes. The most significant is that the dispatcher has been changed from a servlet to a servlet filter. The configuration is just as easy as for a servlet, and shown here:
<filter>
<filter-name>webwork</filter-name>
<filter-class>
org.apache.struts.action2.dispatcher.FilterDispatcher
</filter-class>
</filter>
<filter-mapping>
<filter-name>webwork</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
Deconstructing the Actions
In the request walk-through we spoke about some of the differences between Struts and Struts2 from a high level. Let's take it a step deeper now, and look at the differences between the structures of the actions in each framework.
Let's first review the general structure of the Struts action. The general form of the Struts action looks like this:
public class MyAction extends Action {
public ActionForward execute(ActionMapping mapping,
ActionForm form,
HttpServletRequest request,
HttpServletResponse response)
throws Exception {
// do the work
return (mapping.findForward("success"));
}
}
When implementing a Struts action, you need to be aware of the following items:
All actions have to extend the Action base class.
All actions have to be thread-safe, as only a single action instance is created.
Because the actions have to be thread-safe, all the objects that may be needed in the processing of the action are passed in the method signature.
The name of the method that is invoked for the processing of the action is "execute" (there is a DispatchAction class available in Struts which can re-route the method to be executed to another method in the same action, however the initial entry point from the framework into the action is still the "execute" method).
An ActionForward result is returned using a method from the ActionMapping class, most commonly via the "findForward" method call.
In contrast, the Struts2 action provides a much simpler implementation. Here's what it looks like:
public class MyAction {
public String execute() throws Exception {
// do the work
return "success";
}
}
The first thing you may have noticed is that the action doesn't extend any classes or interfaces. In fact, it goes further than this. By convention, the method invoked in the processing of an action is the "execute" method - but it doesn't have to be. Any method that follows the method signature public String methodName() can be invoked through configuration.
Finally, and perhaps the most revolutionary difference from the original Struts implementation, is that the method invoked in the processing of an action (the "execute" method) has no parameter. So how do you get access to the objects that you need to work with? The answer lies in the "inversion of control" or "dependency injection" pattern (for more information Martin Fowler has an informative article at http://www.martinfowler.com/articles/injection.html). The Spring Framework has popularized this pattern, however, the predecessor to Struts2 (WebWork) started using the pattern around the same time.
You may use dynamic method invocation to vaguely-mimic the old DispatchAction-style "pass in the method name" functionality (or you could write an interceptor that used a parameter to do much the same thing).
There are no "form beans" per se in Struts 2, although you can implement ModelDriven (some docs) and it sort-of works like a form bean.
All JSPs will need to be re-written, but only if you're using the Struts 1 tags. If you used only JSTL tags, you may not need to, it'd depend.
The link provided by Ischin is a good place to start getting more details.
For the Struts 2.x: Make the dispatcher action filter as *.action
For the struts 1.x: Make the action filter as *.do .

How to check for the existence of an action within a namespace in Struts2?

I'd like to implement in a Struts2 web application some sort of url "fallback" using an own ActionMapper. This means:
when
http://server/webapp/foo/bar/myaction
does not exist, I want the ActionMapper to try to load e.g.
http://server/webapp/foo_fallback/bar/myaction
instead.
Parsing the URL and therefore finding the namespace is not a problem, but I don't know how to decide if the desired action is present in this namespace (which I have to modify if it is not).
Is there a possibility to check if an action exists within a namespace (/foo/bar in this case)? Or is there another mechanism to perform what I intend to do?
Thanks,
Gregor
You have to do this for every configured namespace:
<action name="*">
<result type="redirectAction">your fallback action here</result>
</action>
If it doesn't work, set struts.enable.SlashesInActionNames to false.
I solved my problem. This happens in the custom ActionMapper:
To find out if an action exists, I firstly construct a string of the class name (including the namespace) of the desired action. Then I call
Class.forName("namespaceroot.foo.bar.myaction");
If the action does not exist, an ClassNotFoundException exception is thrown, which I can check for in a try { ... } catch { ... } block. Within the catch block I can change the namespace of the mapping to the fallback namespace. This has some implications to the ActionProxy: The namespace has to be changed there, too, in getMappingFromActionName. Otherwise the ActionProxy contains the namespace of the request, which is fine usually. The DefaultActionProxy does not have a setter for namespace, so I subclassed it and create it using a custom AxtionProxyFactory. Phew.
This is not elegant imho, but as long as I don't come up with a better idea it'll stay that way. I'd love to hear a better solution!

Resources