I just use open session in view.  You can still retrieve stuff outside a
transaction.  I explicitly call update to persist.
On Feb 12, 2012 7:54 AM, "Bas Gooren" <b...@iswd.nl> wrote:

> 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!
>

Reply via email to