TSK-1085: Hateoas self-links which contain variables are not working for Paged representationmodels

Bug Fix
* update Aspect
* update unit-test and test "href-self" part of json
* fix checkstyl-finding
This commit is contained in:
Nikita Kolytschew 2020-07-22 00:16:45 +02:00 committed by Nik
parent d6c1040bb0
commit 5030415f17
3 changed files with 25 additions and 15 deletions

View File

@ -1,15 +1,11 @@
package pro.taskana.resource.rest; package pro.taskana.resource.rest;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import java.lang.reflect.Method;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.IanaLinkRelations;
import org.springframework.hateoas.Link; import org.springframework.hateoas.Link;
@ -17,6 +13,7 @@ import org.springframework.hateoas.PagedModel.PageMetadata;
import org.springframework.hateoas.RepresentationModel; import org.springframework.hateoas.RepresentationModel;
import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
import org.springframework.web.util.UriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder;
/** /**
@ -31,12 +28,7 @@ public class PageLinksAspect {
public <T extends RepresentationModel<? extends T> & ProceedingJoinPoint> public <T extends RepresentationModel<? extends T> & ProceedingJoinPoint>
RepresentationModel<T> addLinksToPageResource( RepresentationModel<T> addLinksToPageResource(
ProceedingJoinPoint joinPoint, List<?> data, PageMetadata page) throws Throwable { ProceedingJoinPoint joinPoint, List<?> data, PageMetadata page) throws Throwable {
HttpServletRequest request = final UriComponentsBuilder original = originalUri();
((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
Method method = ((MethodSignature) joinPoint.getSignature()).getMethod();
PageLinks pageLinks = method.getAnnotation(PageLinks.class);
String relativeUrl = pageLinks.value();
UriComponentsBuilder original = originalUri(relativeUrl, request);
RepresentationModel<T> resourceSupport = (RepresentationModel<T>) joinPoint.proceed(); RepresentationModel<T> resourceSupport = (RepresentationModel<T>) joinPoint.proceed();
resourceSupport.add(Link.of(original.toUriString()).withSelfRel()); resourceSupport.add(Link.of(original.toUriString()).withSelfRel());
if (page != null) { if (page != null) {
@ -60,10 +52,11 @@ public class PageLinksAspect {
return resourceSupport; return resourceSupport;
} }
private UriComponentsBuilder originalUri(String relativeUrl, HttpServletRequest request) { private UriComponentsBuilder originalUri() {
// argument to linkTo does not matter as we just want to have the default baseUrl final HttpServletRequest request =
UriComponentsBuilder baseUri = linkTo(PageLinksAspect.class).toUriComponentsBuilder(); ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
baseUri.path(relativeUrl); final UriComponentsBuilder baseUri =
ServletUriComponentsBuilder.fromServletMapping(request).path(request.getRequestURI());
for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) { for (Map.Entry<String, String[]> entry : request.getParameterMap().entrySet()) {
for (String value : entry.getValue()) { for (String value : entry.getValue()) {
baseUri.queryParam(entry.getKey(), value); baseUri.queryParam(entry.getKey(), value);

View File

@ -1,6 +1,7 @@
package pro.taskana.doc.api; package pro.taskana.doc.api;
import static java.nio.charset.StandardCharsets.UTF_8; import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.Matchers.is;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath;
import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields;
@ -351,6 +352,8 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation {
.accept("application/hal+json") .accept("application/hal+json")
.header("Authorization", TEAMLEAD_1_CREDENTIALS)) .header("Authorization", TEAMLEAD_1_CREDENTIALS))
.andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("_links.self.href",
is("http://localhost:8080/api/v1/workbaskets/WBI:100000000000000000000000000000000001")))
.andDo( .andDo(
MockMvcRestDocumentation.document( MockMvcRestDocumentation.document(
"GetSpecificWorkbasketDocTest", responseFields(workbasketFieldDescriptors))); "GetSpecificWorkbasketDocTest", responseFields(workbasketFieldDescriptors)));
@ -383,6 +386,8 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation {
.accept("application/hal+json") .accept("application/hal+json")
.header("Authorization", TEAMLEAD_1_CREDENTIALS)) .header("Authorization", TEAMLEAD_1_CREDENTIALS))
.andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("_links.self.href",
is("http://localhost:8080/api/v1/workbaskets/WBI:100000000000000000000000000000000001")))
.andDo( .andDo(
MockMvcRestDocumentation.document( MockMvcRestDocumentation.document(
"WorkbasketSubset", responseFields(workbasketSubsetFieldDescriptors))); "WorkbasketSubset", responseFields(workbasketSubsetFieldDescriptors)));
@ -411,6 +416,8 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation {
"WBI:100000000000000000000000000000000002")) "WBI:100000000000000000000000000000000002"))
.header("Authorization", TEAMLEAD_1_CREDENTIALS)) .header("Authorization", TEAMLEAD_1_CREDENTIALS))
.andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("_links.self.href",
is("http://localhost:8080/api/v1/workbaskets/WBI:100000000000000000000000000000000002/distribution-targets")))
.andDo( .andDo(
MockMvcRestDocumentation.document( MockMvcRestDocumentation.document(
"GetAllWorkbasketDistributionTargets", "GetAllWorkbasketDistributionTargets",
@ -470,6 +477,8 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation {
.contentType("application/json") .contentType("application/json")
.content(modifiedWorkbasket)) .content(modifiedWorkbasket))
.andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("_links.self.href",
is("http://localhost:8080/api/v1/workbaskets/WBI:100000000000000000000000000000000002")))
.andDo( .andDo(
MockMvcRestDocumentation.document( MockMvcRestDocumentation.document(
"UpdateWorkbasketDocTest", "UpdateWorkbasketDocTest",
@ -500,6 +509,8 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation {
.accept("application/hal+json") .accept("application/hal+json")
.header("Authorization", TEAMLEAD_1_CREDENTIALS)) .header("Authorization", TEAMLEAD_1_CREDENTIALS))
.andExpect(MockMvcResultMatchers.status().isOk()) .andExpect(MockMvcResultMatchers.status().isOk())
.andExpect(MockMvcResultMatchers.jsonPath("_links.self.href",
is("http://localhost:8080/api/v1/workbaskets/WBI:100000000000000000000000000000000001/workbasketAccessItems")))
.andDo( .andDo(
MockMvcRestDocumentation.document( MockMvcRestDocumentation.document(
"AccessItemsDocTest", responseFields(accessItemFieldDescriptors))); "AccessItemsDocTest", responseFields(accessItemFieldDescriptors)));

View File

@ -5,11 +5,13 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static pro.taskana.common.rest.RestHelper.TEMPLATE; import static pro.taskana.common.rest.RestHelper.TEMPLATE;
import java.time.Instant; import java.time.Instant;
import java.util.Optional;
import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.ParameterizedTypeReference; import org.springframework.core.ParameterizedTypeReference;
import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.IanaLinkRelations;
import org.springframework.hateoas.Link;
import org.springframework.hateoas.MediaTypes; import org.springframework.hateoas.MediaTypes;
import org.springframework.http.HttpEntity; import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod; import org.springframework.http.HttpMethod;
@ -49,14 +51,18 @@ class WorkbasketControllerIntTest {
@Test @Test
void testGetWorkbasket() { void testGetWorkbasket() {
final String url = restHelper.toUrl(Mapping.URL_WORKBASKET_ID,
"WBI:100000000000000000000000000000000006");
ResponseEntity<WorkbasketRepresentationModel> response = ResponseEntity<WorkbasketRepresentationModel> response =
TEMPLATE.exchange( TEMPLATE.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, "WBI:100000000000000000000000000000000006"), url,
HttpMethod.GET, HttpMethod.GET,
restHelper.defaultRequest(), restHelper.defaultRequest(),
ParameterizedTypeReference.forType(WorkbasketRepresentationModel.class)); ParameterizedTypeReference.forType(WorkbasketRepresentationModel.class));
assertThat(response.getBody()).isNotNull(); assertThat(response.getBody()).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull(); assertThat(response.getBody().getLink(IanaLinkRelations.SELF)).isNotNull();
assertThat(response.getBody().getLink(IanaLinkRelations.SELF))
.isEqualTo(Optional.of(Link.of(url)));
assertThat(response.getHeaders().getContentType()).isEqualTo(MediaTypes.HAL_JSON); assertThat(response.getHeaders().getContentType()).isEqualTo(MediaTypes.HAL_JSON);
} }