struts 2 action error : retrieves values of form properties - java

Problem
I am using jsp to submit a form and struts 2 action class takes care of it. If there is some problem, then i am sending the result to same page with an error message.
Along with the error message, i want to display property values that he had provided while submitting the request.
Source code
Form contains few text fields and few file type inputs.
My CreateRequest.jsp file:
<input type="file" name="attachment" id="myFile1" />
<input type="file" name="attachment" id="myFile2" />
<input type="file" name="attachment" id="myFile3" />
<input type="text" name="operationName" id="operation1" />
<input type="text" name="operationName" id="operation2" />
<input type="text" name="operationName" id="operation3" />
My Action class :
public class CreateRequest extends ActionSupport {
private List<File> attachment;
private List<String> attachmentContentType;
private List<String> attachmentFileName;
private List<String> operationName
// contains getter and setter for each property
public string execute(){
// some logic
//returns error if it fails otherwise success
}
}
struts.xml (Action Servlet) file:
<action name="createRequest"
class="action.CreateRequest">
<result name="success">RequestStatus.jsp
</result>
<result name="input" >CreateRequest.jsp</result>
<result name="error" >CreateRequest.jsp</result>
</action>
HELP
How do i get all those values displayed in CreateRequest.jsp page, when the action class returns error.

use ognl value=" %{operationName[0]}" for text box

Related

Submitting form's data to a java Set

Is it possible to submit a form's data to a java Set in an action of Struts2?
Action code:
class TestAction extends ActionSupport{
private Set<Integer> mySet = new LinkedHashSet<Integer>();
public TestAction(){
}
public String test(){
someMethod(mySet);
}
... Getters/Setters ...
}
Form code:
<form action="test.action" >
<input name="mySet[0]" />
<input name="mySet[1]" />
<input name="mySet[2]" />
<submit />
</form>
The Set is just a collection, and Struts2 has support for any type of collections internally. But for this type of collection you can't use indexes in your OGNL expressions. Try
<form action="test.action" >
<input name="mySet" />
<input name="mySet" />
<input name="mySet" />
<s:submit />
</form>

Why submitting a form with Ajax it's not setting model data using ModelDriven in Struts 2?

I have following situation in code:
Action class:
#NameSpace("/")
public class MyAction extends ActionSupport implements ModelDriven<Car> {
private Car car = new Cart();
#Override
public Car getModel() {
return car;
}
#Action(value = "pageAction", results = {name = SUCCESS, location = "myPage", type="tiles"})
public String showPage() {
return SUCCESS;
}
#Action(value = "formSubmitAction", results = {name = SUCCESS, location = "results.jsp"})
public String formSubmitAction() {
System.out.println(car);
// everything has default values (nulls)
return SUCCESS;
}
}
View for myPage location:
<s:form
namespace="/"
action="pageAction"
method="post" >
<s:push value="model">
<s:textfield name="color" />
<s:textfield name="manufacturer" />
<sj:submit
href="formSubmitAction"
targets="output" />
</s:push>
</s:form>
<div id="output"></div>
results.jsp:
renders empty content into div#output
<s:property value="%{model}" />
<s:property value="%{model.color}" />
<s:property value="%{model.manufacturer}" />
I wonder why is that happening? Model data is not updated after submit.
I'm using struts2-jquery submit tag.
When I'm using simple form submit without Ajax the model is being updated,
but I want to load data asynchronously with Ajax.
How can I achieve that?
The solution is to add ID to form and to sj:submit tag. But I don't know why submit tag inside form wasn't working properly. The correct code is below:
<s:form
id="formId"
namespace="/"
action="pageAction"
method="post" >
<s:push value="model">
<s:textfield name="color" />
<s:textfield name="manufacturer" />
<sj:submit
formIds="formId"
href="formSubmitAction"
targets="output" />
</s:push>
</s:form>
EDIT
As it turns out you only have to add ID to form, and everything works :)
look at link in the comment below
The modelDriven interceptor pushes a model on top of the valueStack. So you can access model properties directly.
<s:property value="%{color}" />
<s:property value="%{manufacturer}" />

Retaining values between multiple JSPs and Actions in Struts 2

