Passing messages from action to JSP in struts2 - struts2

I am trying to use addActionMessage() and addActionError() to pass messages and error from actions (e.g. in execute()) to the forwarded page.
In the JSP, I use:
<s:if test="hasActionMessages()">
<s:actionmessage/>
</s:if>
to display such messages.
But no message is shown. I am wondering if anyone could give a fix on this problem, or suggest another solution. I am new to Struts and web development, and I am not sure what is a proper pattern for passing messages from actions to pages.
EDIT: action-mapping code and java code
<action name="myAddUser" class="org.any.backend.action.UserAdminAction" method="addUser">
<result name="success" type="redirectAction">myUserAdmin</result>
<result name="input" type="redirectAction">myUserAdmin</result>
</action>
Java code:
public String addUser() throws Exception {
// check duplicate
for (User u : userList)
if (u.getUserName().equals(userName)) {
addActionError("A user with the same user name already exists. Choose another user name. ");
return INPUT;
}
if (userName != null && !userName.isEmpty() && password != null && !password.isEmpty()) {
User newUser = new User();
newUser.setUserName(userName);
newUser.setPassword(password);
userList.add(newUser);
addActionMessage("User " + userName + " added. ");
return SUCCESS;
} else {
addActionError("User name and password cannot be empty");
return INPUT;
}
}

Your code is right.
Maybe you are using a REDIRECT-ACTION result type, or a CHAIN.
They both will lose action messages and errors, forcing you to put them in session (and clean them once displayed) for this page.
EDIT: I'm assuming that you are using the block
<s:if test="hasActionErrors()">
<s:actionerror />
</s:if>
<s:if test="hasActionMessages()">
<s:actionmessage/>
</s:if>
and not only the posted one, or you will never see the errors, only the messages...

Use session.setAttribute(...) in Action Class. and <logic:present .... > tag in jsp.
hope this will help you.

As I have seen you are using redirect action, you can still keep the action error/messages using one of the interceptors.
http://struts.apache.org/2.3.1.2/docs/message-store-interceptor.html
Here's an example in the struts.xml
<action name="submit"
class="com.dummy.SubmitAction">
<interceptor-ref name="store">
<param name="operationMode">STORE</param>
</interceptor-ref>
<interceptor-ref name="defaultStack" />
<result name="success" type="redirectAction">
<param name="actionName">view</param>
<param name="asnid">${id}</param>
</result>
</action>
<action name="view"
class="com.dummy.ViewUserAction">
<interceptor-ref name="store">
<param name="operationMode">RETRIEVE</param>
</interceptor-ref>
<interceptor-ref name="defaultStack" >
<param name="workflow.excludeMethods">execute</param>
</interceptor-ref>
<result name="success">pages/user.jsp</result>
</action>

Related

struts2 tokensession not setting request in Action excludedMethod [duplicate]

This question already has an answer here:
Prevent same action called twice as long as user is in current session
(1 answer)
Closed 5 years ago.
I'm trying to avoid double-submit problems using tokenSession. My action methods are working fine without tokenSession technique.
I add <s:token/> in upsert_crypto_sources.jsp and tokenSession interceptor in struts.xml but I receive request as null in my action excludedMethod of list().
The list page doesn't need to avoid double submit problem but if I add <s:token/> in view_crypto_sources_list.jsp and remove list() from excludedMethod then I always receive result invalid.token.
My struts.xml is like:
<struts>
<package name="key-manager" namespace="/shared/km" extends="console-default" strict-method-invocation="true">
<action name="manage_cs_*" method="{1}" class="console.shared.km.ASC_ManageCryptoProfilesAction">
<interceptor-ref name="tokenSession">
<param name="excludeMethods">
list, initInsert, load, delete
</param>
</interceptor-ref>
<result name="list">/shared/km/view_crypto_sources_list.jsp</result>
<result name="insert">/shared/km/upsert_crypto_sources.jsp</result>
<result name="update">/shared/km/upsert_crypto_sources.jsp</result>
<result name="load">/shared/km/upsert_crypto_sources.jsp</result>
<allowed-methods>list, insert, load, update, delete, testConnection, forward, cancel</allowed-methods>
</action>
My action implements ServletRequestAware interface therefore it gets the request member variable set using setServletRequest() method.
I added a defaultStack interceptor and it is working fine:
<struts>
<package name="key-manager" namespace="/shared/km" extends="console-default" strict-method-invocation="true">
<action name="manage_cs_*" method="{1}" class="console.shared.km.ASC_ManageCryptoProfilesAction">
<interceptor-ref name="defaultStack"></interceptor-ref>
<interceptor-ref name="tokenSession">
<param name="excludeMethods">
list, initInsert, load, delete
</param>
</interceptor-ref>
<result name="list">/shared/km/view_crypto_sources_list.jsp</result>
<result name="insert">/shared/km/upsert_crypto_sources.jsp</result>
<result name="update">/shared/km/upsert_crypto_sources.jsp</result>
<result name="load">/shared/km/upsert_crypto_sources.jsp</result>
<allowed-methods>list, insert, load, update, delete, testConnection, forward, cancel</allowed-methods>
</action>

