aspose file tools*
The moose likes OO, Patterns, UML and Refactoring and the fly likes Validation and copying Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login


Win a copy of Java 8 in Action this week in the Java 8 forum!
JavaRanch » Java Forums » Engineering » OO, Patterns, UML and Refactoring
Bookmark "Validation and copying" Watch "Validation and copying" New topic
Author

Validation and copying

Don Kiddick
Ranch Hand

Joined: Dec 12, 2002
Posts: 580
I'm writing a ui framework. This framework includes validation.

I have a problem, when I edit an entity with my ui, I scrape the values of some the fields and put them in my ui components, texboxes, combos etc. The user makes some edits and presses ok. I then validate his response. So I update my entity with the dirty fields and validate it. If the entity is valid, great, however if it is invalid I've now dirtied my entity when I didn't want to. If the user then aborts the edit the app is a bad state.

So it seems I need to copy the entity before I validate it. I was hoping to avoid this, (particularly clone!) and provide as much support in my framework as possible to make it as easy as possible. However I don't see a solution other than providing an abstract copy() method at a suitable place for developers to implement. This is because the depth of the copy required could vary depending on the edit being carried out.

Hmmm...this (ie the abstract copy method) seems feasible but I wonder if there are other solutions or common approaches to this problem?

thanks, D.
Ilja Preuss
author
Sheriff

Joined: Jul 11, 2001
Posts: 14112
You might want to take a look at https://binding.dev.java.net/ - especially its BufferedValueModel.


The soul is dyed the color of its thoughts. Think only on those things that are in line with your principles and can bear the light of day. The content of your character is your choice. Day by day, what you do is who you become. Your integrity is your destiny - it is the light that guides your way. - Heraclitus
Frank Carver
Sheriff

Joined: Jan 07, 1999
Posts: 6920
I'd probably think about this a bit more before jumping immediately to the idea of copying the whole entity for every "trial edit".

First you really need to get some idea of how often "good" edits are likely to occur compared with "bad" ones. If there are many more "good" ones I suggest you don't want to burden all those good ones with unneeded extra copying.

