0

I'm designing my REST application architecture using Domain Driven Design and Adapter patter (there are interfaces, and many implementations in the aggregate root). It's all fine as long as don't add HATEOAS to the puzzle. In HATEOAS my value objects (on the bottom of dependency hierarchy) need to depend on resources (in the top layer). This messes up everything. I'm fairly new to HATEOAS so maybe I'm missing something. I'm planning to use Dropwizard and Jersey Declarative Linking.

Here is a diagram of my architecture:

enter image description here

Little clarification - this "Return and attributes types" between interfaces and value objects should actually be "Return and argument types" - It means, that all the interfaces' methods take objects from Value objects module as an arguments and return those objects to the caller.

I can add a piece of code that will show you what's in what module:

REST - JAX-RS Resources

@Component
@Path("/groups")
@Produces(MediaType.APPLICATION_JSON)
public class GroupsResource {

    @Autowired
    ProcessEngine processEngine; //interface with driver implementation under it

    @GET
    @Timed
    public List<UserGroup> getUserGroups(@Auth BpmUser user) {
        return processEngine.getUserGroups(user.id);
    }

}

Interface ProcessEngine

public interface ProcessEngine {
    void init();
    List<UserGroup> getUserGroups(String username);
}

Implementation in drivers module

public class ActivitiProcessEngine implements ProcessEngine {

    private org.activiti.engine.ProcessEngine processEngine;
    private DataSource dataSource;
    private String databaseType;

    public ActivitiProcessEngine(String databaseType, DataSource dataSource) {
        this.databaseType = databaseType;
        this.dataSource = dataSource;
    }

    @Override
    public void init() {
        if (processEngine != null)
            throw new ProcessEngineAlreadyInitializedException();
        try {
            processEngine = createProcessEngineConfiguration().buildProcessEngine();
            ProcessEngines.registerProcessEngine(processEngine);
        } catch (SQLException e) {
            throw new ProcessEngineDatabaseException(e);
        }
    }

    @Override
    public List<UserGroup> getUserGroups(String username) {
        return processEngine
                .getIdentityService()
                .createGroupQuery()
                .groupMember(username)
                .list()
                .stream()
                .map(Group::getId)
                .map(UserGroup::new)
                .collect(Collectors.toList());
    }

    ...
}

Value object

public class UserGroup {

    @JsonProperty
    public String name;

    //I want to be able add linking to another resources here

    public UserGroup(String name){
        this.name = name;
    }
}
Bartek Andrzejczak
  • 1,292
  • 2
  • 14
  • 27
  • 1
    It is not clear what is REST on the diagram. In general **value object** should not know anything about **Interface** implementation. – Dmytro Nov 03 '14 at 10:36
  • REST is the module containing dropwizard server, basic configuration and **JAX-RS resources**. In HATEOAS you need to tell linking annotation what JAX-RS resource should it link, and that seems to be the problem here. – Bartek Andrzejczak Nov 03 '14 at 10:40
  • you should not link a domain object to resource but **controller** to **domain object**. – Dmytro Nov 03 '14 at 10:51
  • I've added some sample code from every module. How can I link my controller to domain object here? – Bartek Andrzejczak Nov 03 '14 at 10:54
  • One should link a controller to domain object. For instance ' @ExposesResourceFor(Order.class) in controller'. And not other direction. Read this https://github.com/spring-projects/spring-hateoas/blob/master/readme.md – Dmytro Nov 03 '14 at 10:58
  • The problem is with the fact, that I can't use Spring HATEOAS because I don't use Spring REST, but jersey + jackson. Is there some nondeclarative linking for jersey, like in Spring. In Jersey you can have `@InjectLink(resource=GroupsResource.class) URI u;` link inside Value Object, but can you link it somehow from the resource itself? – Bartek Andrzejczak Nov 03 '14 at 11:03
  • 1
    @bandrzejczak It seems you're currently mixing up domain layer and delivery mechanism layer. In DDD, domain objects (Value Objects and Entities) should be agnostic of how the information is eventually sent over the wire. – guillaume31 Nov 03 '14 at 13:24
  • @bandrzejczak you don't have a *REST application*, you have a *User groups / insert your domain here* application that turns out to use REST as the way to access it, but it could be any other mechanism, and you need to decouple that from your core domain layer. – guillaume31 Nov 03 '14 at 13:27

1 Answers1

1

Domain object should never know anything about Controller or any other application logic. So, link controllers to domain object. It will solve your dependency problem.

Dmytro
  • 496
  • 7
  • 17