RE: Best practice for new/edit object page?

2006-07-16 Thread Jim Steinberger
Quick update on this:

If you're persisting the ID of an entity so you don't have to embed it
in the page (the main conclusion from this thread), the pseudocode I
used before with regard to the pageBeginRender implementation has two
potential gotchas in it (found so far).

To refresh, I said: "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."


First, if you're using Hibernate semantics, you'll probably want to
"get" the entity either way, or you'll likely get a
LazyInitializationException depending on what you've OGNL-mapped.


Second, if you're using validation, you need to be careful not to
re-query the object out when rendering after a validation error.
Consider the order:

1.  Submit the form
2.  pageBeginRender(rewind) - queries out object
3.  rewind - sets mapped-form-properties to object
4.  validation - finds error
5.  listener - since there were validation errors, returns "this"
6.  pageBeginRender(render) - queries out object
7.  renders with persisted properties, not the invalid inputs <--
problem


New pseudo-pseudocode for pageBeginRender:
...
if (getValidationDelegate().getHasErrors()) {
  if (id != null) {
setEntity(getEntityService().get(id));
  } else {
setEntity(new Entity());
  }
}
...

i.e. If there were errors, you'll want to render the page with the data
that was entered.


Jim

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



RE: Best practice for new/edit object page?

2006-07-10 Thread Jim Steinberger
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.

Re: Best practice for new/edit object page?

2006-07-10 Thread Jesse Kuhnert

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.
>

RE: Best practice for new/edit object page?

2006-07-10 Thread Jim Steinberger
"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

RE: Best practice for new/edit object page?

2006-07-10 Thread Gentry, Michael \(Contractor\)
You should be aware that PageLink is not session-aware (DirectLink is).
If a user's session times out and they click on a PageLink, they'll see
the normal Tapestry exception page when the code tries to access the
session.  (They won't see the "friendly" stale session page.)

/dev/mrg


-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
&g

Re: Best practice for new/edit object page?

2006-07-10 Thread Malin Ljungh

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.


Re: Best practice for new/edit object page?

2006-07-10 Thread Andreas Bulling
On 10. Jul 2006 - 11:21:49, Gentry, Michael (Contractor) wrote:
| The down side to embedding database IDs in your HTML form is they can be
| changed by the user before POSTing them back to your application, which
| can cause all sorts of problems.

Exactly, this creates _really huge_ security issues...

Anyway, I took the same approach but I've implemented a HiveMind SecurityService
which is called before the object is written back to the database and which
checks if the current user is allowed to execute the requested operation
(read, write, delete, ...) on the object with the id. Otherwise it throws
a SecurityException which is handled by the page class.

This is a quite simple approach but I don't need more so it's sufficient
for my needs. ACEGI integration would be more powerful and flexible - perhaps
in a future version ;-)

HTH
  Andreas

-
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]



RE: Best practice for new/edit object page?

2006-07-10 Thread Gentry, Michael \(Contractor\)
The down side to embedding database IDs in your HTML form is they can be
changed by the user before POSTing them back to your application, which
can cause all sorts of problems.

/dev/mrg


-Original Message-
From: Jim Steinberger [mailto:[EMAIL PROTECTED] 
Sent: Sunday, July 09, 2006 6:56 PM
To: Tapestry users
Subject: RE: Best practice for new/edit object page?


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 

RE: Best practice for new/edit object page?

2006-07-09 Thread Jim Steinberger
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.g