Possibilities I can think of off the top of my head include:

  • A proxy/decorator which wraps the entity and replaces the mutators with ones which sit "on top" of the actual data, and responds with either the new data (if set), or the original data when validated. If/when validation passes, run a method on the proxy to load all the new values into the entity for storing.
  • Each time you change a value in your entity from this UI, take a note of the old value, and "roll back" the stored old values if validation fails.
  • Put your validation in a third place, with a method which validates an entity and a set of updated values, without modifying the entity itself.
  • if validation fails, just throw away the entity and reload when necessary from the stored version.


  • Any of these sound likely?


    Read about me at frankcarver.me ~ Raspberry Alpha Omega ~ Frank's Punchbarrel Blog
    Stan James
    (instanceof Sidekick)
    Ranch Hand

    Joined: Jan 29, 2003
    Posts: 8791
    I'm not clear on what architecture we're in. Can setField() on the entity do the validation? If there is cross-field editing too complex for that, can you make a "form" object to hold all the data for one update and validate the form before you start touching the real entity?


    A good question is never answered. It is not a bolt to be tightened into place but a seed to be planted and to bear more seed toward the hope of greening the landscape of the idea. John Ciardi
    Don Kiddick
    Ranch Hand

    Joined: Dec 12, 2002
    Posts: 580

    I'd probably think about this a bit more before jumping immediately to the idea of copying the whole entity for every "trial edit".

    First you really need to get some idea of how often "good" edits are likely to occur compared with "bad" ones. If there are many more "good" ones I suggest you don't want to burden all those good ones with unneeded extra copying.


    I can see bad edits happening reasonably often. In my domain, I can't see unnecessary copying being a performance problem, or were you alluding to other related problems?


    Any of these sound likely?


    Two problems :
    * I want the validation logic to be contained with the domain object. This is because the same logic may well be used on the server side.
    * Validating single fields is problematic. My ui may be editing a contact's attributes but the validation may depend on attributes not been edited such as the 'location'. Also there maybe interelationships between the fields, so I cannot just validate the fields in isolation.


    if validation fails, just throw away the entity and reload when necessary from the stored version.


    This is a possiblity although it doesn't seem much better than the copy approach


    If there is cross-field editing too complex for that


    Yes.


    can you make a "form" object to hold all the data for one update and validate the form before you start touching the real entity


    Thing is the cross-field validation may include fields that are not edited.

    Seems I'm a bit stuck with copying or reloading my entity. Oh well! Thanks for your replies.

    thanks,
    D.
    Frank Carver
    Sheriff

    Joined: Jan 07, 1999
    Posts: 6920
    From what you have just clarified, it still looks like my suggestion A proxy/decorator which wraps the entity and replaces the mutators with ones which sit "on top" of the actual data, and responds with either the new data (if set), or the original data when validated. If/when validation passes, run a method on the proxy to load all the new values into the entity for storing. might be a contender.

    In case my descrption was unintelligible, here's a (very simple) example:

    First the example interface and entity object we will be working with:



    The above entity is not particularly interesting, although it does have get/set methods and a validate method which applies multi-field validation. I hope that's representative of some of your domain code.

    Now let's look at a "wrapper" class:



    Note that the "trial" class has no validation, it uses the existing validation in MyEntity. The validation has been written in terns of the public accessor methods (good practice anyway), so it uses the overridden ones from the trial wrapper.

    So, when you need to "try" an update on an entity, start by "wrapping" it, then call whatever methods your UI would normally do. Then validate the trial. If the trial passes validation, push any updated values through to the real entity. If the trial fails validation, the original entity can remain unchanged:



    Does that make any more sense?
    Don Kiddick
    Ranch Hand

    Joined: Dec 12, 2002
    Posts: 580
    Does that make any more sense?


    Yes it does and it is definitely food for thought. Although it seems like a variant on the copying strategy really.

    thanks! Tom
    Stan James
    (instanceof Sidekick)
    Ranch Hand

    Joined: Jan 29, 2003
    Posts: 8791
    That's pretty neat, Frank. Have you used this or seen it in the wild? It's akin to the "copy" solution but only populates the values that are changing, which may give validation a clue about what to validate, too.
    Stan James
    (instanceof Sidekick)
    Ranch Hand

    Joined: Jan 29, 2003
    Posts: 8791
    Overnight this thread reminded me of my last mainframe application. It held a representation of what the user was working on in "model" space whether it was good, bad or ugly. Then this line from the OP stuck out:

    If the entity is valid, great, however if it is invalid I've now dirtied my entity when I didn't want to.

    What bad thing happens because of a dirty entity? If it's shared among users one user could mess others up. But if it belongs to one user's session, maybe it's ok. Maybe a user can hold an invalid state and work on it until it's clean or they abandon it, but they can't save an invalid state to the database.

    I'm guessing you've already been down this road and rejected it. Which leaves me curious about why.
    Frank Carver
    Sheriff

    Joined: Jan 07, 1999
    Posts: 6920
    Stan wrote: What bad thing happens because of a dirty entity? If it's shared among users one user could mess others up. But if it belongs to one user's session, maybe it's ok. Maybe a user can hold an invalid state and work on it until it's clean or they abandon it, but they can't save an invalid state to the database.

    Good question.

    I was guessing that somewhere in this is an ORM solution which (somehow) automatically writes back "dirty" entities to the db. This is obviously a risky position to be in with several entities loaded, some "dirty", but some of those dirty ones potentially invalid and unsuitable for writing back.

    Perhaps it might be possible to modify the entity code or the ORM code to only write these back if they are valid. It sounds trickier than writing all dirty entities back, though.
    Don Kiddick
    Ranch Hand

    Joined: Dec 12, 2002
    Posts: 580
    What bad thing happens because of a dirty entity? If it's shared among users one user could mess others up.

    Only shared by one user.


    But if it belongs to one user's session, maybe it's ok. Maybe a user can hold an invalid state and work on it until it's clean or they abandon it, but they can't save an invalid state to the database.


    I was thinking it would be difficult to abandon, because the same object could be referenced from multiple places in the application. However now I realise, that rather than abondoning the instance, I can just abandon it's state, ie. refresh the instance.

    That helps a lot! Thanks!
    D.
    Stan James
    (instanceof Sidekick)
    Ranch Hand

    Joined: Jan 29, 2003
    Posts: 8791
    ... referenced from multiple places in the application ...


    That might be something to talk about, too.

    Sounds like you have some ideas on how to move forward. Keep us posted how it goes.
    Don Kiddick
    Ranch Hand

    Joined: Dec 12, 2002
    Posts: 580
    ... referenced from multiple places in the application ...
    That might be something to talk about, too


    for example the entity 'Don Kiddick' could be referenced by a table model in the 'manage contacts screen'. It also might be in a list panel in the 'employee screen' and also in the 'required attendees' box on the 'appointment screen'.

    In my implementation the various ui models (table models, list models etc) work by adapting the domain objects. Therefore each view on an entity involves holding references to that entity. When the entity changes, the ui models change too. I end up with domain objects (possibly) referenced in lots of places.

    Another approach is to scrape the display values of the domain objects to create the ui models. In this pattern a view on an entity does not neccessarily mean you hold an object reference to it.

    Does that make any sense?

    D.
    Stan James
    (instanceof Sidekick)
    Ranch Hand

    Joined: Jan 29, 2003
    Posts: 8791
    That's a fun challenge. You probably don't want to update the other views of an entity until the edit passes validation and the user commits?
    Frank Carver
    Sheriff

    Joined: Jan 07, 1999
    Posts: 6920
    It's the classic two-phase transaction approach but at an object level.

    I still stand by my suggestion above of a "buffer" around the problematic objects. Each user of such a shared entity actually talks to a buffer/decorator which adds "commit" and "rollback" methods (commit pushes the buffered data through to the real object, as describd above, and all a rollback needs to do is clear the "has" flags and the client will go back to using the unchanged data in the underlying entity.

    This feels like the way a database would do it. You don't want to copy the whole db every time a transaction is started. You just want a thin "ghost" layer of changed values, only visible to the transaction involved.

    I guess the real challenge is whether between us we can come up with a general solution to this (perhaps using automatic proxying) which will simply wrap such a transaction around any object. Anyone want to try it?
    [ September 29, 2006: Message edited by: Frank Carver ]
    Don Kiddick
    Ranch Hand

    Joined: Dec 12, 2002
    Posts: 580
    Originally posted by Frank Carver:

    I guess the real challenge is whether between us we can come up with a general solution to this (perhaps using automatic proxying) which will simply wrap such a transaction around any object. Anyone want to try it?


    This would definitely be the ideal. I'm writing a framework so anything I can provide 'for free' is a bonus. I'm not convinced it's possible though.

    At a high level I see two approaches :

    1. Try to validate and if fail reload the instance in place.
    2. Copy the entity. If validation fails, throw away the copy. If it succeeds update the 'true' entity and update.

    (I'm lumping the decorator solution proposed by Frank in 2)

    #1 :
    Is performant if entities fail validation rarely.
    Is easy for me to implement a default implemention which will work in 90% of cases. This is because we mainly use hibernate and can simply ask it to refresh an object, which loads its state from the db.
    Will not work well for 'dynamic validation'. That is a text box that gives visual feedback on the 'validity' of the form as it is being updated. In this case a textbox that requires a string of minimum length 10 characters, will validate at least 10 times.

    Hmmm...that last point is a big one, cause that is something we may want to do.

    #2
    Is performant if validation fails regularly.
    Will work well for 'dynamic validation'.
    Is not easy for to provide a default implementation.

    I don't think it's possible to create a 100% effective automated copy strategy because you don't know how deep you need to copy. I 90% stragey would be good though. I see two possibilities :
    a) copy the object using serialization or other reflection based technique.
    b) autogenerate a decorator a la Frank's solution. Dynamic proxies seem out as they only work on interfaces. So that leaves cglib or some other reflection jiggery pokery.

    D.
     
    I agree. Here's the link: http://aspose.com/file-tools
     
    subject: Validation and copying
     
    Similar Threads
    JSF validation components !!
    Make it Better? Struts Validator - Same Form but Multi Actions
    Validating selective fields of a JSP thru Struts Validator Framework
    Need Help for Validation Framework
    Struts validation