Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Wrong Resource Type" When Collection Misses "_embedded" #66

Closed
mathias-ewald opened this issue Jul 23, 2022 · 4 comments · Fixed by #67
Closed

"Wrong Resource Type" When Collection Misses "_embedded" #66

mathias-ewald opened this issue Jul 23, 2022 · 4 comments · Fixed by #67
Assignees
Labels
enhancement New feature or request

Comments

@mathias-ewald
Copy link

mathias-ewald commented Jul 23, 2022

Hi wrote a REST API with Spring HATEOAS and noticed that when there are not resources to return, the rendered JSON misses the _embedded property.

Code from the REST controller that produces the result:

Pageable pageable = PageRequest.of(pageIndex, pageSize);
Page<Article> page = articleRepo.findAll(pageable);
CollectionModel<ArticleV1Representation> colModel = articleAssembler.toCollectionModel(articleRepo.findAll(pageable));

PagedModel.PageMetadata md = new PagedModel.PageMetadata(
    page.getContent().size(),
    page.getNumber(),
    page.getTotalElements(),
    page.getTotalPages());

PagedModel<ArticleV1Representation> model = PagedModel.of(colModel.getContent(), md);
model.add(linkTo(methodOn(ArticleV1RootController.class).getAll(0, pageSize)).withRel("first"));

The result produced when there are no entities in the repository:

{
  "_links" : {
    "first" : {
      "href" : "http://localhost:8081/articles?page=0&size=20"
    },
    "self" : {
      "href" : "http://localhost:8081/articles?page=0&size=20"
    },
    "last" : {
      "href" : "http://localhost:8081/articles?page=0&size=20"
    }
  },
  "page" : {
    "size" : 1,
    "totalElements" : 1,
    "totalPages" : 1,
    "number" : 0
  }
}

The UI code to fetch the data:

this.resourceService.getPage(Article, opts)
  .pipe(delay(500))
  .subscribe((page: PagedResourceCollection<Article>) => {
  ...
});

Error produced in the UI:
Screenshot 2022-07-23 at 12 33 10

Since the HAL specification (https://datatracker.ietf.org/doc/html/draft-kelly-json-hal#section-4.1.2) tells that _embedded is optional, I am opening an issues here.

@lagoshny
Copy link
Owner

lagoshny commented Jul 24, 2022

Hi @mathias-ewald !

In this case, I relied on Spring Data REST behavior for empty collections.
It means that if you have an empty collection, then Spring Data Rest puts an empty object as _embedded: { your_resource_name: [] } property.

This behavior allows simpler to determine what is Resource type: Collection, Page, or simple Resource.

As I understand you use Spring HATEOAS, you can try to repeat the same behavior as Spring Data REST using some part of code:

HalModelBuilder.emptyHalModel()
  .embed(Collections.emptyList(), Order.class);
  // or
  .embed(Collections.emptyList(), LinkRelation.of("orders"));

Then it will be rendered the next JSON for an empty collection:

{
  "_embedded" : {
    "orders" : []
  }
}

See more in Spring HATEOAS docs.

@lagoshny
Copy link
Owner

If you can not make an empty _embedded property for an empty collection. Write about it, I will think how to make _embedded property as optional.

@mathias-ewald
Copy link
Author

Hi @lagoshny,

think it'll be difficult to tell the backend team to do something the specification does not require to be compatible with the frontend library I am using.

Is there a way to catch and handle that error somehow?

cheers,
Mathias

@lagoshny lagoshny self-assigned this Jul 25, 2022
@lagoshny lagoshny added the enhancement New feature or request label Jul 25, 2022
@lagoshny lagoshny linked a pull request Jul 25, 2022 that will close this issue
@lagoshny
Copy link
Owner

@mathias-ewald
I think it is good design to write predictable API and even if specification says that _embedded is optional it is not saying that it is good in some case to put _embedded in another not. And to know about it, you need to read specification.

To help you, I added new config option that allow resource collections without _embedded.

Add option in lib config (see more in docs):

halFormat: {
   collections: {
      embeddedOptional: true
    }
}

This features available since 3.3.0 version and 2.6.0 lib versions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants