Am I wrong, or JPA's EntityManager has no support for anything like evict()? I think this is an Hibernate's Session specific feature... Alex
On Thu, May 1, 2008 at 3:54 PM, Eric D Nielsen <[EMAIL PROTECTED]> wrote: > [ I suspect this is going to break threading.... Is there a good way to > respond > to a message from a digest without breaking threading? ) > > Adam Hardy on 26/04/08 10:42, wrote: > > I am pulling in what I wrote earlier because I should correct what I > said > > about letting entities slip out of scope. Following this situation: > > > > - Model-driven builds the model > > - conversion to type and setting incoming HTTP param into Model > > - validation occurs and fails > > > > the problem was spurious JPA updates - which can be avoided by putting > an > > interceptor in between the Validation and the Workflow interceptors: all > it > > should do is call EntityManager.clear(). > > > > if (validationAwareAction.hasErrors()) getEntityManager().clear(); > > > > > > Using the JPA extended persistence context (not EJB), the clear() will > > eliminate any changes to the model before JPA comes to flush to the db. > I > > assume it would work in an EJB container too. > > > > Does that fit your situation, Eric? > > Unfortunately no. First clear is overkill, it evicts everything from the > session, and only the model may need to be evicts (Users could have other > items > already merged back into the session at this point -- normally I would > have > merged my User entity from the HTTP Session to the Persistence session by > this > point in the interceptor stack to allow authentication/authorization > checks). > > Secondly replacing the clear() with evict(((ModelDriven) > action).getModel()) for > instance would avoid that problem, but now you would lost the ability to > lazy > load anything from the model if needed for form redisplay. > > I'm 90% of the way to an initial solution right now, using two extra > interceptors: > ModelDrivenProtection > ModelDrivenEnable > (I need better names....) > > The first one is placed in the stack after prepare. The second one is > placed > after validation. > > In my Hibernate based implementation of them: > Protection calls session.setReadOnly(modelDrivenAction.getModel(),true) if > the > action also implements ValidationAware > > Enable calls session.setReadOnly(modelDrivenAction.getModel(),false) if > hasErrors() returns false > > I'm hoping I can come up with a more JPA provider agnostic version, after > I get > this pair working. However as the JPA spec doesn't include a notion of > readOnly, I think its going to have to be a custom version of the > JPAValidationInterceptor extends ValidationInterceptor-- > > Steps are something like > doIntercept(...) { > if (actionInvocation.getAction() instanceof ValidationAware && > actionInvocation.getAction() instanceof ModelDriven) { > ValidationAware validationAwareAction = (ValidationAware) > actionInvocation.getAction(); > ModelDriven modelDrivenAction = (ModelDriven) > actionInvocation.getAction(); > em.setFlushMode(FlushMode.COMMIT) > String retVal = super.doIntercept(...); > if (validationAwareAction.hasErrors()) { > em.evict(modelDrivenAction.getModel()); > // check for preparable and recall prepare to get a clean object back > on the > stack -- need to make sure hasErrors() still returns true though.... > // push the request parameters onto the stack ahead of the model for > redisplay of submitted values, while letting the model fill in others) > } > em.setFlushMode(FlushMode.AUTO); > return retVal; > } > > I like the hibernate version better since the "persistence read only" is > exactly > the correct semantics for a failed-validation model object. The generic > JPA is > nicer in that its not vendor specific, but much more kludgy. In rather > generalize it a bit more -- more the em.setFlushMode, em.evict calls to > some > interface and now we're to a more correct model driven situation: > a) the backing model object will never contain invalid values outside of > the > scope of params, validation, thisNewInterceptor (possibly built into > workflow > or validation) > b) values are still available for redisplay. > c) the three callback functions (setReadOnly, setWriteable, replaceModel) > or > similar can be hooked up to different backing stores... allowing any lazy > load > or other similar special behavior provided by the data store to work > transparently. > > This completely generalized version is the version that I would want to > suggest > for inclusion in Struts 2, but I'll need to work through the first two > approaches first to gain some confidence. > > Eric > > --------------------------------------------------------------------- > To unsubscribe, e-mail: [EMAIL PROTECTED] > For additional commands, e-mail: [EMAIL PROTECTED] > > -- Alexander Snaps <[EMAIL PROTECTED]> http://www.jroller.com/page/greenhorn http://www.linkedin.com/in/alexandersnaps