Could you do what you propose with a custom interceptor stack? Make your first call to getModel() return a serialized copy of the model object and the second call return the managed instance. Internally the action would maintain the reference to the managed instance from the time of the first getModel() or prepare() call.

<interceptor-stack name="JPAparamsPrepareParamsStack">
   <interceptor-ref name="exception"/>
   <interceptor-ref name="alias"/>
   <interceptor-ref name="servletConfig"/>
   <interceptor-ref name="params"/>
   <interceptor-ref name="prepare"/>
   <interceptor-ref name="modelDriven"/>
   <interceptor-ref name="params"/>
   <interceptor-ref name="fileUpload"/>
   <interceptor-ref name="checkbox"/>
<interceptor-ref name="staticParams"/> <interceptor-ref name="conversionError"/> <interceptor-ref name="validation"> <interceptor-ref name="i18n"/>
   <interceptor-ref name="workflow">
       <param name="excludeMethods">input,back,cancel</param>
   </interceptor-ref>
   <interceptor-ref name="modelDriven"/>
   <interceptor-ref name="params"/>
   <interceptor-ref name="checkbox"/>
   <interceptor-ref name="staticParams"/>
</interceptor-stack>

-Chase

Eric D Nielsen wrote:
I've been investigating some interesting behavior regarding model-driven actions
and found a past thread that covers the situation from late last year:
http://www.nabble.com/ModelDriven-CRUD-validation-failure-still-causes-JPA-update-td12987242.html

First I outline the problem, then a possible framework provided solution and a
request for feedback before I start trying to generate a patch.

In brief:
Configuration:
  ModelDriven with validation is configured
  Hibernate/JPA is being used (OpenEntityManagerInView/OpenSessionInView is
something of a red-herring)

Sequence of Events:
  Model is loaded from DB
  Params (second params) inject parameters into the model
  Validation fails
  Input reached
  session.flush occurs (either from closing the session in OSIV pattern, OR from
an implicit flush before an explicit query or a lazy-load query)
  dirty and invalid object written to the DB

In the thread referenced, his solution was to preload all collections backing
form elements -- thus avoiding the lazy-load queries after dirtying the object.
 (This is why I say a lot of the discussion in that thread about the flush in
OEMIV is a red-herring.  It could cause the problem, but wasn't the cause of
the problem)

A lot of the other workarounds suggested in the thread seem very unclean as its
something that should be taken care of by the framework.

To my eye, there is a fundamental flaw in Struts 2 validation (and type
conversion).  Under the model-driven paradigm, validation conditions need to be
viewed as invariants, and either all fields should be set or none -- it should
be atomic.  There is also a violation of the SRP going on by making the model
objects responsible for holding and redisplaying invalid values to the web
form.

It would seem to be a way forward exists, however.  Model Driven can be tweaked
as follows:
  The model driven interceptor would need to
a) capture the raw request parameters into some storage
b) skip the second params interceptor
c) create a copy of the getModel object  (to ensure its detached from any
persistence session -- need to make sure this works for other common
persistence engines)
d) run params/validation on this copy
e) if no validation errors, run params on the orginal (still attached to the
persistence session), and proceed as normal
f) if validation errors, intercept calls to the getters for values in the raw
request for redisplay -- need to worry about XSS issues here

There's a lot of moving pieces, and I'm sure I'm missing some even more subtle
interactions.  However I do think something needs to be done.  I'm interesting
in tackling this, and am hoping for some feedback on the above outline of
required changes.

Thank you for reading,
Eric Nielsen

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

Reply via email to