Thanks for all the comments. They've been invaluable. Below is the
result, Mark Vi.
Kalle, I'm using T5.0.9, but I think 5.0.7 would behave similarly.
Yes, I'm trying frantically to keep up with the releases!
As Davor pointed out, if validation has failed then getting the entity
again doesn't overwrite the form in recent releases. I believe,
however, that this only works if you keep everything that can fail in
the onValidate... methods, eg. changePerson is called in
onValidateFromForm instead of in onSuccess for this very reason.
As Martin pointed out, I can avoid getting the entity every time in
onActivate if I use @Persist("flash"), test for null entity in
onActivate, and nullify "flash" fields in cleanupRender, ie. right
before the page is displayed. The reason for the last bit is that
sometimes there's only one onActivate before a page is displayed, so
an attempt to refresh the page won't work because the entity is still
in flash-persistence. A second attempt would work, which is very
disconcerting.
Davor, I like Martin's cleanupRender effect, so I don't think the "new
window" problems you describe occur, and therefore I don't think I
need the @Meta form annotation. Have I missed a corner-case here?
If you're using BeanEditForm, just replace "Form" with "BeanEditForm".
private Long _personId;
@Persist("flash")
private Person _person;
@Component(id = "form")
private Form _form;
@InjectPage
private NextPage _nextPage;
void onActivate(Long id) throws Exception {
_personId = id;
if (_person == null) {
_person = getPersonService().findPerson(_personId);
}
}
Long onPassivate() {
return _personId;
}
void onValidateFromForm() {
if (...a bit of validation logic detects an error...) {
_form.recordError(...);
return;
}
// todo: move this next block back to onSuccess() once TAPESTRY-1972
has been resolved.
try {
getPersonService().changePerson(_person);
}
catch (Exception e) {
_form.recordError(ExceptionUtil.getRootCause(e));
}
}
Object onSuccess() {
_nextPage.onActivate(_personId);
return _nextPage;
}
void cleanupRender() {
_form.clearErrors();
// Clear the flash-persisted fields to prevent anomalies in
onActivate when we hit refresh on page or browser button
_person = null;
}
and of course the hidden version field stuff still applies (it ensures
optimistic locking works, preventing us saving changes to a Person
that has since been updated or deleted by someone else or by us in
another of our windows or tabs):
<t:hidden t:id="version" value="person.version"/>
or if you're using BeanEditForm:
<t:beaneditform t:id="form" object="person" submitLabel="Save">
<t:parameter name="version">
<t:hidden t:id="version" value="person.version"/>
</t:parameter>
</t:beaneditform>
Any more thoughts?
Geoff