My Struts project structure is as follows:
page1->action1->page2->action2->page3
What i need is for a value i entered in an input tag in page1 to be accessed in action2.
Here is my code:
page1:
<div class = "container">
<s:form id = "idinput" method = "post" action = "idEntered">
Enter id: <input id = "txtid" name = "txtid" type = "text" />
<input id = "cmdsubmit" name = "cmdsubmit" type = "submit" value = "enter details" />
</s:form>
</div>
action1:
public class AddId extends ActionSupport {
private int txtid;
//getter and setter
#Override
public String execute() throws Exception {
return "success";
}
}
page2:
<div class = "container">
<s:form id = "formvalues" method = "post" action = "formEntered">
<p>Your id entered is: <s:property value = "txtid" /></p>
First name: <input id = "txtfname" name = "txtfname" type = "text" />
Last name: <input id = "txtlname" name = "txtlname" type = "text" />
Age: <input id = "txtage" name = "txtage" type = "text" />
<input id = "cmdform" name = "cmdform" type = "submit" value = "submit form" />
</s:form>
</div>
action2:
public class AddForm extends ActionSupport {
private String txtfname;
private String txtlname;
private int txtage;
private int txtid;
//getters and setters
#Override
public String execute() throws Exception {
return "success";
}
}
and displaying everything in
page3:
<div class = "container">
ID: <s:property value = "txtid" /><br>
first name: <s:property value = "txtfname" /><br>
last name: <s:property value = "txtlname" /><br>
age: <s:property value = "txtage" />
</div>
this is where I face a problem as txtid is displayed as null, from which I inferred that the value is not passed from page2 to action2
a solution i have come up with is to use
<s:hidden value = "%{txtid}" name = "txtid2 />
in my form in page2 which will allow me to use the value of txtid as txtid2 in action2, this however seems more like a hack than an actual solution, so any other suggestions are welcome.
In the situation where you want to keep the field values passed from one action to another you could configure the scope of the field. Just place the same field with getters and setters in each action, in your case it will be action1 and action2. The field name is txtid. As well as scope interceptor doesn't include in the defaultStack you should reference it in the action configuration.
For example:
<action name="action1" class="com.package.action.AddId">
<result>/jsp/page2.jsp</result>
<interceptor-ref name="basicStack"/>
<interceptor-ref name="scope">
<param name="key">mykey</param>
<param name="session">txtid</param>
<param name="autoCreateSession">true</param>
</interceptor-ref>
</action>
<action name="action2" class="com.package.action.AddForm">
<result>/jsp/page3.jsp</result>
<interceptor-ref name="scope">
<param name="key">mykey</param>
<param name="session">txtid</param>
<param name="autoCreateSession">true</param>
</interceptor-ref>
<interceptor-ref name="basicStack"/>
</action>
Now you have the scope with the key mykey and field txtid under it. Providing accessors to the field in each action will make transfer field value from one action to another.
In the example above used the basicStack which is a skeleton for the interceptor stack and it does not include some interceptors including a validation interceptor.
If you need to have other features to your actions, you should either construct a custom stack or reference other interceptors in the action configuration.

Struts2 Repopulate form information when validation fails

