J'utilise spring-boot-2.2.1 avec spring-HATEOAS. Les liens hypermédia fonctionnent bien mais
Je vois l'attribut _embedded
lors du renvoi des liens, veuillez trouver le code ci-dessous pour référence et le projet dans github ici ,
Endpoint:
a) Renverra CollectionModel
=> localhost: 8099 / api / v1 / ability / list / noembedded
et
b) Renverra List
XXX
Controller.Java
[ { "capabilityId": "sample", "techStack": "Java", "numOfDevelopers": 25, "numOfAvailableDevelopers": 10, "_links": { "getThisCapability": { "href": "http://localhost:9771/api/v1/capability/sample" }, "getAllCapabilities": { "href": "http://localhost:9771/api/v1/capability/list" } } } ]
Réponse réelle
[ { "id": "sample", "techStack": "Java", "numOfDevelopers": 25, "numOfAvailableDevelopers": 10, "_links": { "getThisCapability": { "href": "http://localhost:8099/api/v1/capability/sample" }, "getAllCapabilities": { "href": "http://localhost:8099/api/v1/capability/list" } } } ]
Réponse attendue: p>
{ "_embedded": { "capabilityList": [ { "id": "sample", "techStack": "Java", "numOfDevelopers": 25, "numOfAvailableDevelopers": 10, "_links": { "getThisCapability": { "href": "http://localhost:8099/api/v1/capability/sample" }, "getAllCapabilities": { "href": "http://localhost:8099/api/v1/capability/list" }, "deleteThisCapability": { "href": "http://localhost:8099/api/v1/capability/sample" }, "createCapability": { "href": "localhost:8099/api/v1/capability" } } } ] } }
J'ai essayé
spring.data.rest.defaultMediaType = application / json
spring.hateoas.use-hal-as-default-json-media-type = false
Mais pas de chance, je peux toujours voir l'attribut _embedded
dans la réponse.
Quelqu'un pourrait-il m'aider à identifier le problème.
J'utilisais spring-boot-1.5.10
avant de pouvoir afficher les liens correctement sans _embedded code>, veuillez vous référer ici .
Cela fonctionne bien après ajouté sous l'annotation dans la classe principale et si je retourne List
@EnableHypermediaSupport (type = EnableHypermediaSupport.HypermediaType.HAL)
localhost: 9771 / api / v1 / ability / list
Cela produit le résultat ci-dessous:
@RestController @RequestMapping(value = "/api/v1/capability") @RequiredArgsConstructor @CrossOrigin public class CapabilityController { private final CapabilityService capabilityService; private final CapabilityResourceAssembler capabilityResourceAssembler; @GetMapping(value = "/list") public CollectionModel<EntityModel<Capability>> getAllCapabilities() { List<EntityModel<Capability>> capabilities = capabilityService.listCapabilities().stream() .map(capability -> new EntityModel<>(capability, linkTo(methodOn(CapabilityController.class).getCapabilityById(capability.getId())).withRel("getThisCapability"), linkTo(methodOn(CapabilityController.class).getAllCapabilities()).withRel("getAllCapabilities") )).collect(Collectors.toList()); return new CollectionModel<>(capabilities); } }
Malheureusement, ce n'est pas travaillant dans la dernière version. Toute aide serait vraiment appréciée.
3 Réponses :
Si je comprends correctement la spécification HAL , cela être invalide HAL, c'est pourquoi Spring HATEOAS ne produira pas ce résultat tant que vous retournerez un CollectionModel
dans votre requête. Notez qu'il est possible que la collection ait également des liens, qui seraient à côté de la propriété _embedded
dans une propriété _links
comme illustré dans cet exemple de document .
Au cas où vous voudriez vraiment vous débarrasser de la propriété _embedded
et produire une liste de EntityModel
s, alors cela devrait fonctionner si vous modifiez votre code pour renvoyer un List
. Vous perdrez alors les propriétés _embedded
et _links
qui sont produites par Spring HATEOAS. Voici votre extrait de code modifié:
@RestController @RequestMapping(value = "/api/v1/capability") @RequiredArgsConstructor @CrossOrigin public class CapabilityController { private final CapabilityService capabilityService; private final CapabilityResourceAssembler capabilityResourceAssembler; @GetMapping(value = "/list") public List<EntityModel<Capability>> getAllCapabilities() { List<EntityModel<Capability>> capabilities = capabilityService.listCapabilities().stream() .map(capability -> new EntityModel<>(capability, linkTo(methodOn(CapabilityController.class).getCapabilityById(capability.getId())).withRel("getThisCapability"), linkTo(methodOn(CapabilityController.class).getAllCapabilities()).withRel("getAllCapabilities") )).collect(Collectors.toList()); return capabilities; } }
Je vous déconseille fortement cela car vous perdez les avantages de Spring HATEOAS.
De plus, je recommande de faire utilisez votre CapabilityResourceAssembler
et créez les instances EntityModel
en utilisant abilityResourceAssembler.toModel (...)
pour ne pas devez répéter le code que vous avez implémenté dans votre fonction .map (...)
.
Je connais cette solution. Je l'utilise déjà pour l'une de mes API. Mais si nous utilisons EntityModel pour List, nous perdons des _links aussi bien que vous l'avez mentionné. Je souhaite conserver _links.
Actuellement, cela ne semble pas possible dans Spring HATEOAS. Cela entrerait également en conflit avec toute classe que vous retournez (peut-être ne pas être List
) qui a une propriété _links
.
Pourriez-vous s'il vous plaît vérifier ma question à nouveau. Je l'ai mis à jour. Cela fonctionnait bien avec l'ancienne version.
@VelNaga En regardant votre question mise à jour et le code que vous avez fourni, j'ai immédiatement remarqué que vous renvoyez List
( github.com/VelDeveloper/spring-hypermedia/blob/master/src/ma dans /… ), pas Resources
qui serait la bonne façon de renvoyer une collection de ressources. Par conséquent, dans l'ancien projet, vous avez fait la même chose que je l'ai proposé ci-dessus - vous n'auriez pas dû être en mesure de voir les liens liés à la collection dans le code que vous avez fourni via GitHub. Pouvez-vous vérifier cela?
Capability
étend RecourseSupport
donc List _embedded
dans la réponse. Si je renvoie Resources
alors ma réponse contiendra _embedded
. La principale chose à noter dans l'ancienne API est que je peux voir _links
dans la réponse et que les liens en réponse sont rendus correctement, ce qui ne fonctionne pas dans la nouvelle API.
Lorsque vous êtes passé à la nouvelle API, vous avez changé le type de retour de votre méthode d'une collection de ressources à une ressource qui contient plusieurs ressources ( CollectionModel code>). Pour obtenir exactement la même chose qu'avant, renvoyez
List
. Dans l'ancienne API, vous n'auriez dû voir aucun lien à côté du tableau. Dans la nouvelle API, vous pouvez, car il s'agit d'une ressource ( CollectionModel
). Regardez exactement où la propriété _links
que vous mentionnez se trouve dans la hiérarchie, elle appartient à un seul objet Capability
- pas à la collection. Et renvoyer des EntityModel
s le conservera.
continuons cette discussion dans le chat .
Poussé des modifications dans le référentiel github en désactivant MongoDB. Veuillez vérifier cet hôte local de point de terminaison:
J'ai donc vérifié à nouveau votre code. C'est fondamentalement la même chose, sauf pour le EntityModel
qui n'est pas correctement sérialisé en 2.2.1. Je vous suggère de découvrir comment sérialiser des instances de EntityModel
contenues dans une List
puis d'utiliser ma solution proposée détaillée dans ma réponse. Mais je vous encourage toujours à utiliser le CollectionModel
et à utiliser correctement HAL afin que vous ayez des liens au niveau de la collection.
Lors de l'utilisation de Spring Boot 1.5, vous vous reposiez sur une limitation de Spring HATEOAS qui a abouti à l'utilisation du ObjectMapper
Jackson qui est destiné à être spécifique à HAL comme ObjectMapper à l'échelle de l'application
. Cette pollution signifiait que le formatage HAL était appliqué aux réponses alors qu'il n'aurait pas dû l'être.
La limitation a été corrigée dans Spring HATEOAS 1.0 et son ObjectMapper
spécifique à HAL ne pollue plus l'ensemble de l'application. Si vous souhaitez que l'application principale ObjectMapper
applique une sérialisation de style HAL, vous pouvez la réactiver en la personnalisant:
@Bean public ObjectMapper objectMapper(Jackson2ObjectMapperBuilder builder, HypermediaMappingInformation mappingInformation) { ObjectMapper objectMapper = builder.build(); mappingInformation.configureObjectMapper(objectMapper); return objectMapper; }
Bien que je pense que ce qui précède va travail, je ferai écho à la préoccupation que Daniel a soulevée dans sa réponse concernant le format de la réponse et la conformité avec la spécification HAL. p>
Cela fonctionne très bien !!! Merci beaucoup pour vos messages.
Je recommande d'étendre CollectionModel avec un champ de type collection annoté @JsonValue, puis dans votre assembleur, remplacez toCollectionModel pour renvoyer le CollectionModel personnalisé
@Override public CustomCollectionModel toCollectionModel(Iterable<? extends T> entities) { List<EntityModel<T>> resourceList = new ArrayList<>(); for (T entity : entities) { resourceList.add(toModel(entity)); } return new CustomCollectionModel(resourceList); }
puis dans votre assembleur
XXX
L'exemple de code ne semble pas reproduire le comportement de votre question. L'exécution de
SpringBootUnittestApplication
et l'accès à: 8099 / api / v1 / ability / list
renvoie un objet JSON vide. Je suppose que le magasin de données est vide? Pouvez-vous mettre à jour les exemples pour les rendre aussi minimaux que possible, par exemple en supprimant la dépendance à Mongo et en codant en dur certaines données?@AndyWilkinson Merci beaucoup pour votre réponse. Bien sûr, laissez-moi mettre à jour le Github.
@AndyWilkinson Poussé les modifications dans le référentiel github en désactivant MongoDB. Veuillez vérifier cet hôte local de point de terminaison: / api / v1 / ability / list / noembedded pour les deux projets. Dans spring-boot-unittest, les liens de repo ne seront pas rendus correctement qui utilise spring-boot-2.x et dans spring-hypermedia les liens sont rendus correctement qui utilise spring-boot.15.x. votre aide sera vraiment appréciée.