Martin,

Ok, and do you perform all such copying manually or do you use something automated for that? (Or simply a JPA merge?)

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

Reply via email to