I have a page with a form that is prepopulated with user information. It is a user profile page. I have validation for some of the fields in place but currently my validation method is just hard coded to execute addFieldError("exp", "Cats"); where exp is a variable that is being validated and Cats is a random message. The form has selects and a doubleselect which I am repopulating by executing actions in the jsp. (Seen Below)
This is the entire form:
<s:form action="%{formAction}" method="post" enctype="multipart/form-data">
<div id="buttons">
<s:submit value="Save" />
</div>
<div id="left_column" class="divStyle">
<div id="picture">
<div id="picture_border">
Picture should go here 150px x 150px
</div>
<s:file name="upload" label="File" />
</div>
<hr />
<div id="contact" class="divPad">
<h3>Contact Information</h3>
<s:textfield name="email" value="%{profile.email}" required="true" />
</div>
<hr />
<div id="availabilityDuration" class="divPad">
<h3>When Available</h3>
<s:textfield name="whenAvailable" value="%{profile.whenAvailable}" />
<h3>Availability Length</h3>
<s:textfield name="availabilityLength" value="%{profile.availabilityLength}" />
<h3>Desired Credit</h3>
<s:action name="CreditSelectAction" executeResult="true" />
</div>
</div>
<div id="right_column" class="divStyle">
<div id="basic_info" class="divPad">
<h4>College & Major</h4>
<s:action name="CollegeMajorsSelectAction" executeResult="true" />
<hr />
<h4>Years of Work Experience</h4>
<s:action name="ExpYearsSelectAction" executeResult="true" /> <hr />
<h4>Undergrad</h4>
<s:action name="UndergradSelectAction" executeResult="true" /> <hr />
<h4>Graduation Year</h4>
<s:action name="GradYearSelectAction" executeResult="true" />
</div>
<hr />
<div id="aboutDescription" class="divPad">
<h3>About Me</h3>
<s:textarea name="comments" value="%{profile.comments}" cols="40" rows="10" />
</div>
<hr />
<div id="skillsNeeds" class="divPad">
<h3>Skills</h3>
<div id="userSkillList">
<s:iterator value="profile.skills" status="status">
<div>
<h5 class="formLabels">Skill Description</h5>
<s:textfield name="userSkillDescription_%{#status.count}" value="%{description}" />
<h5 class="formLabels">Years of Experience</h5>
<s:textfield name="userSkillExperience_%{#status.count}" value="%{experience}"/>
<h5 class="removeSkillLink" onclick="removeUserSkill(this);">Remove Skill</h5>
</div>
</s:iterator>
<h5 class="addSkillLink" id="addSkill" onclick="addUserSkill();">Add New Skill</h5>
</div>
</div>
</div>
</s:form>
The dropdowns are populating alright. The problem is that the values that I thought would be saved in the value stack and retained upon reloading the jsp (%{formAction}, %{profile.email}, etc.) are not being retained when I reload the jsp. How do I capture these values and present them when the page is reloaded after the failed validation? I have tried adding them to the session, but that tends to get messy and I'm not sure how to get that to work with the formAction.
Code from struts.xml:
<action name="updateProfile" class="profiles.actions.UpdateProfileAction" method="execute">
<!-- <interceptor-ref name="basicStack"/>
<interceptor-ref name="fileUpload">
<param name="allowedTypes">image/jpeg,image/gif,image/png,image/jpg</param>
</interceptor-ref>
<interceptor-ref name="validation"/>
<interceptor-ref name="workflow"/> -->
<result name="success">/index.jsp</result>
<result name="input">/jsp/editProfile.jsp</result>
</action>
Code snippet from the Action that loads the form:
public String execute()
{
// get the user profile
String result = "success";
//If the profile is null, then the user is new and does not yet have a profile
//NOTE: If the user's profile doesn't exist, when trying to view someone else's
//profile, they will be redirected to edit their own.
if(user.intValue() == 0)
{
logger.info("New User Detected. Returning Failure.");
result = "failure";
}
else
{
//If the userid is null, we are loading the user's profile
//Otherwise, we are viewing someone else's profile
if(userid == null)
userid = user.toString();
profile = dao.selectCurUserById(Integer.parseInt(userid));
// get all of my projects
this.setMyProjects(projectDAO.selectMyProjects(Integer.parseInt(userid)));
// get all of the projects i've been invited to
this.setJoinedProjects(projectDAO.selectJoinedProjects(Integer.parseInt(userid)));
}
return result;
}
Code snippet from that Action that updates the user profile:
public String execute()
{
// request that sent from the client
HttpServletRequest request = ServletActionContext.getRequest();
Map<String, Object> session = ActionContext.getContext().getSession();
profile = new UserProfile();
id = ((authentication.beans.User) session.get("currentUser")).getId();
profile.setId(id);
profile.setEmail(email);
profile.setAvailabilityLength(availabilityLength);
profile.setComments(comments);
profile.setUndergrad(Integer.parseInt(undergrad));
profile.setWhenAvailable(whenAvailable);
profile.setYear(year);
profile.setCredit(credit);
profile.setMajor(Major.getMajor(major));
profile.setCollege(College.getCollege(college));
profile.setExp(exp);
SimpleDateFormat sdf = new SimpleDateFormat("dd-MMM-yy");
profile.setModify(sdf.format(new GregorianCalendar().getTime()));
//If file is not null, then the user is uploading an image for his/her
//profile
if(file != null)
{
byte[] b = new byte[(int) file.length()];
try
{
new FileInputStream(file).read(b);
b = Base64.encode(b);
}
catch (IOException e)
{
// TODO Auto-generated catch block
profile.setComments(profile.getComments() + "\n" + e.getMessage());
}
profile.setPic(b);
}
// get all of the params and then process the user skills
HashMap<String,String[]> params = (HashMap<String,String[]>)request.getParameterMap();
// process the user skills
profile.setSkills(processSkills(params));
// add the userid to the skills
for(int i = 0; i < profile.getSkills().size(); i++){
profile.getSkills().get(i).setUserID(profile.getId());
}
//TODO: Check the result and do error handling
boolean result = dao.updateProfile(profile);
return "success";
}
UPDATE
The problem was pretty much what coding_idiot said. In the action for loading the form, I needed to have getters for the information to initially populate the form (had this). In the action for updating the information, I needed to have setters for the information put into the form AND a getter for where to get the new information if the form should be repopulated after a failed validation. I fixed this by populating the profile object in the validate() function in the update action with the data I got from the form and then providing a setter for the profile object. I did not have to make any changes to my .jsp
I don't know what you've written in your action, but from above I can infer that this is a slight misunderstanding about functionality issue. You are having fields with names - email, whenAvailable etc. but their value is fetched from profile object.
How can you expect to set it from something that doesn't exist ?
To make it more clear :
Values that go from JSP to action is email, but what comes back is profile.email, instead it
should have been just email, or you can simply skip the value attribute or you can change your
field-name to profile.email
Let me know if that helps.
[EDIT]
Reading your question again, the getters and setters for profile won't help, because what
is going into the action is just primitive fields (email etc.) So you should have getters/setters for these fields instead and then to re-populate the fields into the JSP
you can simply use for e.g. :
<s:textfield name="whenAvailable" value="%{whenAvailable}" />
OR
<s:textfield name="whenAvailable"/>

