In my project I am updating details so I created action, but it gives me exception in response as
No result defined for action org.employee.actions.EmployeeMyProfileAction and result input
In struts.xml (Before)
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<result name="success">empMyProfile.jsp</result>
</action>
(After)
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<result name="success">empMyProfile.jsp</result>
<result name="input">emp-personal-form.jsp</result>
</action>
Ajax Call
function checkPersonal(id) {
if (checkEverythingP()) {
$.ajax({
type : 'POST',
url : 'savePersonalDetails',
data : $('#personalform').serialize(),
success : function(data) {
alert('success');
},
error : function() {
alert('error');
}
});
}
}
It gives me success message in JQuery but It is not going to the action class declared. I didn't understand why it is happening after everything is correct. I referred many sites for this but not resolved. Please suggest me what is going wrong.
Not everything is correct as you thought, because in the success callback function you have received INPUT result. This result is returned by workflow interceptor, which is in the defaultStack - the stack of interceptors used by default if your action doesn't override the interceptors configuration. It checks if an action invocation has validation errors like action errors or field errors (the conversion errors) then returns a result specified by the parameter inputResultName. By default this parameter is set to "input". If the interceptor returns a result it breaks a chain of interceptors and invocation of action method. You noted it saying It is not going to the action class declared.
The solution is to override interceptors configuration of the action to use basic stack, i.e. without validation and/or workflow interceptors.
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<interceptor-ref name="basicStack"/>
<result name="success">empMyProfile.jsp</result>
</action>
If you still need to perform validations you can do it programmatically or configure workflow interceptor to filter your action method. The last option you should use only if you have enough reasons to do so, because it overcomes the purpose of the interceptor itself.
Assumning you know what the INPUT result is and how it works, you are doing the wrong thing here.
When you perform an AJAX call, 1) the result will be parsed (and then eventually injected) in your current page, or, alternatively, you can use that result to perform a redirect by using javascript (window.location = "newUrl";).
You can't return a whole page and then use that response to make a new page (unless inside an iframe or similar, but that's DOM / page manipulation, then case 1).
Then this
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<result name="success">empMyProfile.jsp</result>
<result name="input">emp-personal-form.jsp</result>
</action>
can't be right, because both the result should be an entire page (in case of a classic POST) or a JSP snippet / JSON / whatever (in case of an AJAX CALL).
You should change it to something like
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<result name="success">emp-personal-form.jsp</result>
<result name="input">emp-personal-form.jsp</result>
<result name="error">emp-personal-form.jsp</result>
</action>
and include in the first rows of emp-personal-form.jsp a message with the errors (in case of INPUT or ERROR results), or a message of success (in case of SUCCESS result) and then provide a link to navigate away from the page.
Otherwise, use standard POST and return the same page in case of INPUT or ERROR, or a success page in case of SUCCESS:
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<result name="success">profileCorrectlyUpdated.jsp</result>
<result name="input">empMyProfile.jsp</result>
<result name="error">empMyProfile.jsp</result>
</action>
But nothing prevent you to use standard POST and return in the same page also in case of SUCCESS.
Note: to know how display a (success or error) message only when needed, read this.
Related
I am writing an application using struts2. I am facing a problem in the login part. When a login is performed,it will redirect to the index.jsp page.Now the problem arises. The problem is when after loggin in, index.jsp is reloaded, browser asks me resend data. I dont know why it is happening?
here is my struts.xml code for authenticate action:-
<action name="authenticate" class="com.action.LoginAction">
<result name="success">index.jsp</result>
<result name="failure">loginerror.jsp</result>
</action>
and here is code for the login action class:-
public String execute() {
if(sessionMap.containsKey("project_user")){
return "success";
}
Project_User project_User=Login.checkCredentials(email_id,password);
if(project_User!=null) {
sessionMap.put("project_user", project_User);
return "success";
} else
return "failure";
}
also when index.jsp comes, the url area of browser remians unchanged, the link in url field of browser still shows the action name like:- localhost:8084/Tek-Hub/authenticate/
if anyone knows about it plzzz help me.
Thanxx
You need to use a pattern named PRG (Post / Redirect / Get).
This way, a second request will be performed when executing the first action result (because of the redirection), and a refresh of the landing page (eg. pressing F5) will hit the second action (the GET one), instead of the login action (the POST one).
Change this:
<action name="authenticate" class="com.action.LoginAction">
<result name="success">index.jsp</result>
<result name="failure">loginerror.jsp</result>
</action>
to this:
<action name="authenticate" class="com.action.LoginAction">
<result name="success" type="redirectAction">index.action</result>
<result name="failure">loginerror.jsp</result>
</action>
<action name="index" class="com.action.IndexAction">
<result name="success">index.jsp</result>
</action>
In my project I am updating details so I created action, but it gives me exception in response as
No result defined for action org.employee.actions.EmployeeMyProfileAction and result input
In struts.xml (Before)
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<result name="success">empMyProfile.jsp</result>
</action>
(After)
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<result name="success">empMyProfile.jsp</result>
<result name="input">emp-personal-form.jsp</result>
</action>
Ajax Call
function checkPersonal(id) {
if (checkEverythingP()) {
$.ajax({
type : 'POST',
url : 'savePersonalDetails',
data : $('#personalform').serialize(),
success : function(data) {
alert('success');
},
error : function() {
alert('error');
}
});
}
}
It gives me success message in JQuery but It is not going to the action class declared. I didn't understand why it is happening after everything is correct. I referred many sites for this but not resolved. Please suggest me what is going wrong.
Not everything is correct as you thought, because in the success callback function you have received INPUT result. This result is returned by workflow interceptor, which is in the defaultStack - the stack of interceptors used by default if your action doesn't override the interceptors configuration. It checks if an action invocation has validation errors like action errors or field errors (the conversion errors) then returns a result specified by the parameter inputResultName. By default this parameter is set to "input". If the interceptor returns a result it breaks a chain of interceptors and invocation of action method. You noted it saying It is not going to the action class declared.
The solution is to override interceptors configuration of the action to use basic stack, i.e. without validation and/or workflow interceptors.
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<interceptor-ref name="basicStack"/>
<result name="success">empMyProfile.jsp</result>
</action>
If you still need to perform validations you can do it programmatically or configure workflow interceptor to filter your action method. The last option you should use only if you have enough reasons to do so, because it overcomes the purpose of the interceptor itself.
Assumning you know what the INPUT result is and how it works, you are doing the wrong thing here.
When you perform an AJAX call, 1) the result will be parsed (and then eventually injected) in your current page, or, alternatively, you can use that result to perform a redirect by using javascript (window.location = "newUrl";).
You can't return a whole page and then use that response to make a new page (unless inside an iframe or similar, but that's DOM / page manipulation, then case 1).
Then this
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<result name="success">empMyProfile.jsp</result>
<result name="input">emp-personal-form.jsp</result>
</action>
can't be right, because both the result should be an entire page (in case of a classic POST) or a JSP snippet / JSON / whatever (in case of an AJAX CALL).
You should change it to something like
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<result name="success">emp-personal-form.jsp</result>
<result name="input">emp-personal-form.jsp</result>
<result name="error">emp-personal-form.jsp</result>
</action>
and include in the first rows of emp-personal-form.jsp a message with the errors (in case of INPUT or ERROR results), or a message of success (in case of SUCCESS result) and then provide a link to navigate away from the page.
Otherwise, use standard POST and return the same page in case of INPUT or ERROR, or a success page in case of SUCCESS:
<action name="savePersonalDetails" class="org.employee.actions.EmployeeMyProfileAction" method="updateEmployeeDetails">
<result name="success">profileCorrectlyUpdated.jsp</result>
<result name="input">empMyProfile.jsp</result>
<result name="error">empMyProfile.jsp</result>
</action>
But nothing prevent you to use standard POST and return in the same page also in case of SUCCESS.
Note: to know how display a (success or error) message only when needed, read this.
In plain old servlets I can use doGet and doPost methods. Where in doGet i'm forwarding user to some page and in doPost i'm proccessing data entered from the page that I gave. That all happening in one servlet.
But the Struts2 works on Front Controller pattern and instead doGet/doPost I have only execute method. So how can I properly give user some page, so then he can see it, enter data, submit and application as result proccess it in execute ?
From what I know I have two options (example on registration form):
Map page to another url:
<action name="register_display">
<result name="success" type="dispatcher">register.jsp</result>
</action>
<action name="register"
class="magazine.action.client.RegisterClientAction"
method="execute">
<result name="success" type="redirectAction">/index</result>
<result name="error" type="redirectAction">register_display
</result>
</action>
Create whole package named display and place there all view from which POST can be performed:
<package name="display" namespace="/display" extends="struts-default">
<action name="register">
<result name="success" type="dispatcher">register.jsp</result>
</action>
...
</package>
Is there any other options ? Which one is prefered ?
In the standard Struts2 style, an Action class has only one work method, this is the execute method. However, you do not necessary have to follow this. You can define multiple actions in a single Action class.
For example you make a GET request to users, which is handled in the default execute method of UsersAction.
#Override
public String execute() {
// fetch the list of users
return SUCCESS;
}
Let's suppose you would like to add a new user in this same action, by POSTing to user_add. So you define an add method:
public String add() {
// add the user
return SUCCESS;
}
The struts.xml would look similar to this:
<package name="users" extends="defaultPackage">
<action name="users" class="com.example.UsersAction">
<result>users.jsp</result>
</action>
<action name="user_add" class="com.example.UsersAction" method="add">
<result type="redirect">users</result>
</action>
</package>
In your scenario, you would render your page, which the user should see after the run of the (maybe empty) execute method. Then, you would make the post request, which would be mapped to the other method of the Action class.
I have a slight problem with forwarding using Struts.
Now when users accessing my page like this -> http://mypage/
they are automatically forwarded to /index.jsp.
But I'd also like to have index.jsp to be linked to name "sg".
So when they access page like this :
http://mypage/ > they will be forwarded to http://mypage/sg
which is http://mypage/index.jsp.
As I've already mentioned above I'm using Struts to handle all these action. The below example is what I have in my struts.xml file. But it's working rather partially. When I access the page as stated above I'm getting redirected to http://mypage/sg and it also gives me 404 - Not Found.
However when I try manually accessing the url (http://mypage/sg), it works perfectly.
<package name="index" namespace="/" extends="default">
<action name="">
<result>/sg</result>
</action>
<action name="/sg">
<result>/index.jsp</result>
</action>
</package>
When I access the page as stated above I'm getting redirected to http://mypage.com/sg and it also gives me 404 - Not Found.
Answer :
If you want to call another action as result of one action then you need to mention attribute type of result tag
<action name="">
<result type="redirect">/sg</result>
</action>
This will redirect to action sg.
The redirect result type:
The redirect result type calls the standard response.sendRedirect() method, causing the browser to create a new request to the given location.
I have the following actions defined in my struts.xml
<action name="Search" method="prepareLookUpvalues" class="com.mycompany.actions.FrSearchAction">
<result name="success" type="tiles">search.layout</result>
</action>
<action name="List" class="com.mycompany.actions.FrSearchAction">
<result name="success" type="tiles">results.layout</result>
<result name="input" type="tiles">search.layout</result>
</action>
<action name="SearchDetails" class="com.mycompany.actions.FrSearchDetailsAction">
<result name="success" type="tiles">details.layout</result>
</action>
<action name="Logoff" class="com.mycompany.actions.LogoffAction" >
<result name="success" type="tiles">logoff.layout</result>
</action>
Assuming that a user goes directly to my page home http://localhost:8080/fr/Search.action everything works OK, but it has been discovered hat some users are accessing http://localhost:8080/fr/List.action directly without first going to the search page which is causing problems.
When a user goes to the search page and enters criteria and submits, it is only then that the "List" action should be called via the struts form's action attribute. I basically want to stop users from being able to access the "List", "SearchDetails", and "Logoff" actions directly unless those actions are invoked from my JSPs or code.
I'm new to maintaining/developing Struts2 applications and I haven't found clear answers to this. Any suggestions would be greatly appreciated!
There's a few details missing so the answer will be a bit vague, but the list action probably pulls values from a form submission to search? Or pulls state from session? Or...?
Anyways, however that may be stored, simply check and then redirect the user to Search if the state is not set as expected.
For details on doing redirects in struts2, see, for e.g. http://www.roseindia.net/struts/struts2/actions/struts-2-redirect-action.shtml
This isn't an elegant solution but you could try checking for the referer to see who called the action. You action class will need to implement ServletRequestAware.
String referrer = request.getHeader("referer");
if (referrer.equals("http://localhost:8080/fr/Search.action")) {
// do the action
} else {
// handle unwanted access
}
Remember that the referer is a client-controlled value and can be spoofed or removed.