I would like to create an action class with no setter and getter on properties for the data coming from the user interface. Instead, I would like to use ServletActionContext.getRequest().getParameterMap() in my own builder class to construct the object.
I had created my Action class with no properties. When I am submitting my form I am running into ognl.OgnlException: target is null for setProperty(null, "field-name", [Ljava.lang.String;#5513fab7)
Is there any additional conventions or configurations required to convey Struts2 framework to not set properties and stop avoid the exception I am receiving above?
You can exclude some properties from the accepted parameters for params interceptor by setting parameter excludeParams to the interceptor. By default this parameter is initialized with
<interceptor-ref name="params">
<param name="excludeParams">dojo\..*,^struts\..*,^session\..*,^request\..*,^application\..*,^servlet(Request|Response)\..*,parameters\...*</param>
</interceptor-ref>
You should add you properties here, it accepts the regex pattern to match the property names. The strategy applied with accepted parameter names could be compromised via the ParameterNameAware implemented actions where you could remove the restriction given above.
To be more specific about "data coming from the user interface" I'd adhere that parameters to the interceptor-ref element is applied to the interceptor on start up and is not stored elsewhere in the configuration manager. This means you can't get this parameters at runtime and only could change via updating and reloading the configuration file struts.xml. If you keep your configuration in the safe place and it's protected from modification then you could make more claims toward your running application safety.
Yes, you need to remove the Struts params interceptor mapping for this specific action. I believe you can take an approach similar to the one in this related question. Otherwise you will have to create another interceptor stack with the interceptors you desire, minus the parameter interceptor and map the action to that stack in struts.xml or use the #InterceptorRef annotation on your action class, assuming you're using the convention plugin.
Related
How to rename the Struts2 Token Parameters?
if we use <s:token/> tag while form submit by default Struts2 will generate URL something like this
?name=name&struts.token.name=struts.token&struts.token=8E1USQZ5LHG120FU4YUZJAMPOUT4OVP3
by using this <s:token name="suid"/> tag we can rename the "struts.token" parameter. Struts2 will generate URL something like this
?name=name&struts.token.name=suid&suid=8E1USQZ5LHG120FU4YUZJAMPOUT4OVP3
How can we rename the "struts.token.name" parameter?
The parameter is used by the TokenHelper. There no extension points are given for this bean. You can provide your own implementation by extending token interceptors and overriding their methods only and replace references of token helper inside them.
You should check this links:
Interceptors
Introducing Interceptors
Writing Interceptors
I want to call a method on a Filter object after it has been added according to the web.xml definition. All I got is a WebApplicationContext object (let's call it: wac).
I'm able to add new Filter objects via: wac.getServletContext().addFilter("otherfilter", otherFilter);
Also, I can test successfully for its existence via: wac.getServletContext().getFilterRegistration("myfilter")
But how may I access (and possibly modify) Filter objects which have been added before?
I'm not sure how to do it exactly as you want, but this problem is usually solved using different approach.
You can declare your Filter as a bean in your application context and then register a DelegatingFilterProxy in web.xml to delegate filtering to your filter.
In this case your filter will be a regular Spring bean, and you'll be able to access it like any other bean.
The Servlet API does not provide any mechanism to directly access a Filter instance once it has been added to a ServletContext. The best you are going to get with the Servlet API is the FilterRegistration interface you have already found which lets you modify the same set of configuration options as you can via web.xml.
Depending on exactly what you want to do, you might be able to code your way around this problem using init parameters but that is never going to be a particularly clean solution. I'd go with the DelegatingFilterProxy solution suggested by axtavt.
In my app, before upgrading to jsf 2, when doing a custom redirect I used to manually put a request parameter with a specific value in external context like this:
FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap()
.put(CmwNavigationControllerBean.PARAM_DISPLAY_TARGET_POPUP, "true");
Now this line, throws an exception because it seems that this map is no longer allowed to be modified:
at java.util.Collections$UnmodifiableMap.put(Unknown Source) [rt.jar:1.7.0]
Isn't really no other way to bypass this exception? I'm doing refactoring because of upgrade and I try to keep the changes at minimal level.
You can either use a view parameter or use the flash scope for that. A view parameter is in practice a GET parameter which you can pass when you request the page you want to redirect to. For your case, you should redirect to it with the parameter appended.
Return the navigation case with the parameter appended:
//Will be reflected in browser's address bar as /context/myDestinationView.xhtml?displayTargetPopUp=true
return "myDestinationView?displayTargetPopUp=true&faces-redirect=true&includeViewParams=true";
Catch it from your destination view:
<f:viewParam name="displayTargetPopUp" value="#{displayTargetPopUp}" />
Another way if you want to avoid including it in your GET request, is to use flash scope, which is supposed to be fixed for Mojarra 2.1.27 and 2.2.5 versions. Flash scoped values are designed to support a redirection, while the request ones are not.
See also:
Understand Flash Scope in JSF2
How do you pass view parameters when navigating from an action in JSF2?
Rather than getRequestParameterMap() (which is read-only) you should invoke getRequestMap() on the ExternalContext.
For example:
FacesContext.getCurrentInstance()
.getExternalContext()
.getRequestMap()
.put(CmwNavigationControllerBean.PARAM_DISPLAY_TARGET_POPUP, "true");
In order to take control of the parameters which an action accept you must:
Make your action implement ParameterNameAware like:
public class sample implements ParameterNameAware(){
public boolean acceptableParameterName(String parameterName) {
if (("amount".equals(parameterName) ||
"sourceAccount".equals(parameterName) ||
"destinationAccount".equals(parameterName))
return true;
else
return false;
}
}
This method is called for the excluded properties of param properties.
So, you need to configure params interceptor to exclude all parameters, so the acceptableParameters get the chance to be called by params interceptor.
<interceptor-ref name="params">
<param name="excludeParams">\w+((\.\w+)|(\[\d+\])|(\(\d+\))|(\['\w+'\])|(\('\w+'\)))*</param>
</interceptor-ref>
Am I correct?! This seems some how strange for me (Excluding all parameters and then adding them in each action).
The Struts2 params interceptor behavior against accepting or declining parameters could be extended via the ParameterNameAware action. All parameters are handled by this interceptor if they are accepted or ignored if they are excluded. The extension point checks for accepted parameters. If they are accepted by the interceptor then they are passed, nevertheless additional checks is performed by calling acceptableParameterName but it useless if parameter is accepted by the interceptor. On the other hand if parameter is excluded by the interceptor then calling this method makes a power. Coexisting both methods looks strange because they are designed to be mutually exclusive.
I know that S2 provides a clean way to fetch the request parameters in you action class all you need to follow these simple rules.
Create a property with same name as request parameter name.
Create getter and setters for this property or make property public (for S2.1+)
However, when I do this in an AJAX call like this:
$.ajax({
url: '/gma/getJSONData.action?tspName='+tspName+'&thresholdType='+thresholdType,
I don't get the tspName parameter inside action class. I created the getter/setter for it. It's displaying null value.
Am I wrong somewhere?
EDIT:
I was checking the value of tspName in my Action class constructor, so was printing null. However, in my execute method it displays the value correctly. Why is it so? It means before constructor call it does not initialize values?
I was checking the value of tspName in my Action class constructor, so
was printing null. However, in my execute method it displays the value
correctly. Why is it so?? It means before constructor call it does not
initialize values?
Probably you should learn the basics how Struts2 works. When you make a request a filter is invoked and the dispatcher is handling the request via creating the action context and building action instance.
Then interceptors are invoked on this action. One of the interceptors of the defaultStack is params interceptor. It's responsible to populate your action with request parameters, to be more Struts2 action context parameters.
It means you can always get parameters from the action context. See How can we access request parameters passed into an Action.
The constructor of the action is called before any interceptor is invoked, so the action is not populated yet and properties aren't initialized. On the other hand when the action is executed all interceptors are already invoked, so the action is populated. Before constructor or after constructor it doesn't matter. What is matter is params interceptor in the action configuration.
You can always get parameters like described in the link above, or directly from the servlet request like in this answer. All features of Struts2 framework is available to you.