How can I change action class entry in struts.xml dynamically?

I have an application where I want to modify(or overwrite) action mapping in struts.xml with new entry.
For detailed explanation here is the scenario.
In my application I have different stages like registration, change_data, I am managing these using context Param.
Web.xml
<context-param>
<description>Current stage of the application</description>
<param-name>stage</param-name>
<param-value>registration</param-value>
</context-param>
I have an action which is redirect request for Payment Gateway i.e payment gateway is sending user to this action.
struts2.xml (demo entries)
<!-- for registration -->
<action name="paymentResponse" class="abc.xyz.PaymentResponse">
<result name="input" type="tiles">paymentForReg.tiles</result>
<result name="success" type="tiles">home.tiles</result>
</action>
<!-- for change data -->
<action name="paymentResponse" class="abc.xyz.PaymentResponseForChangeData">
<result name="input" type="tiles">paymentForChangeData.tiles</result>
<result name="success" type="tiles">home.tiles</result>
</action>
So when stage of the application changes, what I am doing is changes stage in web.xml and commenting one entry from of action from struts.xml
So to summarize I have multiple actions with same name and I want to trigger(or change class name of action) action on the basis of context param. is there any way to do it?
If i am not wrong i think you have to use dynamic action like below then you can use the same action and same entry in xml
struts.xml:
<action name="paymentResponse" class="abc.xyz.RedirectPaymentResponse" method="updateCriteria">
<result name="response" type="tiles">paymentForChangeData.tiles</result>
<result name="responsechanged" type="tiles">paymentForReg.tiles</result>
<result name="success" type="tiles">home.tiles</result>
</action>
Action class:
public class RedirectPaymentResponse extends AbstractAppAction {
public String execute () throws Exception
{
// some code
return "success";
}
public String updateCriteria(){
//logic here
if(PaymentResponse){
// code here
return "response";
}
if(PaymentResponseChanged){
// code here
return "responsechanged"
}
}

Unable to map when file is not existed in file downloading in struts 2

I am developing a web application using struts2 .. In that I am downloding a file when user clicks a link ..
When user clicks the link I am checking in my action class whether requested file is existed or not if it is existed then it is working fine ...
WHen it is not existed I am giving a action error message .. But That page is redirecting to error page that i have mapped globally .. IN my console ther is no exception message except these error lines ..
Can not find a java.io.InputStream with the name [fileInputStream] in the invocation stack. Check the <param name="inputName"> tag specified for this action.
And I can see that action message in my error page ... I have debugged the problem also .. Mapping also perfect ..
<action name="downloadAction" class="DownloadPDFAction" method="pdfDownload" >
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="inputName">fileInputStream</param>
<param name="contentDisposition">attachment;filename="${downloadDoc}".pdf</param>
<param name="bufferSize">1024</param>
</result>
Is It possible to map back to the same JSP when The file is not existed in SYSTEM .. Thanks
Check whether the file exists or not in the action, and return success & error respectively. You can do something like this :
<action name="downloadAction" class="DownloadPDFAction" method="pdfDownload" >
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="inputName">fileInputStream</param>
<param name="contentDisposition">attachment;filename="${downloadDoc}".pdf</param>
<param name="bufferSize">1024</param>
</result>
<result name="error">/error.jsp</result>
error.jsp
<s:actionerror/>
<s:actionmessage/>
or your hard-coded message
But since, you need to go back to the same page, then I suggest calling the download action using ajax and return 200 on success and 204 on error something like this :
<action name="downloadAction" class="DownloadPDFAction" method="pdfDownload" >
<result name="success" type="stream">
<param name="contentType">application/octet-stream</param>
<param name="inputName">fileInputStream</param>
<param name="contentDisposition">attachment;filename="${downloadDoc}".pdf</param>
<param name="bufferSize">1024</param>
</result>
<result name="error" type="httpheader">
<param name="status">204</param>
</result>
The ajax call can be something like - docs
$.ajax({
statusCode: {
404: function() {
alert( "page not found" );
},
204: function() {
alert( "file not found" );
}
}
});

Send URL Message as Parameters

In servlets I used
response.sendRedirect("index.jsp?msg=Login failed");
msg after ? to send message while redirecting.
How to do same things with struts2
Since redirection is via struts.xml
<result name="error">/index.jsp</result>
I am just a beginner in struts framework
in your action class which extends ActionSupport:
addActionError("Login failed");
in your index.jsp:
<s:actionerror/>
<result name="error" type="redirect" >
<param name="location">index.jsp?msg=${actionMessage}</param>
<param name="parse">true</param>
<param name="encode">true</param>
</result>

Struts2: interceptor and parameters

i have done some pages with Struts 2.(J2EE project)
All was ok until i try to add an interceptor.
It seems that the Interceptor delete all properties of my Class Action and Parameters send by the jsp with url like: action?param=xxx
here is the interceptor:
public class SessionInterceptor extends AbstractInterceptor{
#Override
public String intercept(ActionInvocation invocation) throws Exception {
return invocation.invoke();
}
here is the struts.xml:
<action name="movefc_ShowFjt" class="struts2.ShowFjtAction" method="movefc">
<interceptor-ref name="sessionInterceptor"></interceptor-ref>
<result name="input" type="dispatcher">jsp/showFjt.jsp</result>
<result name="success" type="dispatcher">jsp/showFjt.jsp</result>
</action>
in the class action,
public class ShowFjtAction extends ActionSupport {
private String param;
private Personne p;
param property never receive value from the jsp (it is ok when interceptor is off). Worse, other properties in Class action seems to be erased.
Is that an normal effect of the return invocation.invoke(); of the interceptor ?
Is there anything i can do to fix that ?
y defining your own interceptor are you causing all of the default interceptors to be discarded?
Should you perhaps be defining an interceptor stack which includes your interceptor and the default stack?
<package name="default" extends="struts-default">
<interceptors>
<interceptor name="sessionInterceptor" class="SessionInterceptor"/>
<interceptor-stack name="myStack">
<interceptor-ref name="sessionInterceptor"/>
</interceptor-stack>
</interceptors>
<action name="movefc_ShowFjt"
class="struts2.ShowFjtAction">
<interceptor-ref name="myStack"/>
<result name="input" type="dispatcher">jsp/showFjt.jsp</result>
<result name="success" type="dispatcher">jsp/showFjt.jsp</result>
</action>
The entire concept is explained as follows
1] First when user does not writes any interceptors, then interceptors defined in struts-default.xml will be used. It is defined in struts-core.jar, it is accomplished by extending the "struts-default" extended in our package xml tag.
2] When user writes his own interceptor if you add one mode code block after sessionInterceptor ref name i.e interceptor-ref name="defaultStack" will solve your problem.
Befor trying this try to unzip the struts-core.jar and move forward with your implementation.

Resources