Recieving 'null' values from a jsp page into Struts 2 Action

I have a jsp page and struts 2 Action class . When I submit the form in the jsp , I am getting null values into the action.
The JSP code looks like :
<s:form id="user" name="user" action="initUserAdmin">
<s:textfield name="userName" cssClass="txtbox" size="30" />
<div class="btn"><a href='<s:url action="searchUserAdmin"/>'
title="Search" id="button" class="btn" ><span>Search</span></a></div>
</s:form>
The struts.xml has this part
<action name="*UserAdmin" method="{1}" class="com.mphasis.im.web.action.UserAction">
<result name="init" type="tiles">user</result>
<result name="search" type="tiles">user</result>
<result name="reset" type="tiles">user</result>
<result name="createNew" type="tiles">createNewUser</result>
</action>
And the Action class has this :
public class UserAction extends BaseAction
{
public String userName;
public String getUserName()
{
return userName;
}
public void setUserName(String userName)
{
this.userName = userName;
}
public String search()
{
searchProcessed = true;
System.out.println("******** inside search ******");
System.out.println("username = "+ userName);
return TilesConstants.SEARCH;
}
And the output comes as below when I type a string in the text box in jsp page.
******** inside search ******
username = null
What might be the problem ? Am I missing something ?
<a href='<s:url action="searchUserAdmin"/>'
title="Search" id="button" class="btn" >
It's just a href to the URL of action and with no parameter. Therefore, the 'userName' in the action is null.
<s:form id="user" name="user" action="initUserAdmin">
<s:textfield name="userName" cssClass="txtbox" size="30" />
<div class="btn"><a href='javascript:submitme()'
title="Search" id="button" class="btn" ><span>Search</span></a></div>
</s:form>
Javascript
function submitme(){
document.user.submit()
}
Also in the action mapping you provided the action name you are using there is UserAdmin whereas in the form action you are using initUserAdmin.They must be the same

Categories