I need to override the default conversion messages
So, I m trying to make a custom conversion error interceptor for my application which would be called instead of struts default interceptor
Below mentioned is the code for that
public class MyConversionErrorInterceptor extends ConversionErrorInterceptor {
private static final long serialVersionUID = 1L;
protected Object getOverrideExpr(ActionInvocation invocation, Object value) {
ValueStack stack = invocation.getStack();
return (String)stack.findValue("myproj.item");
}
protected boolean shouldAddError(String propertyName, Object value) {
return true;
}}
Here is the struts.xml configuration mentioned.
<interceptors >
<interceptor name="conversionError" class="com.celtic.cmvs.webapp.interceptor.MyConversionErrorInterceptor" />
<interceptor-stack name="myDefaultStack">
<interceptor-ref name="conversionError" />
<interceptor-ref name="defaultStack"/>
</interceptor-stack>
But it doesn't work.
Thanks in advance
I see a few possibilities.
The struts2 conversionError interceptor is still going to be called. If you want yours instead of the standard one, you need to define the entire stack yourself, with your interceptor in place of the standard one.
You might want to change the configured name of the custom interceptor so that it is not the same as the standard one. Otherwise, interceptor-ref name="conversionError" may still be pointing to the standard interceptor.
You need to make sure that your new stack is used. You can do that either by declaring it as the default stack, or by referencing the custom stack inside a specific action.
I have a tutorial on custom interceptors in my blog that may be useful: http://ddubbya.blogspot.com/2011/01/creating-custom-struts2-interceptors.html
Related
I'm trying to find a way to configure in struts.xml an error message for each type of exception that can be thrown by an Action class. In an action class I could accomplish something similar by catching an exception, calling addActionError(String), and rethrowing the exception (provided an <exception-mapping> exists). Is there a way to do this through configuration?
As a reference point, this functionality exists in Struts1 with the key attribute on an exception handler - I'm hoping to be able to do something similar.
<exception key="some.key"
type="java.io.IOException"
handler="com.yourcorp.ExceptionHandler"/>
In strut2 also you can define exception mappings. Refer http://struts.apache.org/release/2.1.x/docs/exception-configuration.html. You can have a common error.jsp which displays a message that is looked up based on the class name of the exception.
In Struts2 you can use the following mapping to pass on the key/message to result (result can be a jsp or another action class).
<global-exception-mappings>
<exception-mapping exception="com.test.exception.MyCustomException" result="error">
<param name="param">display.custom.error</param>
</exception-mapping>
</global-exception-mappings>
<global-results>
<result name="error" type="chain">handleAction</result>
</global-results>
<action name="handleAction" class="HandleExceptionAction">
<result name="result">/WEB-INF/jsp/error.jsp</result>
</action>
If it an action class, in case of chaining (if the user wants to process the exception) then you need to have a corresponding attribute in Action class with getters and setters.
public class HandleExceptionAction extends ActionSupport implements
ServletRequestAware, SessionAware {
private **String param**;
private HttpServletRequest httpRequest;
private static final Log LOG = LogFactory.getLog(InputAction.class);
public String execute(){
LOG.debug("inside excute().....");
LOG.debug("Parameter passed:" + param);
System.out.println("Parameter passed:" + param);
return "result";
}
I am using spring injection, hope it will hep you.
I have a question with respect to interceptors in Struts2
Struts2 provides very powerful mechanism of controlling a request using Interceptors. Interceptors are responsible for most of the request processing. They are invoked by the controller before and after invoking action, thus they sits between the controller and action. Interceptors performs tasks such as Logging, Validation, File Upload, Double-submit guard etc.
I have taken this above lines from:
http://viralpatel.net/blogs/2009/12/struts2-interceptors-tutorial-with-example.html
In this example you will see how the interceptors are invoked both before and after the execution of the action and how the results are rendered back to the user.
I have taken this above lines from
http://www.vaannila.com/struts-2/struts-2-example/struts-2-interceptors-example-1.html
I have written a basic interceptor and plugged it to my Action class:
public class InterceptorAction implements Interceptor {
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("Action class has been called : ");
return success;
}
}
struts.xml
<action name="login" class="com.DBAction">
<interceptor-ref name="mine"></interceptor-ref>
<result name="success">Welcome.jsp</result>
<result name="error">Login.jsp</result>
</action>
As per the above statements from their sites , i assumed that this line Action class has been called would be two times on the console (That is before the Action and after the Action class ) , but it has been printed only once?
PLease let me know , if my understanding is wrong , or the authors were wrong in that site ??
Not taking the time to read the page lets clear a few things up...
You are missing an important step in your interceptor.
Struts2, uses an object called ActionInvocation to manage calling the interceptors.
Lets give ActionInvocation a name (invocation) and show how the framework starts the ball rolling:
ActionInvocation invocation;
invocation.invoke(); //this is what the framework does... this method then calls the first interceptor in the chain.
Now we know interceptors can do pre-processing and post-processing... but the interface only defines one method to do the work of the interceptor (init and delete are just life cycle)! If the interface defined a doBefore and doAfter it would be easy so there must be some magic, happening...
As it turns out you are responsible for giving control back to action invocation at some point in your interceptor. This is a requirement. If you don't give control back to the ActionInvocation you will break the chain.
So when creating an interceptor you do the following steps
Create a class which implements com.opensymphony.xwork2.interceptor.Interceptor
[optional] do pre-processing work
call ActionInvocations invoke method to carry on processing down the stack and capture the return value.
[optional] do post processing as the above call unwinds.
return the string from step 3 (the result string) unless you have reason to do otherwise.
And here is a complete but pretty useless example:
package com.quaternion.interceptors;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.interceptor.Interceptor;
public class MyInterceptor implements Interceptor{
#Override
public void destroy() {
//nothing to do
}
#Override
public void init() {
//nothing to do
}
#Override
public String intercept(ActionInvocation invocation) throws Exception {
System.out.println("Something to do before the action!");
String resultString = invocation.invoke();
System.out.println("Something to do after the action!");
return resultString;
//if you are not doing post processing it is easiest to write
//return invocation.invoke();
}
}
I would like to apply a variable in the session scoped using before the view is displayed, than this view will use this variable.
Here is the link:
<h:link value="#{msg.persondeactivate}" outcome="persondeactivate" />
Here is the faces-config.xml
<navigation-rule>
<navigation-case>
<from-outcome>persondeactivate</from-outcome>
<to-view-id>/deactivatePerson.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
Here is the view (deactivatePerson.xhtml):
...<h:outputText value="#{msg.personIsDeactivate}" rendered="#{controller.personDeactivated}" style="color:green" />... <h:commandButton action="#{controller.deaktivieren}" value="#{msg.deactivate}"></h:commandButton>...
Here is the managed bean:
#ManagedBean #SessionScoped public class Controller { ... private boolean personDeactivated = false; public String deaktivieren(){ personDeactivated = false;
// Deactivate process personDeactivated = true; return "persondeactivate";} ... }
I want that the variable personDeactivated is set to false before the view (deactivatePerson.xhtml) for the second time by is called.
It does not work.
Can someone please tell me what is wrong?
Thanks in advance.
You can use <f:event type="preRenderView"> to invoke a backing bean listener method before the view is rendered.
<f:event type="preRenderView" listener="#{controller.onPreRenderView}" />
with
public void onPreRenderView() {
if (!FacesContext.getCurrentInstance().isPostback()) {
// Do your job here when the view is been freshly requested by GET.
}
else {
// Do your job here when a POST request is been performed by command link/button.
}
}
Unrelated to the concrete problem, I have the impression that the Controller is actually in the wrong scope. A much better solution would be to make it #ViewScoped instead. This way the bean instance will be freshly created on every new GET request and live as long as you're POSTbacking to the very same view (and thus you won't encounter inconsitenties and unintuitive behaviour when having the same page open in multiple browser tabs/windows in the same session which would share the very same session scoped bean!). See also How to choose the right bean scope?
I am new for JSF. In my project am using #ManagedBean, #RequestScoped. Am using 4 pages in my project. My problem was bean values not maintain in the second, third and fourth pages. Am using getter and setter properly. If i not use #ManagedProperty the bean value maintained properly. But i need to use the
#ManagedProperty. Could you please advise me how to solve this issue. I have copied some sample code for reference.
#ManagedBean
#RequestScoped
public class ArticlePrepToolManagedBean implements Runnable, Serializable {
#ManagedProperty (value="#{param.jidName}")
private String jidName;
#ManagedProperty (value="#{param.aidName}")
private String aidName;
private List<com.elsevier.ArticlePrepTool.db.ItemZipContains> usabilityDetailList = null;
public String getAidName() {
return aidName;
}
public void setAidName(String aidName) {
this.aidName = aidName;
}
public String getJidName() {
return jidName;
}
public void setJidName(String jidName) {
this.jidName = jidName;
}
public List<ItemZipContains> getUsabilityDetailList() {
return usabilityDetailList;
}
public void setUsabilityDetailList(List<ItemZipContains> usabilityDetailList) {
ArticlePrepToolManagedBean.usabilityDetailList = usabilityDetailList;
}
}
My project url is (http://localhost:8080/articlepreptool/) but input for my project is jidName=AEA aidName=10663. that input given by some other webpage that is if user trigger using the following href "PrepTool". Depends on the input i fetched some data in my project DB (using JPA) and list out the data in the first page. But if i goes to next page all previous data stored in that list which i got from DB was cleared that is all list values and variables which set in the bean becomes null. So could you please advise me how to solve this issue.That problem occured only if i used the #ManagedProperty. I used #ManagedProperty to fetch the input values comes through url, because the input values of my project comes through other web page.
A #ManagedProperty("#{param.foo}") basically sets the HTTP request parameter with name "foo" as a bean property directly after bean's construction. If you're retrieving null values for them, then it simply means that those parameters are not present in the HTTP request.
Assuming that you're navigating by a plain link, then you need to fix your links to include the request parameters:
<h:link value="Go to page2" outcome="page2">
<f:param name="jidName" value="#{bean.jidName}" />
<f:param name="aidName" value="#{bean.aidName}" />
</h:link>
This will result in something like:
<a href="page2.xhtml?jidName=foo&aidname=bar">
This way those parameters can be set as bean properties.
Alternatively, instead of #ManagedProperty you could also use <f:viewParam> on all pages and add includeViewParams=true to the outcome. See also ViewParam vs #ManagedProperty(value = "#{param.id}")
If you're navigating by a form submit, then there's really no reason to use them. Or you must be abusing forms instead of links for plain vanilla page-to-page navigation.
I got an interceptor that I'm trying to get to output a stream when a certain action is calling. This is part of my code in the inteceptor:
InputStream inputStream;
public String intercept(ActionInvocation invocation) throws Exception
{
if (currAction.contentEquals("actionToTest"))
{
String result = "TRUE";
inputStream = new ByteArrayInputStream(result.getBytes("UTF-8"));
return "resultToGiveStream";
}
}
inputStream has got it's own getters and setters.
And in struts.xml:
<global-results>
<result type="stream" name="resultToGiveStream">
<param name="contentType">text/plain</param>
<param name="inputName">inputStream</param>
</result>
</global-results>
But when I call actionToTest I only receive this in my console:
2011-maj-18 11:19:16 com.opensymphony.xwork2.util.logging.commons.CommonsLogger error
ALLVARLIG: Can not find a java.io.InputStream with the name [inputStream] in the invocation stack. Check the <param name="inputName"> tag specified for this action.
Is it a lost cause to get it to output what I want? I haven' found anyone doing anything similar.
This code is an atempt for a workaround for my other question.
Struts2 is looking for the getInputStream() method on your action and it isn't finding it.
You could try placing the inputStream on the stack manually from within the interceptor. Something like:
invocation.getInvocationContext().put("inputStream", inputStream);