No, that's perfect! Properties we don't want to be changed, we're not exposing to the template at all, because that makes us vulnerable to the user spoofing new values for those properties, even if they're hidden.
So, in pageBeginRender(..), we load the object we want to update, and then in Tapestry's rewind phase, only those properties that were bound to the form are set (and marked dirty), so then in the listener, only those properties that were actually exposed to the user-interface are actually ultimately updated by Hibernate. Meanwhile, no EJB transfer objects ^_^ Jim -----Original Message----- From: Jesse Kuhnert [mailto:[EMAIL PROTECTED] Sent: Monday, July 10, 2006 2:50 PM To: Tapestry users Subject: Re: Best practice for new/edit object page? No that's true, hibernate will only update members that have changed. They modify all of your classes with cglib to add changing listeners to fields/values. (Also how you get lazy initialization). There are still some issues with this though as the current logic in tapestry wrt forms would be that all values get re-parsed on submission and set on your object..Making hibnerate think that you may have changed all of them. (Any members bound to specific form fields at least). On 7/10/06, Jim Steinberger <[EMAIL PROTECTED]> wrote: > > "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] > > -- Jesse Kuhnert Tacos/Tapestry, team member/developer Open source based consulting work centered around dojo/tapestry/tacos/hivemind. --------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]