"If the user enters the edit page for an existing item and then clicks the link to create a new item I will have to reset the ID, am I right? My current PageLink will not do in that case."
Right; I'm using DirectLinks in both cases, setting the ID to be either the appropriate ID or NULL if I'm creating a brand new object. One last thought ... that synchronization issue I mentioned ... that might be even /further/ mitigated if using Hibernate, since I'm pretty sure that even even for detached objects, Hibernate will maintain which properties of a loaded object have been modified (i.e. "dirty" flags), and will only update those properties. i.e. if the user-interface is only modifying properties A and B, depending on your setup, Hibernate might only update A and B, and not C and D. This begs for a proper test, though. Jim -----Original Message----- From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of Malin Ljungh Sent: Monday, July 10, 2006 2:23 PM To: Tapestry users Subject: Re: Best practice for new/edit object page? Thank you. Especially Jim, you have understood my "problem" perfectly! The thing is I have a hibernate OR-mapping with lots of relationships and attributes which the user should not edit or see at all in the edit page. I think I'll use your #3 - keeping the ID in the session using @Persist and reload entity from database at postback. My wonder is then - how do I detect the "new entity" scenario? If the user enters the edit page for an existing item and then clicks the link to create a new item I will have to reset the ID, am I right? My current PageLink will not do in that case. Malin On 7/10/06, Jim Steinberger <[EMAIL PROTECTED]> wrote: > > Hi Malin, > > Here are my thoughts: > > 1. Embedding the ID into the page (along with every other property of > the entity). > > Benefit: After the rewind phase sets all the OGNL-mapped properties to > your page-property-object, you can simply pass that object directly to > the service/persistence layers to be saved. > > Downside: This only works if you're comfortable embedding all of the > object's properties in the page. There's a security issue here (if it's > not an SSL connection, for example, you wouldn't want a user's password > or social security number being transferred in cleartext). There's a > practicality issue, too; if your object has a lot of associated > entities, it'd probably be too cumbersome to embed the entire > object-graph inside the page. > > > 2. Embedding the ID into the page (along with, only, properties you > intend to be updatable) > > Downside: I don't know of a great way to do this. As you asked: " but > this means I will have to redo EventServices.getEvent(eventId) after > postback. This could maybe be OK but where do I put the code?" After > all, you need the ID in order to query out the object, but that ID isn't > set via OGNL until after the rewind phase. The problem here, then, is > that you'd have to manually set all the properties to the object in your > listener. > > > 3. Keeping the ID in the session > > Implementation: Instead of setting the ID to the visit object (or > another application-state-object), declare the ID as a property of the > page, and also declare it to be persistent (e.g. the @Persist > annotation). Have your page implement the PageBeginRenderListener, and > in your pageBeginRender method, if the ID is not null, "get" the object > (I'm using Hibernate semantics) if you're not rewinding, and "load" the > object if you are. If you're rewinding, then, you'll query out the > object as it currently appears in the database, and then the rewind > phase will set all the OGNL mapped properties to it (which are the only > ones you intend to be mutable). You can then pass this to the > service/persistence layer in your listener. > > Downside: Very slight RAM overhead (I try to avoid persistent > properties/session data as much as possible, but individual Integer > objects should take awhile to add-up [I say perhaps naively]). > > Benefit: Only the properties intended to be edited will be sent to the > client. > > This also mitigates, by a degree, the synchronization issue inherent to > this. Consider the following scenario: > > Page 1 edits properties A and B. Page 2 edits properties C and D. > > Using scenario 1 above, when user Alpha loads page 1, he sees properties > A and B, and properties C and D are embedded in the page. User Beta > loads page 2, and has the reverse situation. If user Beta then submits > the form, properties C and D will be updated. When user Alpha submits > /his/ form, he'll be updating C and D back to what they were originally. > > This scenario still exists in scenario 3 above -- but the time-window of > this is much much smaller: properties C and D would only be reverted if > user Beta's save occurs between the Page 1's pageBeginRender method and > listener (since it loads the object in the former but doesn't save it > until the latter). > > Still, even this smaller window could well be unacceptable if your > interface allows for this scenario. I don't have a great suggestion for > this, but I'm pretty sure they're there; that people have explored > having transactions that span user-requests. > > > Anyway, I'm currently migrating toward scenario 3, but I'm certainly > open to other suggestions, as I was about to ask exactly this question > of the list : ) > > Jim > > -----Original Message----- > From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf > Of Malin Ljungh > Sent: Saturday, July 08, 2006 5:21 PM > To: Tapestry users > Subject: Best practice for new/edit object page? > > Hi everyone, > > I'm pretty much a newbie on Tapestry and need some help. > > I'm building a simple web application for administering some data in a > database. I use Hibernate for database connection. I'll need several > pages > that will handle insert of new record to table or editing an existing > record. I wan't to use the same page for insert and edit. > My question is basically: How should I build my pages and how should I > handle state between postbacks? > Let me take an example - I have a model object called Event, a page > ListEvents and a page EditEvent. > > This is the essentials of my EditEvent.java: > > public abstract Event getEvent(); > public abstract void setEvent(Event event); > > public void pageBeginRender(PageEvent event) > { > if(getEvent() == null) > // new Event > setEvent(new Event()); > } > > Could/should the thing in pageBeginRender be done by injection instead? > And this is the link between the Event list and the EditEvent page in > ListEvents.java: > > > @InjectPage("EditEvent") > public abstract EditEvent getEditEvent(); > > public IPage editEvent(int eventId) { > EditEvent editEvent = getEditEvent(); > editEvent.setEvent(EventServices.getEvent(eventId)); > return editEvent; > } > > where EventServices.getEvent fetches Event from DB. > > How should I handle state between postbacks? I have put my eventId in a > Hidden in the EditEvent.html like this: > <input jwcid="@Hidden" value="ognl:event.eventId" /> > > but this means I will have to redo EventServices.getEvent(eventId) after > postback. This could maybe be OK but where do I put the code? Or should > I > store the Event instance in my visit state? > > This must be one of the most common scenarios so I guess you all know > how it > should be done - please tell me :) > > Malin > > --------------------------------------------------------------------- > 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]