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 <[email protected]>: > 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: [email protected] For additional commands, e-mail: [email protected]
