Custom ActionMapper in struts2 - 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

Related

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

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.

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.

Call Grails Controller method without having a view for it

I am using Grails 3, and am working on a template page, which contains the outline for the rest of the website. I and am attempting to call a method from a controller, by using the following code, as recommended by the official documentation:
<g:include controller="layouts" action="loadUsers" />
My controller looks as follows:
class LayoutsController {
def loadUsers() {
println("we are in here")
}
}
When the include statement gets executed on my embedded tomcat, I get the following error:
[http-nio-8443-exec-4] ERROR o.a.c.c.C.[.[.[.[grailsDispatcherServlet] - Servlet.service() for servlet grailsDispatcherServlet threw exception
javax.servlet.ServletException: Could not resolve view with name 'loadUsers' in servlet with name 'grailsDispatcherServlet'
Ofcourse, the error makes sense, as I do not have that view/gsp page. I want to just simply invoke a method to create some stuff in the backend, not tie it to a gsp page. Is this possible? Basically, a similar approach to JSF where I can execute a public method on a bean.
When a controller action is invoked, unless the action invokes something like redirect or render, then a view will be rendered. That is by design and how controller actions are supposed to behave. If the view isn't present, then an error occurs.
It isn't clear what you are trying to do but if you are just trying to invoke some logic and you don't want a view that is a little bit of an unusual thing to be doing from a GSP, but you could do it by invoking a custom GSP tag that does whatever it is you are trying to accomplish. Normally all of that sort of thing is done before the view is rendered (so, before any GSP code is involved).

StructureMap MVC 5 html.Action Issue

I am trying to call an Action from my view using #Html.Action("ActionName","controllerName"). But my page fails to load with below error:
A single instance of controller 'Web.Areas.Area1.Controllers.ActionController'
cannot be used to handle multiple requests. If a custom controller
factory is in use, make sure that it creates a new instance of the
controller for each request.
I am using structure map for Dependency injection. Please help me what am i missing.
You need to add
x.For<{Your controller name}>().AlwaysUnique();
in IoC.cs file. This should be done for every controller in your project.
For more details check this link.

Grails Custom Scaffolding get access to controller name

I am trying to write a custom src/templates/scaffolding/Controller.groovy and was wondering if there was any way to get access to the controller name? Right now it seems like you can only get the "model" class. The reason I need it is I am customizing the render to prefix the templates directory based on the controller.
For instance I have a controller named AuthorAdminController and I need to customize the list to use the /admin/user/** directory.
Let me know if you have any questions. I am getting ready to look into how to customize DefaultGrailsTemplateGenerator but I am not sure if that is the correct route to go.
Example:
class UserAdminController {
static scaffold = User
}
Currently in my Controller.groovy I get className='user' so I have no access to the controller.
I don't think you can, as the way scaffolding works your template will always be generating a class named DomainClassNameController (i.e. UserController in your example), which gets loaded into a new classloader and then the metaclass of the real controller (UserAdminController) gets new actions added to it which delegate to an instance of the generated UserController.
Now every controller has access to the controllerName property during execution of actions, so this may provide you with a workaround. I haven't tried it, but you could try putting a log.info("controller: \${controllerName}") into the template and see which name it gives you (the backslash to make it resolve at runtime rather than generation time).

Resources