4

I am curious on what is the preferred way to decouple a core domain entity from the entity served by a REST layer.

I saw on this enlightening Spring REST tutorial http://spring.io/guides/tutorials/rest/1/ that it's a good thing not to expose the core domain model directly in the REST layer as it should evolve independently of the core domain model.

The core service is handling and producing events. These events are seen as the communication ports of the application. The core service does not see any REST domain entity. And the REST controller does not see any core domain entity.

To make things simpler, let's consider the example of only one entity, the Order entity.

The tutorial shows how an Order REST domain class is passed by a REST request to a controller. In turn the controller creates an OrderDetails entity passed to an Order handling event to create a CreateOrderEvent event, which is then passed to a service which returns another OrderCreatedEvent event. The controller finally creates a REST domain Order entity from the returned event, and sends it in the response.

We can see that for this one entity, there is one class for core domain entity, one class for the REST domain entity, and one class for the event payload entity.

Also, we can see that the events, sitting in the application core, extend on some base events which remind strongly of the HTTP methods. It is a bit surprising to see this REST like stuff seeping into the application core, when what we are trying to do in the first place, is to decouple the application core from the REST layer.

Any thought on this design or an some alternate design ? Are there any preferred way of achieving this decoupling ?

Thanks for any suggestion.

Kind Regards,

Stephane

One additional question I now have...

Should I go for an entity NotFoundException exception or for a notFoundEntity event member in the event, on a REST domain decoupled from the data domain ?

The event sent back to the controller can carry a notFoundEntity member state which can be used in the controller.

Here is the event notFoundEntity logic:

protected boolean notFoundEntity = false;

public boolean isNotFoundEntity() {
    return notFoundEntity;
}

public static OneAdminEvent notFound(Long id) {
    OneAdminEvent oneAdmiEvent = new OneAdminEvent(id);
    oneAdmiEvent.notFoundEntity = true;
    return oneAdmiEvent;
}

The service updates the event member state depending on the entity having been found or not:

Admin admin  = adminRepository.findOne(deleteAdminEvent.getId());            
if (admin == null) {
    return AdminDeletedEvent.notFound(deleteAdminEvent.getId());

In the controller, a call to checks for the entity having been found or not:

if (adminDeletedEvent.isNotFoundEntity()) {
}

This is in line with the decoupling design.

But, I'm not sure the decoupling event should carry this information. This information can be seen as an exception, a business custom exception.

Also, using an exception makes it possible to specify a rollback attribute in the transactional annotation:

@Transactional(rollbackFor = NotFoundException.class)

With an exception, the only not found entity logic left is on the service, the event does not contain any.

The service now looks like:

Admin admin  = adminRepository.findOne(deleteAdminEvent.getId());            
if (admin == null) {
    throw new NotFoundException("No admin was found with the id " + deleteAdminEvent.getId());

What rule of thumb to use to decide when to use a member state in the event and when to use a business custom exception ?

Stephane
  • 11,836
  • 25
  • 112
  • 175
  • Iam not sure about the answer. But I have worked with openmrs , a medical recording system. There in REST layer is a separate module which is decoupled with the core application. You can look at its design. – geekgugi Nov 01 '13 at 17:33
  • @geekgugi Thanks for that, I will have a look at their REST layer, it should be interesting. – Stephane Nov 25 '13 at 07:59
  • They are using spring AOP. – geekgugi Nov 25 '13 at 09:31

1 Answers1

2

It would be harder for this example application to decouple the REST domain and core domain layers more. Not only have the REST (a.k.a. "view") objects been cleanly separated from the core (a.k.a. "domain") objects, but their direct communication has also been decoupled via an internal event-driven architecture. The reason that the core events remind you so strongly of HTTP methods is probably more due to the simplicity of the example's use cases than by necessity or design. Such can be the peril of example. :)

While this is certainly a sound way to layer an application, the real question is whether it's necessary for your particular scenario. If your application will be very data-oriented (e.g., a data entry system with few business rules), you might not need a separate set of REST domain objects (much the way you might decide you don't need a separate layer of "view" objects in a traditional MVC application). You could take the Spring Data REST approach (see Oliver Gierke's RESTBucks sample app). Then again, if you have some heavy business logic in core and want to create a rich domain model, you're probably better off with a more decoupled architecture.

Jonathan W
  • 3,759
  • 19
  • 20
  • Thanks, I guess I don't need that bad to decouple in fact. I'll have a look at the RESTBucks sample. – Stephane Nov 25 '13 at 08:04