diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/resource/rest/PageLinksAspect.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/resource/rest/PageLinksAspect.java index 11a41bc27..901232ec5 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/resource/rest/PageLinksAspect.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/resource/rest/PageLinksAspect.java @@ -1,15 +1,11 @@ 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.Map; import javax.servlet.http.HttpServletRequest; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; -import org.aspectj.lang.reflect.MethodSignature; import org.springframework.context.annotation.Configuration; import org.springframework.hateoas.IanaLinkRelations; import org.springframework.hateoas.Link; @@ -17,6 +13,7 @@ import org.springframework.hateoas.PagedModel.PageMetadata; import org.springframework.hateoas.RepresentationModel; import org.springframework.web.context.request.RequestContextHolder; import org.springframework.web.context.request.ServletRequestAttributes; +import org.springframework.web.servlet.support.ServletUriComponentsBuilder; import org.springframework.web.util.UriComponentsBuilder; /** @@ -31,12 +28,7 @@ public class PageLinksAspect { public & ProceedingJoinPoint> RepresentationModel addLinksToPageResource( ProceedingJoinPoint joinPoint, List data, PageMetadata page) throws Throwable { - HttpServletRequest request = - ((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); + final UriComponentsBuilder original = originalUri(); RepresentationModel resourceSupport = (RepresentationModel) joinPoint.proceed(); resourceSupport.add(Link.of(original.toUriString()).withSelfRel()); if (page != null) { @@ -60,10 +52,11 @@ public class PageLinksAspect { return resourceSupport; } - private UriComponentsBuilder originalUri(String relativeUrl, HttpServletRequest request) { - // argument to linkTo does not matter as we just want to have the default baseUrl - UriComponentsBuilder baseUri = linkTo(PageLinksAspect.class).toUriComponentsBuilder(); - baseUri.path(relativeUrl); + private UriComponentsBuilder originalUri() { + final HttpServletRequest request = + ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest(); + final UriComponentsBuilder baseUri = + ServletUriComponentsBuilder.fromServletMapping(request).path(request.getRequestURI()); for (Map.Entry entry : request.getParameterMap().entrySet()) { for (String value : entry.getValue()) { baseUri.queryParam(entry.getKey(), value); diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/doc/api/WorkbasketControllerRestDocumentation.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/doc/api/WorkbasketControllerRestDocumentation.java index 3519151a5..62048512e 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/doc/api/WorkbasketControllerRestDocumentation.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/doc/api/WorkbasketControllerRestDocumentation.java @@ -1,6 +1,7 @@ package pro.taskana.doc.api; import static java.nio.charset.StandardCharsets.UTF_8; +import static org.hamcrest.Matchers.is; import static org.junit.Assert.assertEquals; import static org.springframework.restdocs.payload.PayloadDocumentation.fieldWithPath; import static org.springframework.restdocs.payload.PayloadDocumentation.requestFields; @@ -351,6 +352,8 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation { .accept("application/hal+json") .header("Authorization", TEAMLEAD_1_CREDENTIALS)) .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("_links.self.href", + is("http://localhost:8080/api/v1/workbaskets/WBI:100000000000000000000000000000000001"))) .andDo( MockMvcRestDocumentation.document( "GetSpecificWorkbasketDocTest", responseFields(workbasketFieldDescriptors))); @@ -383,6 +386,8 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation { .accept("application/hal+json") .header("Authorization", TEAMLEAD_1_CREDENTIALS)) .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("_links.self.href", + is("http://localhost:8080/api/v1/workbaskets/WBI:100000000000000000000000000000000001"))) .andDo( MockMvcRestDocumentation.document( "WorkbasketSubset", responseFields(workbasketSubsetFieldDescriptors))); @@ -411,6 +416,8 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation { "WBI:100000000000000000000000000000000002")) .header("Authorization", TEAMLEAD_1_CREDENTIALS)) .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("_links.self.href", + is("http://localhost:8080/api/v1/workbaskets/WBI:100000000000000000000000000000000002/distribution-targets"))) .andDo( MockMvcRestDocumentation.document( "GetAllWorkbasketDistributionTargets", @@ -470,6 +477,8 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation { .contentType("application/json") .content(modifiedWorkbasket)) .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("_links.self.href", + is("http://localhost:8080/api/v1/workbaskets/WBI:100000000000000000000000000000000002"))) .andDo( MockMvcRestDocumentation.document( "UpdateWorkbasketDocTest", @@ -500,6 +509,8 @@ class WorkbasketControllerRestDocumentation extends BaseRestDocumentation { .accept("application/hal+json") .header("Authorization", TEAMLEAD_1_CREDENTIALS)) .andExpect(MockMvcResultMatchers.status().isOk()) + .andExpect(MockMvcResultMatchers.jsonPath("_links.self.href", + is("http://localhost:8080/api/v1/workbaskets/WBI:100000000000000000000000000000000001/workbasketAccessItems"))) .andDo( MockMvcRestDocumentation.document( "AccessItemsDocTest", responseFields(accessItemFieldDescriptors))); diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/workbasket/rest/WorkbasketControllerIntTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/workbasket/rest/WorkbasketControllerIntTest.java index 65019da1b..b2609ac39 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/workbasket/rest/WorkbasketControllerIntTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/workbasket/rest/WorkbasketControllerIntTest.java @@ -5,11 +5,13 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import static pro.taskana.common.rest.RestHelper.TEMPLATE; import java.time.Instant; +import java.util.Optional; import org.assertj.core.api.ThrowableAssert.ThrowingCallable; import org.junit.jupiter.api.Test; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.ParameterizedTypeReference; import org.springframework.hateoas.IanaLinkRelations; +import org.springframework.hateoas.Link; import org.springframework.hateoas.MediaTypes; import org.springframework.http.HttpEntity; import org.springframework.http.HttpMethod; @@ -49,14 +51,18 @@ class WorkbasketControllerIntTest { @Test void testGetWorkbasket() { + final String url = restHelper.toUrl(Mapping.URL_WORKBASKET_ID, + "WBI:100000000000000000000000000000000006"); ResponseEntity response = TEMPLATE.exchange( - restHelper.toUrl(Mapping.URL_WORKBASKET_ID, "WBI:100000000000000000000000000000000006"), + url, HttpMethod.GET, restHelper.defaultRequest(), ParameterizedTypeReference.forType(WorkbasketRepresentationModel.class)); assertThat(response.getBody()).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); }