Search code examples
springresthateoas

How to add HATEOAS links in a sub resource


I have a parent resource called the AdminResource and a child resource called the AdminModuleResource.

The resource of the parent is correctly fitted with HATEOAS links:

{
  "firstname" : "Stephane",
  "lastname" : "Eybert",
  "email" : "mittiprovence@yahoo.se",
  "password" : "e41de4c55873f9c000f4cdaac6efd3aa",
  "passwordSalt" : "7bc7bf5f94fef7c7106afe5c3a40a2",
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost/admins/3683"
  }, {
    "rel" : "modules",
    "href" : "http://localhost/admins/3683/modules"
  } ],
  "id" : 3683
}

The resource of the child is also correctly fitted with HATEOAS links:

{
  "module" : "BTS",
  "adminResource" : {
    "firstname" : "Stephane",
    "lastname" : "Eybert",
    "email" : "mittiprovence@yahoo.se",
    "password" : "e41de4c55873f9c000f4cdaac6efd3aa",
    "passwordSalt" : "7bc7bf5f94fef7c7106afe5c3a40a2",
    "links" : [ ],
    "id" : 3683
  },
  "links" : [ {
    "rel" : "self",
    "href" : "http://localhost/modules"
  } ],
  "id" : 1087
}

But its parent resource has lost its links.

For now, when inside my child admin module resource, the parent admin resource does not have its links. Indeed the toResource method of the assembler only provides the links for the child admin module resource.

public AdminModuleResource toResource(AdminModule adminModule) {
    AdminModuleResource adminModuleResource = new AdminModuleResource();
    adminModuleResource.fromAdminModule(adminModule);
    adminModuleResource.add(linkTo(AdminModuleController.class).slash(adminModuleResource.getId()).withSelfRel());
    return adminModuleResource;
}

public AdminResource toResource(Admin admin) {
    AdminResource adminResource = createResourceWithId(admin.getId(), admin);
    adminResource.fromAdmin(admin);
    adminResource.add(linkTo(AdminController.class).slash(admin.getId()).slash(UriMappingConstants.MODULES).withRel(UriMappingConstants.MODULES));
    return adminResource;
}

Any idea how I can add the links to the parent admin resource even when inside the child admin module resource ?

EDIT: Here is how I build the resources:

public void fromAdminModule(AdminModule adminModule) {
    this.setResourceId(adminModule.getId());
    this.setModule(adminModule.getModule());
    AdminResource adminResource = new AdminResource();
    adminResource.fromAdmin(adminModule.getAdmin());
    this.adminResource = adminResource;
}

public void fromAdmin(Admin admin) {
    this.setResourceId(admin.getId());
    this.setFirstname(admin.getFirstname());
    this.setLastname(admin.getLastname());
    this.setEmail(admin.getEmail().toString());
    this.setPassword(admin.getPassword());
}

Thanks !

Stephane


Solution

  • Just stumbled on this question, even though it is quite old, but may be worth answering for others implementing similar functionality. Basically, you create embedded resources for AdminModuleResource on your AdminResource and build the links for these embedded resources within your AdminResourceAssembler. The code below is a simplified version of what is posted on this answer

    On AdminResource add:

    @JsonUnwrapped
    private Resources<EmbeddedWrapper> embeddeds;
    // + setters/getters
    

    On AdminResourceAssembler add:

    EmbeddedWrappers wrapper = new EmbeddedWrappers(true);
    
    List<EmbeddedWrapper> wrappers = (List<EmbeddedWrapper>) super.buildEmbeddables(entity);
    Set<AdminModuleResource> moduleResources = adminResource.getModuleResources( );
    if(!moduleResources.isEmpty( ))
        wrappers.add(wrapper.wrap(adminModuleResourceAssembler.toResources(moduleResources)));
    
    adminResource.setEmbeddeds(new Resources<>(wrappers));