> Ok, and do you perform all such copying manually or do you use something > automated for that? (Or simply a JPA merge?)
Yes, merge for simplicity, and if we have a custom caching mechanism we simply replace the node object in a hashmap. ** Martin > > Op 12-2-2012 16:22, schreef Martin Makundi: >> >> Yeah.. what we do is we detach entities when loading from service >> layer to view layer and when user is ready to commit we persist them >> on service layer overriding service layer state (standard locking >> techniques here). >> >> ** >> Martin >> >> 2012/2/12 Bas Gooren<b...@iswd.nl>: >>> >>> Ok, so you mean detaching entities when returning them to the view layer >>> (wicket)? >>> >>> How do you propose updating the underlying entities? Send the detached >>> entities back to the service layer and copying their changes to attached >>> entities? Or ...? >>> >>> Op 12-2-2012 14:22, schreef Martin Makundi: >>>> >>>> Why don't you just detach the entity/data objects with deep or shallow >>>> clone or similar? Minimal duplication... >>>> >>>> ** >>>> Martin >>>> >>>> 2012/2/12 Bas Gooren<b...@iswd.nl>: >>>>> >>>>> Hi All, >>>>> >>>>> I have an architectural question about wicket, DDD and the service >>>>> layer. >>>>> >>>>> Let's say we have a simple JPA entity (Customer), and a few simple >>>>> CRUDL >>>>> screens. >>>>> For database access, we have a DAO layer (CustomerDao) which delegates >>>>> to >>>>> an >>>>> EntityManager, and provides some convenience methods for searching. >>>>> We also like to have clear boundaries, so we have a thin service layer >>>>> which >>>>> wraps persist() and delete() calls in a transaction before forwarding >>>>> them >>>>> to the DAO layer (@Transactional, as provided by guice-persist). >>>>> >>>>> A wicket model fetches one or more customers (by id or by running a >>>>> search), >>>>> and attaches to a form. In the form we use PropertyModels which push >>>>> their >>>>> changes to the entity, and in onSubmit() we call >>>>> service.persist(entity). >>>>> This means that the actual changes to the model happen outside of the >>>>> transaction (in wicket code), and within the transaction (/service >>>>> layer) >>>>> we >>>>> merely call persist() and flush(). >>>>> >>>>> Then parts of the app need something a bit more advanced, so we decide >>>>> to >>>>> apply parts of DDD and put logic where it belongs (on the domain >>>>> models). >>>>> However, some logic coordinates multiple models, so we add a domain- or >>>>> application-service for that. >>>>> The good thing about DDD is that it's a lot more clear what happens >>>>> (intent). We now realize that having a persist() method on a >>>>> entity-based >>>>> service now looks like a bit of a code smell, since it does not capture >>>>> intent at all. Also, since the changes to the model happen in wicket, >>>>> before >>>>> the service layer is called, I feel that the service layer is not doing >>>>> anything to act as a boundary. We might as well mark the persist() >>>>> method >>>>> on >>>>> our daos @transactional and remove the service layer. >>>>> >>>>> The only clean way to fix this seems to be either: >>>>> (a) using DTO's so the UI/wicket is not actually modifying domain >>>>> entities >>>>> upside: the state of the domain is not modified by wicket itself >>>>> downside: duplication of models (actual model + DTO); >>>>> downside: validation is currently set-up in wicket by scanning >>>>> fields >>>>> for >>>>> validation annotations, so we would need to duplicate those on the DTO? >>>>> >>>>> (b) using a concept from CQRS: sending commands to the domain through a >>>>> bus. >>>>> This clearly and cleanly defines the intent and captures the exact >>>>> change. >>>>> upside: the state of the domain is not modified by wicket itself >>>>> downside: likely overkill for what we are trying to achieve; lot of >>>>> extra >>>>> complexity >>>>> >>>>> (c) wrapping the entire request in a transaction >>>>> upside: easy to implement >>>>> downside: since anything in the request can fetch a dao, read some >>>>> entities and modify them, this means we can lose track of what happens >>>>> in >>>>> a >>>>> request; >>>>> downside: feels like moving backwards >>>>> >>>>> (d) simplify by removing thin services and, where necessary, putting >>>>> more >>>>> logic in the dao's >>>>> upside: simple api contract: want to save/update an entity? use the >>>>> dao >>>>> directly >>>>> downside: dao's contain logic which does not really belong there >>>>> downside: if at some point we really do need a service, the api >>>>> contract >>>>> becomes less clear: for X and Y you can use the dao, for Z you have to >>>>> use a >>>>> service >>>>> >>>>> (a) and (b) provide a way to capture a change and execute all of the >>>>> change >>>>> inside a transaction. >>>>> >>>>> So my question to the list is: what are your experiences with this? How >>>>> do >>>>> you deal with this in simple to moderately complex webapps? >>>>> >>>>> Thanks for reading! >>>> >>>> --------------------------------------------------------------------- >>>> To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org >>>> For additional commands, e-mail: users-h...@wicket.apache.org >>>> >> --------------------------------------------------------------------- >> To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org >> For additional commands, e-mail: users-h...@wicket.apache.org >> > --------------------------------------------------------------------- To unsubscribe, e-mail: users-unsubscr...@wicket.apache.org For additional commands, e-mail: users-h...@wicket.apache.org