2017-05-28 1 views
0

J'essaie d'utiliser des processeurs de ressources Spring Data Rest pour ajouter un lien à une ressource; Cependant, lors de tests d'intégration MockMvc, il explose avec une exception de transtypage de classe, se plaignant qu'un EmptyCollectionEmbeddedWrapper ne peut pas être converti en ResourceSupport (les limites du type paramétrés de ResourceProcessor):Échec du traitement des ressources Spring Data Rest

java.lang.ClassCastException: org.springframework.hateoas.core.EmbeddedWrappers$EmptyCollectionEmbeddedWrapper cannot be cast to org.springframework.hateoas.ResourceSupport 
    at org.springframework.data.rest.webmvc.ResourceProcessorInvoker$DefaultProcessorWrapper.invokeProcessor(ResourceProcessorInvoker.java:225) ~[spring-data-rest-webmvc-2.5.3.RELEASE.jar:na] 
    at org.springframework.data.rest.webmvc.ResourceProcessorInvoker.invokeProcessorsFor(ResourceProcessorInvoker.java:142) ~[spring-data-rest-webmvc-2.5.3.RELEASE.jar:na] 
    at org.springframework.data.rest.webmvc.ResourceProcessorInvoker.invokeProcessorsFor(ResourceProcessorInvoker.java:119) ~[spring-data-rest-webmvc-2.5.3.RELEASE.jar:na] 
    at org.springframework.data.rest.webmvc.ResourceProcessorHandlerMethodReturnValueHandler.handleReturnValue(ResourceProcessorHandlerMethodReturnValueHandler.java:114) ~[spring-data-rest-webmvc-2.5.3.RELEASE.jar:na] 
    at org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite.handleReturnValue(HandlerMethodReturnValueHandlerComposite.java:81) ~[spring-web-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:130) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897) ~[spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:861) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:622) ~[tomcat-embed-core-8.5.5.jar:8.5.5] 
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846) [spring-webmvc-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.test.web.servlet.TestDispatcherServlet.service(TestDispatcherServlet.java:65) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:729) ~[tomcat-embed-core-8.5.5.jar:8.5.5] 
    at org.springframework.mock.web.MockFilterChain$ServletFilterProxy.doFilter(MockFilterChain.java:167) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.mock.web.MockFilterChain.doFilter(MockFilterChain.java:134) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 
    at org.springframework.test.web.servlet.MockMvc.perform(MockMvc.java:155) [spring-test-4.3.3.RELEASE.jar:4.3.3.RELEASE] 

Il est prévu que la valeur retournée devrait être vide à ce stade (comme le suggère EmptyCollectionEmbeddedWrapper), mais bien sûr, la distribution n'est pas prévue. Comme le suggère la trace de la pile, cette exception se produit lors du post-traitement des ressources; si je supprime un simple processeur de ressources que j'ai pour ce type, l'exception de cast de classe disparaît et la requête réussit. Cela me surprend, car le processeur de ressources est essentiellement retiré de la documentation.

De manière plus détaillée, le type de paramètre de ressource est Notification; la demande MockMvc qui ne ressemble à:

perform(get(entityLinks.linkToSearchResource(Notification.class, NotificationRepository.ACTIVE_SEARCH) 
      .expand(Collections.singletonMap("projectId", 1)).getHref())) 
      .andExpect(status().isOk()) 
      .andExpect(jsonPath("$._embedded.notifications").isEmpty()); 

Et le ResourceProcessor ressemble:

@Bean 
public ResourceProcessor<Resource<Notification>> notificationResourceProcessor(RepositoryEntityLinks entityLinks) { 
    return notificationResource -> { 
     notificationResource.add(entityLinks.linkToCollectionResource(NotificationAction.class)); 
     return notificationResource; 
    }; 
} 

Je suppose que j'ai mal configuré, parce que cela semble être une utilisation très basique du printemps de repos de données. Qu'est-ce que je rate?

Répondre

1

Après le débogage dans ResourceProcessorInvoker a constaté que le type résolu pour le ResourceProcessor n'a pas été ResourceProcessor<Resource<T>> (dans votre cas ResourceProcessor<Resource<Notification>>) comme prévu, mais ResourceProcessor<T extends ResourceSupport>>. La raison en est la création du processeur en utilisant lambda. La création de la classe anonyme à l'ancienne façon résolu le problème dans mon cas:

@Bean 
public ResourceProcessor<Resource<Notification>> notificationResourceProcessor(RepositoryEntityLinks entityLinks) { 
    return new ResourceProcessor<Resource<Notification>>() { 
     @Override 
     public Resource<Notification> process(Resource<Notification> notificationResource) { 
      notificationResource.add(entityLinks.linkToCollectionResource(NotificationAction.class)); 
      return notificationResource; 
     } 
    }; 
}