how to introduce etag and version headers with spring data rest abstraction

时间:2015-06-15 14:17:20

标签: spring spring-mvc spring-data spring-data-rest spring-hateoas

Hi I am using spring data rest with Jpa in my project to expose HAL based rest webservices .It works well for most of my cases and for further customization I do use additional controllers and call spring data repositories to fetch data for me and use hateos resource for displaying those with links exposed via hateos entityLinks .This is great and works for most of my use cases . Now I have a few additional requirement wherein I want to put etag headers for server caching and instance level version link headers [https://tools.ietf.org/html/rfc5988] more specific https://tools.ietf.org/html/rfc5829#page-3 as below for my responses .

GET /81822 HTTP/1.1 ...

HTTP/1.1 OK
Host: dumbserver.com
Content-Type: application/json
Link: </81822 ;v=1.1>; rel="previous";
       </81822 >; rel="current";
       </81822 /version-history>; rel="version-history";

{

Is this possible via using hateos interfaces or will I have to go for a custom approach by adding these via HttpServletResponse or responseentity.getHeaader and add custom code for handling versioning .I think Spring data rest or hateos must work on providing abstractions for these as well.

1 个答案:

答案 0 :(得分:0)

我认为,一旦从控制器覆盖Spring Data Rest端点,即使您的控制器使用@RepositoryRestController进行注释,您也必须自行滚动。

我们通过创建一个基本控制器来完成此操作,该控制器负责将entity包裹为Resource,而ResponseEntity又包裹在ETag

我们的versionNumber恰好基于具有@Version注释的实体protected ResponseEntity<Resource<T>> createResponse(T entity, PersistentEntityResourceAssembler assembler) { def bb = ResponseEntity.ok() bb.eTag(ETag.from("${entity.versionNumber}").toString()) return bb.body(createResource(entity, assembler)) } protected Resource<T> createResource(T entity, ResourceAssembler assembler) { def resource = resourceCreator.toResource(assembler, entity) resource.add(buildSelfLink(resource)) resource } Link buildSelfLink(Resource<T> resource) { linkBuilder.buildSelfLinkWithId(this.class, resource.content.id) } Link prependLinkWithApiBase(ControllerLinkBuilder linkBuilder) { URI uri = linkBuilder.toUri() String origPath = uri.rawPath String newPath = "$API_BASE$origPath" log.debug("Replacing {} with {}", origPath, newPath) def uriBuilder = UriComponentsBuilder.fromUri(uri).replacePath(newPath) new Link(uriBuilder.toUriString()) } Link buildSelfLinkWithId(Class c, def id) { /* When trying to use `methodOn` to properly build the self URI, we ran into this. Going the dumb route instead. java.lang.ClassCastException: Cannot cast com.MyEntity$$EnhancerByCGLIB$$a1654b7b to com.MyEntity at java.lang.Class.cast(Class.java:3369) ~[na:1.8.0_92] at org.sfw.hateoas.core.DummyInvocationUtils $InvocationRecordingMethodInterceptor.intercept(DummyInvocationUtils.java:100) ~[spring-hateoas-0.20.0.RELEASE.jar:na] */ //Due to https://github.com/spring-projects/spring-hateoas/issues/434 we have hoops to jump def linkBuilder = linkTo(c).slash(id) prependLinkWithApiBase(linkBuilder) }

import requests
links = [link.strip() for link in requests.get('http://pastebin.com/raw/JGM3p9c9').text.split('\n')]
相关问题