I have a stripes action page. and When the page loads, I want to save an originalAssignee by assigning it from an object (i.e setOriginalAssignee (userAction.getAssignee())) so that in case if the object's field assignee is changed i will do some computing. Here is my action bean:
@UrlBinding("/action/view-details.page")
public class ActionListViewPage extends CustomAction {
.
.
.
private static final String ACTION_LIST_VIEW = "/action/view-details.jsp";
private static final String ACTION_HOME_PAGE="/action/dashboard.page";
private SecurityPerson originalAssignee;
private UserAction userAction;
public UserAction getUserAction() {
return userAction;
}
public void setUserAction(UserAction userAction) {
this.userAction = userAction;
}
public SecurityPerson getOriginalAssignee() {
return originalAssignee;
}
public void setOriginalAssignee(SecurityPerson originalAssignee) {
this.originalAssignee = originalAssignee;
}
@DefaultHandler
public Resolution showUserAction() {
if(userAction==null){
flash("error", "Can't find the the specified User action." );
return new RedirectResolution(ACTION_HOME_PAGE);
}
setOriginalAssignee(userAction.getAssignee());// This one works fine and assigns the the assignee to originalAssignee for future reference
return new ForwardResolution(ACTION_LIST_VIEW);
}
public Resolution saveUserAction() {
try {
if(!originalAssignee.equals(userAction.getAssignee())){
userAction.setStatusEnum(StatusEnum.RE_ASSIGNED);
userAction.setAssignedBy(getCurrentUser(getRequest()));
userAction.setAssignedTimestamp(new Date());
}
if (userAction.getStatusEnum() == null) {
userAction.setStatusEnum(FinAidActionStatusEnum.UNASSIGNED);
}
userAction.save();
flash("ok", "User Action change has been saved to the database. ");
}
catch (Exception e) {
flash("error", "Error saving UserAction./n " + e.getMessage());
}
return new RedirectResolution(ACTION_HOME_PAGE);
}
}
part of the view-details.jsp page looks like this
<stripes:form beanclass="${actionBean.class}" name="actionListForm" id="actionListForm" method="POST"
action="view-details.page?saveUserAction=1"
style="padding-left:20px;">
**<stripes:hidden name="originalAssignee"/>**
<tr>
<td align="left"> Assign to:</td>
<td align="right">
<stripes:select name="userAction.assignee" value="${actionBean.userAction.assignee}"
onchange="$('actionListForm').submit();">
<stripes:option value=""> </stripes:option>
<stripes:options-collection collection="${actionBean.assigneeList}"
label="person.name"/>
</stripes:select>
</td>
</br> </br>
</tr>
<tr>
<td>
Status:
</td>
<td>
<stripes:select name="userAction.statusEnum" onchange="$('actionListForm').submit();"
value="${actionBean.userAction.statusEnum}">
<stripes:option value=""> </stripes:option>
<stripes:options-enumeration enum="uiowa.maui.biz.finaid.enums.FinAidActionStatusEnum"/>
</stripes:select>
</td>
</tr>
<stripes:hidden name="userAction"/>
</stripes:form>
As you can see from my code i used hidden variable to keep originalAssignee ... but when the saveUserAction method is called, it says the originalAssignee is null. I shouldn't figure out the reason. Is there a change i should make on the Forward or Redirect resolution?
FYI: userAction is a hibernate persistent object. Thank you.
This is what I have when i see the source
However, when I add "
value="${actionBean.originalAssignee}"
" to the hidden var .. and it worked fine. I don't know why the original code is not working but, for now at least it solved the problem.FYI: If you can provide why the previous one is not working and your solution is better than mine, I will make your's the solution. So, feel free to add your answer.
The reasons is because Stripes default input tag population strategy first looks at request parameters and then at the ActionBean values:
Check out https://stripesframework.atlassian.net/wiki/display/STRIPES/Tag+Library+Doc section Input Tag Population and Repopulation"
You can change this behaviour system-wide by using the
BeanFirstPopulationStrategy
. There are also ways to limit this behaviour to a specific bean: https://stripesframework.atlassian.net/wiki/display/STRIPES/Overriding+PopulationStrategy+per+ActionBeanYour problem is with type conversion / formatting.
Within the HTTP protocol data can only be represented as Strings. So all HTML form values need to be formatted as String values and when the setter on the action bean is called type conversion is needed. Out of the box Stripes has type converters / formatters for int, long, date etc.
But logically Stripes can not know how to format/convert your own self made classes, thus you either need to use getters and setters with String values (or any other already known type) and do the mapping to your own types your self. Or you need to extend the type conversion/formatting system of Stripes by providing custom Formatter/TypeConverters and use the @Validate(converter=UserTypeConverter.class)
See also: http://www.stripesframework.org/display/stripes/Binding+Into+Domain+Models and http://www.stripesframework.org/display/stripes/Validation+Reference
BTW Stripersist packages also contains a EntityTypeConverter / EntityFormatter that will map your JPA entities.