【问题标题】:Circular Dependency due to usage of HATEOAS in REST由于在 REST 中使用 HATEOAS 导致的循环依赖
【发布时间】:2014-11-03 10:09:09
【问题描述】:

我正在使用域驱动设计和适配器模式设计我的 REST 应用程序架构(在聚合根中有接口和许多实现)。只要不将 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;
    }
}

【问题讨论】:

  • 在图上不清楚什么是REST。一般来说值对象不应该知道任何关于接口的实现。
  • REST 是包含 dropwizard 服务器、基本配置和 JAX-RS 资源的模块。在 HATEOAS 中,您需要告诉链接注释应该链接哪个 JAX-RS 资源,这似乎是这里的问题。
  • 您不应将域对象链接到资源,而应将控制器链接到域对象
  • 我从每个模块中添加了一些示例代码。如何在此处将我的控制器链接到域对象?
  • @bandrzejczak 看来您目前正在混淆域层和交付机制层。在 DDD 中,域对象(值对象和实体)应该不知道信息最终是如何通过网络发送的。

标签: java rest domain-driven-design circular-dependency hateoas


【解决方案1】:

域对象永远不应该知道任何关于控制器或任何其他应用程序逻辑的信息。因此,将 controllers 链接到域 object。它将解决您的依赖问题。

【讨论】:

  • 问题在于它不是 Spring - 它是基于 Jersey + Jackson 的 Dropwizard。请查看我原始问题顶部的改写问题。
  • 思路是一样的。不要引用域对象中的任何逻辑。
  • 这是个好主意,但我不知道有什么方法可以做到这一点,但仍然可以获得 HATEOAS 链接。
猜你喜欢
  • 2020-12-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-10-09
  • 1970-01-01
  • 2021-09-27
  • 2015-06-08
相关资源
最近更新 更多