I was trying out few options, but subclassing is the simplest. When subclassing generic data is preserved, and prop: binding can resolve to actual return type of a method.
generic data is preserved for: - fields : List<String> strings; - methods List<Strings> getNames(List<User> users) - subclasses : class UserEdit extends GenericEdit<User, Long> tapestry currently only handles the third case, and only for getters, when for example: class GenericEdit<T, T_ID>{ public T getEntity(){...} } Davor Hrg On Jan 30, 2008 11:38 AM, Geoff Callender <[EMAIL PROTECTED]> wrote: > Good point, Davor. The way I've used flash persistence it could just > as well have been session persistence. The effect would be identical. > > * Perhaps what we really need is @Persist("redirection")?!?!?! > > It's a serious suggestion. After all, what we're aiming for is > persistence during a redirection and only during a redirection. We > don't want persistence after arriving from PageLink or browser Reload/ > Refresh because it causes anomalies (and that's why Mk VI uses > cleanupRender()). Even better, redirection-persistence could be keyed > by a temporary conversation id behind the scenes. > > What does everyone think? > > * Mk VI might be unacceptable in clustered environments, because it > uses server-side persistence, requiring session replication traffic. > In that situation I guess the options are either the Mk V solution or > some sort of client-side persistence - hidden fields, > @Persist("client"). or something new. > > As for your generic editing, I like it. It's exactly where I wanted > to take this once we have the possible solutions codified. Perhaps an > @EditPage annotation rather than a superclass would be even nicer? > > Cheers, > > Geoff > > > On 30/01/2008, at 1:15 AM, Davor Hrg wrote: > > > cleanupRender is not a fix for flash persistence, it's more like > > replacement for it. > > flash persistence is made for the same reason (only persisting until > > next request) > > > > you can take your example even further and make it generic > > thus allowing actual edit page to be as simple as: > > > > public class EditCompany extends EntityEditPage<Company, Long>{ > > > > @Override > > protected Object getNextPage() { > > return ListCompany.class; > > } > > > > } > > > > > > the generic edit page I'm working on > > gets entity class like this: > > > > @SuppressWarnings("unchecked") > > public AbstractEntityEdit() { > > Type genericSuperclassType = getClass().getGenericSuperclass(); > > if((genericSuperclassType instanceof ParameterizedType)){ > > ParameterizedType genericSuperclass = (ParameterizedType) > > genericSuperclassType; > > if(genericSuperclass.getActualTypeArguments()[0] > > instanceof Class){ > > this.persistentClass = (Class<T>) > > genericSuperclass.getActualTypeArguments()[0]; > > this.idClass = (Class<T_ID>) > > genericSuperclass.getActualTypeArguments()[1]; > > } > > } > > } > > > > uses Session to load entity when needed, > > persists only entityId as string > > uses TypeCoercer to convert string to "idClass" before calling > > session.get() > > > > resets the form if cancel button is pressed or entityId changes > > > > Davor Hrg > > > > > > On Jan 29, 2008 2:48 PM, Geoff Callender > > <[EMAIL PROTECTED]> wrote: > >> 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 > >> > >> > > > > --------------------------------------------------------------------- > > To unsubscribe, e-mail: [EMAIL PROTECTED] > > For additional commands, e-mail: [EMAIL PROTECTED] > > > > --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]