1

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

user2607126
  • 23
  • 2
  • 6
  • [Check this question.](http://stackoverflow.com/questions/16265052/validate-struts2-form-other-than-validation-framework) – Roman C Jul 22 '13 at 15:21
  • They should be retained; are you using a `chain` or `redirectAction` for you `input` result ? Do you have getters and setters for the `profile` object in the Action ? – Andrea Ligios Jul 22 '13 at 16:14
  • I am not using `chain` or `redirectAction`. I do have getters and setters for the `profile` object. – user2607126 Jul 22 '13 at 16:45

1 Answers1

0

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"/>
coding_idiot
  • 13,526
  • 10
  • 65
  • 116
  • Hi coding_idiot. That may be a problem. I haven't tried yet, but how does that account for the `formAction` not being set correctly? – user2607126 Jul 22 '13 at 16:57
  • Because formAction is never submitted as a request parameter! You can simply create a hidden-field to submit formAction and then when it comes back, it'll be auto-populated. – coding_idiot Jul 22 '13 at 17:00
  • I have added `` only to get the same result. The form in the loaded jsp shows `
    `
    – user2607126 Jul 22 '13 at 17:08
  • you need to set formAction first so that it goes fine to JSP and then it'll come back because of that hidden field. What was the value of formAction before this hidden field. – coding_idiot Jul 22 '13 at 18:13
  • It is set correctly initially since I am able to update if it validates correctly. In this example, it satrted as `
    `
    – user2607126 Jul 22 '13 at 18:54
  • hmm... well nothing can't be done, unless I see your action code. Also, have you tried with defaultStack ? – coding_idiot Jul 22 '13 at 20:27
  • I've added the execute methods for the load and update actions. Aren't I using the defaultStack? The stuff that's there is commented out. It will check the file type of the uploaded image. – user2607126 Jul 22 '13 at 20:58
  • There should be, yes, but that section has the trouble with the logic involving the profile object. Looking at just a bare variable: formAction does not get set properly and has all of the correct getters and setters. – user2607126 Jul 23 '13 at 12:21
  • UPDATE: It appears I had the getters and setters in the wrong action file for the formAction. It now works but the rest of the fields don't. I have changed it so their value no longer has the "profile." part. It is now like what you said `` – user2607126 Jul 24 '13 at 13:42
  • yes, again i had the methods in the wrong action. thank you for your help – user2607126 Jul 26 '13 at 13:59