2 votes

Personnaliser les endpoints avec Spring Data REST

J'ai un projet avec Spring Boot 1.5.7, Spring Data REST, Hibernate, Spring JPA, Swagger2.

J'ai deux beans comme ça:

    @Entity
public class TicketBundle extends AbstractEntity {
    private static final long serialVersionUID = 404514926837058071L;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private List notes = new ArrayList<>();

    .....
    }

et

    @Entity
public class Note extends AbstractEntity {
    private static final long serialVersionUID = -5062313842902549565L;

    @Lob
    private String text;
    ...
    }

J'expose mes méthodes via le Repository:

@Transactional
@RepositoryRestResource(excerptProjection = TicketBundleProjection.class)
@PreAuthorize("isAuthenticated()")
public interface TicketBundleRepository extends PagingAndSortingRepository {
....
}

donc dans swagger, je vois le point de terminaison qui m'intéresse pour charger la collection de notes d'un ensemble de tickets spécifique:

entrer la description de l'image ici

Maintenant, je veux remplacer le GET /api/v1/ticketBundles/{id}/notes par défaut avec ma méthode personnalisée que j'ai mise dans TicketBundleRepository:

@Transactional(readOnly = true)
@RestResource(rel = "ticketBundleNotes", path = "/ticketBundles/{id}/notes")
@RequestMapping(method = RequestMethod.GET, path = "/ticketBundles/{id}/notes")
@Query("SELECT n FROM TicketBundle tb JOIN tb.notes n WHERE tb.id=:id ORDER BY n.createdDate DESC,n.id DESC")
public Page getNotes(@Param("id") long id, Pageable pageable);

Il est très pratique de créer la requête de cette manière car j'ai besoin d'utiliser Pageable et de retourner une Page. Malheureusement, j'ai deux problèmes à ce stade.

Premier problème La méthode est mappée sur le point de terminaison /api/v1/ticketBundles/search/ticketBundles/{id}/notes au lieu de /api/v1/ticketBundles/ticketBundles/{id}/notes entrer la description de l'image ici

Deuxième problème Lorsque j'appelle la méthode depuis swagger, je reçois une HTTP 404:

La requête semble erronée. Il semble que la variable de chemin n'est pas comprise:

curl -X GET --header 'Accept: application/json' 'http://localhost:8080/api/v1/ticketBundles/search/ticketBundles/{id}/notes?id=1'

Voici la réponse du serveur:

{
   "timestamp": "2017-10-05T14:00:35.563+0000",
   "status": 404,
   "error": "Not Found",
   "message": "Aucun message disponible",
   "path": "/api/v1/ticketBundles/search/ticketBundles/%7Bid%7D/notes"
 }

sans aucune erreur du côté du serveur.

Y a-t-il un moyen de remplacer le point de terminaison GET/api/v1/ticketBundles/{id}/notes en l'exposant via Repository sans utiliser un contrôleur personnalisé (en utilisant cela je perdrais les facilités pour gérer le Pageable)?

De plus, qu'est-ce que je fais mal pour obtenir un HTTP 404 dans l'appel que j'ai montré ci-dessus?

0voto

Srikanth Anusuri Points 354

Je crois que vous utilisez des annotations incorrectes. Vous devriez annoter votre classe avec @RestController et utiliser @PathVariable sur votre méthode au lieu de @Param. Voici un exemple fonctionnel, que vous voudrez peut-être adapter à vos besoins.

@org.springframework.data.rest.webmvc.RepositoryRestController
@org.springframework.web.bind.annotation.RestController
public interface PersonRepository extends org.springframework.data.repository.PagingAndSortingRepository {

    @org.springframework.web.bind.annotation.GetMapping(path = "/people/{id}")
    Person findById(@org.springframework.web.bind.annotation.PathVariable("id") Long id);

}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X