Круговая зависимость из-за использования HATEOAS в REST

Я разрабатываю архитектуру своего приложения REST, используя шаблон Domain Driven Design и Adapter (есть интерфейсы и множество реализаций в совокупном корне). Все в порядке, если не добавлять HATEOAS к головоломке. В HATEOAS мои объекты-значения (в нижней части иерархии зависимостей) должны зависеть от ресурсов (в верхнем слое). Это портит все. Я новичок в HATEOAS, поэтому, возможно, я что-то упускаю. Я планирую использовать декларативное связывание Dropwizard и Jersey.

Вот схема моей архитектуры:

введите здесь описание изображения

Небольшое уточнение: эти «Типы возврата и атрибутов» между интерфейсами и объектами-значениями на самом деле должны быть «Типы возврата и аргумента». Это означает, что все методы интерфейсов берут объекты из модуля «Объекты-значения». в качестве аргументов и вернуть эти объекты вызывающей стороне.

Я могу добавить кусок кода, который покажет вам, что в каком модуле:

REST — ресурсы по JAX-RS

@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);
    }

}

Интерфейс ProcessEngine

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

Реализация в модуле драйверы

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());
    }

    ...
}

Объект значения

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;
    }
}

person Bartek Andrzejczak    schedule 03.11.2014    source источник
comment
Непонятно, что такое REST на схеме. В общем случае объект-значение ничего не должен знать о реализации Interface.   -  person Dmytro    schedule 03.11.2014
comment
REST — это модуль, содержащий сервер dropwizard, базовую конфигурацию и ресурсы JAX-RS. В HATEOAS вам нужно указать связывающую аннотацию, какой ресурс JAX-RS должен быть связан, и здесь, похоже, проблема.   -  person Bartek Andrzejczak    schedule 03.11.2014
comment
вы не должны связывать объект домена с ресурсом, а контроллер с объектом домена.   -  person Dmytro    schedule 03.11.2014
comment
Я добавил несколько примеров кода из каждого модуля. Как я могу связать свой контроллер с объектом домена здесь?   -  person Bartek Andrzejczak    schedule 03.11.2014
comment
Нужно привязать контроллер к объекту домена. Например, «@ExposesResourceFor(Order.class) в контроллере». И не другое направление. Прочтите это github.com/spring-projects/spring-hateoas/ blob/master/readme.md   -  person Dmytro    schedule 03.11.2014
comment
Проблема в том, что я не могу использовать Spring HATEOAS, потому что я использую не Spring REST, а jersey + jackson. Есть ли какая-то недекларативная привязка для джерси, как в Spring. В Джерси у вас может быть ссылка @InjectLink(resource=GroupsResource.class) URI u; внутри Value Object, но можете ли вы как-то связать ее с самим ресурсом?   -  person Bartek Andrzejczak    schedule 03.11.2014
comment
@bandrzejczak Кажется, вы сейчас смешиваете уровень домена и уровень механизма доставки. В DDD объекты домена (объекты значений и сущности) не должны зависеть от того, как информация в конечном итоге отправляется по сети.   -  person guillaume31    schedule 03.11.2014
comment
@bandrzejczak у вас нет приложения REST, у вас есть приложение Группы пользователей / вставьте сюда свой домен, которое, оказывается, использует REST как способ доступа к нему, но это может быть любой другой механизм, и вам необходимо отделить его от уровня основного домена.   -  person guillaume31    schedule 03.11.2014


Ответы (1)


Объект домена никогда не должен знать ничего о контроллере или любой другой логике приложения. Итак, свяжите контроллеры с объектом домена. Это решит вашу проблему зависимости.

person Dmytro    schedule 03.11.2014
comment
Проблема в том, что это не Spring — это Dropwizard на базе Jersey + Jackson. Пожалуйста, посмотрите на перефразированный вопрос в верхней части моего исходного вопроса. - person Bartek Andrzejczak; 03.11.2014
comment
Идея та же. Не ссылайтесь на какую-либо логику в объекте предметной области. - person Dmytro; 03.11.2014
comment
Это хорошая идея, но я не знаю, как это сделать и при этом получить ссылки HATEOAS. - person Bartek Andrzejczak; 03.11.2014