diff --git a/lib/taskana-core/src/main/java/pro/taskana/workbasket/api/WorkbasketService.java b/lib/taskana-core/src/main/java/pro/taskana/workbasket/api/WorkbasketService.java index 32122da44..920354709 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/workbasket/api/WorkbasketService.java +++ b/lib/taskana-core/src/main/java/pro/taskana/workbasket/api/WorkbasketService.java @@ -3,6 +3,7 @@ package pro.taskana.workbasket.api; import java.util.List; import pro.taskana.common.api.BulkOperationResults; +import pro.taskana.common.api.exceptions.ConcurrencyException; import pro.taskana.common.api.exceptions.DomainNotFoundException; import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; @@ -63,7 +64,8 @@ public interface WorkbasketService { * @return the updated Workbasket * @throws NotAuthorizedException if the current user is not authorized to update the work basket */ - Workbasket updateWorkbasket(Workbasket workbasket) throws NotAuthorizedException; + Workbasket updateWorkbasket(Workbasket workbasket) + throws NotAuthorizedException, WorkbasketNotFoundException, ConcurrencyException; /** * Returns a new WorkbasketAccessItem which is not persisted. diff --git a/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketServiceImpl.java b/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketServiceImpl.java index 9dc6e0cdd..544c0e024 100644 --- a/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketServiceImpl.java +++ b/lib/taskana-core/src/main/java/pro/taskana/workbasket/internal/WorkbasketServiceImpl.java @@ -15,6 +15,7 @@ import org.slf4j.LoggerFactory; import pro.taskana.TaskanaEngineConfiguration; import pro.taskana.common.api.BulkOperationResults; import pro.taskana.common.api.LoggerUtils; +import pro.taskana.common.api.exceptions.ConcurrencyException; import pro.taskana.common.api.exceptions.DomainNotFoundException; import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; @@ -139,24 +140,46 @@ public class WorkbasketServiceImpl implements WorkbasketService { } @Override - public Workbasket updateWorkbasket(Workbasket workbasketToUpdate) throws NotAuthorizedException { - LOGGER.debug("entry to updateWorkbasket(workbasket)", workbasketToUpdate); + public Workbasket updateWorkbasket(Workbasket workbasketToUpdate) + throws NotAuthorizedException, WorkbasketNotFoundException, ConcurrencyException { + + LOGGER.debug("entry to updateWorkbasket(Workbasket = {})", workbasketToUpdate); + taskanaEngine.getEngine().checkRoleMembership(TaskanaRole.BUSINESS_ADMIN, TaskanaRole.ADMIN); - WorkbasketImpl workbasket = (WorkbasketImpl) workbasketToUpdate; + WorkbasketImpl workbasketImplToUpdate = null; + try { + taskanaEngine.openConnection(); - workbasket.setModified(Instant.now()); - if (workbasket.getId() == null || workbasket.getId().isEmpty()) { - workbasketMapper.updateByKeyAndDomain(workbasket); + + workbasketImplToUpdate = (WorkbasketImpl) workbasketToUpdate; + + Workbasket oldWorkbasket = + this.getWorkbasket(workbasketImplToUpdate.getKey(), workbasketImplToUpdate.getDomain()); + + checkModifiedHasNotChanged(oldWorkbasket, workbasketImplToUpdate); + + workbasketImplToUpdate.setModified(Instant.now()); + + if (workbasketImplToUpdate.getId() == null || workbasketImplToUpdate.getId().isEmpty()) { + + workbasketMapper.updateByKeyAndDomain(workbasketImplToUpdate); + } else { - workbasketMapper.update(workbasket); + + workbasketMapper.update(workbasketImplToUpdate); } - LOGGER.debug("Method updateWorkbasket() updated workbasket '{}'", workbasket.getId()); - return workbasket; + LOGGER.debug( + "Method updateWorkbasket() updated workbasket '{}'", workbasketImplToUpdate.getId()); + + return workbasketImplToUpdate; + } finally { + taskanaEngine.returnConnection(); - LOGGER.debug("exit from updateWorkbasket(). Returning result {} ", workbasket); + + LOGGER.debug("exit from updateWorkbasket(). Returning result {} ", workbasketImplToUpdate); } } @@ -829,6 +852,26 @@ public class WorkbasketServiceImpl implements WorkbasketService { } } + /** + * Check if current workbasket is based on the newest (by modified). + * + * @param oldWorkbasket the old workbasket in the system + * @param workbasketImplToUpdate the workbasket to update + * @throws ConcurrencyException if the workbasket has been modified by some other process. + * @throws WorkbasketNotFoundException if the given workbasket does not exist. + */ + void checkModifiedHasNotChanged(Workbasket oldWorkbasket, WorkbasketImpl workbasketImplToUpdate) + throws ConcurrencyException { + + if (!oldWorkbasket.getModified().equals(workbasketImplToUpdate.getModified())) { + + throw new ConcurrencyException( + "The current Workbasket has been modified while editing. " + + "The values can not be updated. Workbasket " + + workbasketImplToUpdate.toString()); + } + } + private void validateWorkbasketId(String workbasketId) throws InvalidArgumentException { if (workbasketId == null) { throw new InvalidArgumentException("The WorkbasketId can“t be NULL"); diff --git a/lib/taskana-core/src/test/java/acceptance/workbasket/UpdateWorkbasketAccTest.java b/lib/taskana-core/src/test/java/acceptance/workbasket/UpdateWorkbasketAccTest.java index bb85ea107..d49a62937 100644 --- a/lib/taskana-core/src/test/java/acceptance/workbasket/UpdateWorkbasketAccTest.java +++ b/lib/taskana-core/src/test/java/acceptance/workbasket/UpdateWorkbasketAccTest.java @@ -1,14 +1,16 @@ package acceptance.workbasket; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotEquals; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import acceptance.AbstractAccTest; import java.time.Instant; -import org.junit.jupiter.api.Assertions; +import java.time.temporal.ChronoUnit; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; +import pro.taskana.common.api.exceptions.ConcurrencyException; import pro.taskana.common.api.exceptions.NotAuthorizedException; import pro.taskana.security.JaasExtension; import pro.taskana.security.WithAccessId; @@ -16,6 +18,7 @@ import pro.taskana.workbasket.api.Workbasket; import pro.taskana.workbasket.api.WorkbasketService; import pro.taskana.workbasket.api.WorkbasketType; import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException; +import pro.taskana.workbasket.internal.WorkbasketImpl; /** Acceptance test for all "update workbasket" scenarios. */ @ExtendWith(JaasExtension.class) @@ -29,9 +32,11 @@ public class UpdateWorkbasketAccTest extends AbstractAccTest { userName = "teamlead_1", groupNames = {"group_1", "businessadmin"}) @Test - public void testUpdateWorkbasket() throws NotAuthorizedException, WorkbasketNotFoundException { + public void testUpdateWorkbasket() + throws NotAuthorizedException, WorkbasketNotFoundException, ConcurrencyException { WorkbasketService workbasketService = taskanaEngine.getWorkbasketService(); Workbasket workbasket = workbasketService.getWorkbasket("GPK_KSC", "DOMAIN_A"); + final Instant modified = workbasket.getModified(); workbasket.setName("new name"); @@ -49,11 +54,49 @@ public class UpdateWorkbasketAccTest extends AbstractAccTest { workbasketService.updateWorkbasket(workbasket); Workbasket updatedWorkbasket = workbasketService.getWorkbasket("GPK_KSC", "DOMAIN_A"); - assertEquals(workbasket.getId(), updatedWorkbasket.getId()); - assertEquals(workbasket.getCreated(), updatedWorkbasket.getCreated()); - assertNotEquals(modified, updatedWorkbasket.getModified()); - assertEquals("new name", updatedWorkbasket.getName()); - assertEquals(WorkbasketType.TOPIC, updatedWorkbasket.getType()); + + assertThat(updatedWorkbasket.getId()).isEqualTo(workbasket.getId()); + assertThat(updatedWorkbasket.getCreated()).isEqualTo(workbasket.getCreated()); + assertThat(updatedWorkbasket.getName()).isEqualTo("new name"); + assertThat(updatedWorkbasket.getType()).isEqualTo(WorkbasketType.TOPIC); + assertThat(updatedWorkbasket.getModified()).isNotEqualTo(modified); + } + + @WithAccessId( + userName = "teamlead_1", + groupNames = {"group_1", "businessadmin"}) + @Test + public void testUpdateWorkbasketWithConcurrentModificationShouldThrowException() + throws NotAuthorizedException, WorkbasketNotFoundException, ConcurrencyException { + + WorkbasketService workbasketService = taskanaEngine.getWorkbasketService(); + + WorkbasketImpl workbasket = + (WorkbasketImpl) workbasketService.getWorkbasket("GPK_KSC", "DOMAIN_A"); + + workbasket.setModified(workbasket.getModified().minus(1, ChronoUnit.SECONDS)); + + assertThatExceptionOfType(ConcurrencyException.class) + .isThrownBy(() -> workbasketService.updateWorkbasket(workbasket)); + } + + @WithAccessId( + userName = "teamlead_1", + groupNames = {"group_1", "businessadmin"}) + @Test + public void testUpdateWorkbasketOfNonExistingWorkbasketShouldThrowException() + throws NotAuthorizedException, WorkbasketNotFoundException, ConcurrencyException { + + WorkbasketService workbasketService = taskanaEngine.getWorkbasketService(); + + WorkbasketImpl workbasket = + (WorkbasketImpl) workbasketService.getWorkbasket("GPK_KSC", "DOMAIN_A"); + + workbasket.setDomain("InvalidDomain"); + workbasket.setKey("InvalidKey"); + + assertThatExceptionOfType(WorkbasketNotFoundException.class) + .isThrownBy(() -> workbasketService.updateWorkbasket(workbasket)); } @WithAccessId( @@ -67,7 +110,7 @@ public class UpdateWorkbasketAccTest extends AbstractAccTest { workbasket.setName("new name"); - Assertions.assertThrows( - NotAuthorizedException.class, () -> workbasketService.updateWorkbasket(workbasket)); + assertThatThrownBy(() -> workbasketService.updateWorkbasket(workbasket)) + .isInstanceOf(NotAuthorizedException.class); } } diff --git a/lib/taskana-core/src/test/java/pro/taskana/workbasket/internal/WorkbasketServiceImplTest.java b/lib/taskana-core/src/test/java/pro/taskana/workbasket/internal/WorkbasketServiceImplTest.java index 669cb82b6..7d1cac610 100644 --- a/lib/taskana-core/src/test/java/pro/taskana/workbasket/internal/WorkbasketServiceImplTest.java +++ b/lib/taskana-core/src/test/java/pro/taskana/workbasket/internal/WorkbasketServiceImplTest.java @@ -1,5 +1,7 @@ package pro.taskana.workbasket.internal; +import static org.assertj.core.api.Assertions.assertThatCode; +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.startsWith; @@ -8,11 +10,14 @@ import static org.hamcrest.core.IsNot.not; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.doReturn; +import static org.mockito.Mockito.lenient; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyNoMoreInteractions; import static org.mockito.Mockito.when; +import java.time.Instant; +import java.time.temporal.ChronoUnit; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -29,6 +34,7 @@ import org.mockito.junit.jupiter.MockitoExtension; import pro.taskana.TaskanaEngineConfiguration; import pro.taskana.common.api.TaskanaEngine; +import pro.taskana.common.api.exceptions.ConcurrencyException; import pro.taskana.common.api.exceptions.DomainNotFoundException; import pro.taskana.common.api.exceptions.NotAuthorizedException; import pro.taskana.common.internal.InternalTaskanaEngine; @@ -70,7 +76,7 @@ class WorkbasketServiceImplTest { @BeforeEach void setup() { - when(internalTaskanaEngineMock.getEngine()).thenReturn(taskanaEngine); + lenient().when(internalTaskanaEngineMock.getEngine()).thenReturn(taskanaEngine); } @Test @@ -189,6 +195,27 @@ class WorkbasketServiceImplTest { .isInstanceOf(WorkbasketAccessItemAlreadyExistException.class); } + @Test + void testCheckModifiedHasNotChanged() throws Exception { + + Instant expectedModifiedTimestamp = Instant.now(); + + WorkbasketImpl oldWb = createTestWorkbasket(null, "Key-1"); + WorkbasketImpl workbasketImplToUpdate = createTestWorkbasket(null, "Key-2"); + oldWb.setModified(expectedModifiedTimestamp); + workbasketImplToUpdate.setModified(expectedModifiedTimestamp); + + assertThatCode( + () -> workbasketServiceSpy.checkModifiedHasNotChanged(oldWb, workbasketImplToUpdate)) + .doesNotThrowAnyException(); + + workbasketImplToUpdate.setModified(expectedModifiedTimestamp.minus(1, ChronoUnit.HOURS)); + + assertThatExceptionOfType(ConcurrencyException.class) + .isThrownBy( + () -> workbasketServiceSpy.checkModifiedHasNotChanged(oldWb, workbasketImplToUpdate)); + } + private WorkbasketImpl createTestWorkbasket(String id, String key) { WorkbasketImpl workbasket = new WorkbasketImpl(); workbasket.setId(id); diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/TaskanaRestExceptionHandler.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/TaskanaRestExceptionHandler.java index a1e2f3a67..8eb2783a6 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/TaskanaRestExceptionHandler.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/TaskanaRestExceptionHandler.java @@ -99,7 +99,7 @@ public class TaskanaRestExceptionHandler extends ResponseEntityExceptionHandler @ExceptionHandler(ConcurrencyException.class) protected ResponseEntity handleConcurrencyException( ConcurrencyException ex, WebRequest req) { - return buildResponse(ex, req, HttpStatus.LOCKED); + return buildResponse(ex, req, HttpStatus.CONFLICT); } @ExceptionHandler(WorkbasketInUseException.class) diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketController.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketController.java index 6604e5489..a25f01f4e 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketController.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketController.java @@ -22,6 +22,7 @@ import org.springframework.web.bind.annotation.RestController; import pro.taskana.common.api.BaseQuery.SortDirection; import pro.taskana.common.api.LoggerUtils; +import pro.taskana.common.api.exceptions.ConcurrencyException; import pro.taskana.common.api.exceptions.DomainNotFoundException; import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; @@ -177,7 +178,8 @@ public class WorkbasketController extends AbstractPagingController { public ResponseEntity updateWorkbasket( @PathVariable(value = "workbasketId") String workbasketId, @RequestBody WorkbasketResource workbasketResource) - throws InvalidWorkbasketException, WorkbasketNotFoundException, NotAuthorizedException { + throws InvalidWorkbasketException, WorkbasketNotFoundException, + NotAuthorizedException, ConcurrencyException { LOGGER.debug("Entry to updateWorkbasket(workbasketId= {})", workbasketId); ResponseEntity result; if (workbasketId.equals(workbasketResource.workbasketId)) { diff --git a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketDefinitionController.java b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketDefinitionController.java index 36752d3d7..c60584ebf 100644 --- a/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketDefinitionController.java +++ b/rest/taskana-rest-spring/src/main/java/pro/taskana/rest/WorkbasketDefinitionController.java @@ -24,6 +24,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; +import pro.taskana.common.api.exceptions.ConcurrencyException; import pro.taskana.common.api.exceptions.DomainNotFoundException; import pro.taskana.common.api.exceptions.InvalidArgumentException; import pro.taskana.common.api.exceptions.NotAuthorizedException; @@ -40,6 +41,7 @@ import pro.taskana.workbasket.api.exceptions.WorkbasketAccessItemAlreadyExistExc import pro.taskana.workbasket.api.exceptions.WorkbasketAlreadyExistException; import pro.taskana.workbasket.api.exceptions.WorkbasketNotFoundException; import pro.taskana.workbasket.internal.WorkbasketAccessItemImpl; +import pro.taskana.workbasket.internal.WorkbasketImpl; /** Controller for all {@link WorkbasketDefinitionResource} related endpoints. */ @RestController @@ -110,7 +112,8 @@ public class WorkbasketDefinitionController { public ResponseEntity importWorkbaskets(@RequestParam("file") MultipartFile file) throws IOException, NotAuthorizedException, DomainNotFoundException, InvalidWorkbasketException, WorkbasketAlreadyExistException, WorkbasketNotFoundException, - InvalidArgumentException, WorkbasketAccessItemAlreadyExistException { + InvalidArgumentException, WorkbasketAccessItemAlreadyExistException, + ConcurrencyException { LOGGER.debug("Entry to importWorkbaskets()"); ObjectMapper mapper = new ObjectMapper(); mapper.enable(SerializationFeature.INDENT_OUTPUT); @@ -134,9 +137,13 @@ public class WorkbasketDefinitionController { for (WorkbasketDefinitionResource definition : definitions) { Workbasket importedWb = workbasketDefinitionAssembler.toModel(definition.getWorkbasket()); String newId; - Workbasket wbWithoutId = removeId(importedWb); + WorkbasketImpl wbWithoutId = (WorkbasketImpl) removeId(importedWb); if (systemIds.containsKey(logicalId(importedWb))) { + Workbasket modifiedWb = + workbasketService.getWorkbasket(importedWb.getKey(), importedWb.getDomain()); + wbWithoutId.setModified(modifiedWb.getModified()); workbasketService.updateWorkbasket(wbWithoutId); + newId = systemIds.get(logicalId(importedWb)); } else { newId = workbasketService.createWorkbasket(wbWithoutId).getId(); diff --git a/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/WorkbasketControllerIntTest.java b/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/WorkbasketControllerIntTest.java index f60fb6ae0..e7d2c7d11 100644 --- a/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/WorkbasketControllerIntTest.java +++ b/rest/taskana-rest-spring/src/test/java/pro/taskana/rest/WorkbasketControllerIntTest.java @@ -1,11 +1,11 @@ package pro.taskana.rest; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.junit.Assert.fail; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.time.Instant; import java.util.Iterator; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Test; @@ -23,7 +23,9 @@ import pro.taskana.RestHelper; import pro.taskana.TaskanaSpringBootTest; import pro.taskana.rest.resource.DistributionTargetListResource; import pro.taskana.rest.resource.DistributionTargetResource; +import pro.taskana.rest.resource.WorkbasketResource; import pro.taskana.rest.resource.WorkbasketSummaryListResource; +import pro.taskana.workbasket.api.WorkbasketType; /** Test WorkbasketController. */ @TaskanaSpringBootTest @@ -45,7 +47,7 @@ class WorkbasketControllerIntTest { HttpMethod.GET, restHelper.defaultRequest(), ParameterizedTypeReference.forType(WorkbasketSummaryListResource.class)); - assertNotNull(response.getBody().getLink(Link.REL_SELF)); + assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull(); } @Test @@ -56,8 +58,8 @@ class WorkbasketControllerIntTest { HttpMethod.GET, restHelper.defaultRequest(), ParameterizedTypeReference.forType(WorkbasketSummaryListResource.class)); - assertNotNull(response.getBody().getLink(Link.REL_SELF)); - assertEquals(3, response.getBody().getContent().size()); + assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull(); + assertThat(response.getBody().getContent()).hasSize(3); } @Test @@ -69,8 +71,8 @@ class WorkbasketControllerIntTest { HttpMethod.GET, restHelper.defaultRequest(), ParameterizedTypeReference.forType(WorkbasketSummaryListResource.class)); - assertNotNull(response.getBody().getLink(Link.REL_SELF)); - assertTrue(response.getBody().getLink(Link.REL_SELF).getHref().endsWith(parameters)); + assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull(); + assertThat(response.getBody().getLink(Link.REL_SELF).getHref().endsWith(parameters)).isTrue(); } @Test @@ -83,11 +85,63 @@ class WorkbasketControllerIntTest { ParameterizedTypeReference.forType(WorkbasketSummaryListResource.class)); fail(); } catch (HttpClientErrorException e) { - assertEquals(HttpStatus.BAD_REQUEST, e.getStatusCode()); - assertTrue(e.getResponseBodyAsString().contains("[invalid]")); + assertThat(e.getStatusCode()).isEqualTo(HttpStatus.BAD_REQUEST); + assertThat(e.getResponseBodyAsString().contains("[invalid]")).isTrue(); } } + @Test + void testUpdateWorkbasketWithConcurrentModificationShouldThrowException() { + + String workbasketId = "WBI:100000000000000000000000000000000001"; + + final ObjectMapper mapper = new ObjectMapper(); + + ResponseEntity initialWorkbasketResourceRequestResponse = + template.exchange( + restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId), + HttpMethod.GET, + new HttpEntity(restHelper.getHeaders()), + ParameterizedTypeReference.forType(WorkbasketResource.class)); + + WorkbasketResource workbasketResource = initialWorkbasketResourceRequestResponse.getBody(); + + workbasketResource.setKey("GPK_KSC"); + workbasketResource.setDomain("DOMAIN_A"); + workbasketResource.setType(WorkbasketType.PERSONAL); + workbasketResource.setName("was auch immer"); + workbasketResource.setOwner("Joerg"); + workbasketResource.setModified(String.valueOf(Instant.now())); + + assertThatThrownBy( + () -> + template.exchange( + restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId), + HttpMethod.PUT, + new HttpEntity<>( + mapper.writeValueAsString(workbasketResource), restHelper.getHeaders()), + ParameterizedTypeReference.forType(WorkbasketResource.class))) + .extracting(ex -> ((HttpClientErrorException) ex).getStatusCode()) + .isEqualTo(HttpStatus.CONFLICT); + } + + @Test + void testUpdateWorkbasketOfNonExistingWorkbasketShouldThrowException() { + + String workbasketId = "WBI:100004857400039500000999999999999999"; + + assertThatThrownBy( + () -> + template.exchange( + restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId), + HttpMethod.GET, + new HttpEntity(restHelper.getHeaders()), + ParameterizedTypeReference.forType(WorkbasketResource.class))) + .isInstanceOf(HttpClientErrorException.class) + .extracting(ex -> ((HttpClientErrorException) ex).getStatusCode()) + .isEqualTo(HttpStatus.NOT_FOUND); + } + @Test void testGetSecondPageSortedByKey() { @@ -98,14 +152,14 @@ class WorkbasketControllerIntTest { HttpMethod.GET, restHelper.defaultRequest(), ParameterizedTypeReference.forType(WorkbasketSummaryListResource.class)); - assertEquals(5, response.getBody().getContent().size()); - assertEquals("USER_1_1", response.getBody().getContent().iterator().next().getKey()); - assertNotNull(response.getBody().getLink(Link.REL_SELF)); - assertTrue(response.getBody().getLink(Link.REL_SELF).getHref().endsWith(parameters)); - assertNotNull(response.getBody().getLink(Link.REL_FIRST)); - assertNotNull(response.getBody().getLink(Link.REL_LAST)); - assertNotNull(response.getBody().getLink(Link.REL_NEXT)); - assertNotNull(response.getBody().getLink(Link.REL_PREVIOUS)); + assertThat(response.getBody().getContent()).hasSize(5); + assertThat(response.getBody().getContent().iterator().next().getKey()).isEqualTo("USER_1_1"); + assertThat(response.getBody().getLink(Link.REL_SELF)).isNotNull(); + assertThat(response.getBody().getLink(Link.REL_FIRST)).isNotNull(); + assertThat(response.getBody().getLink(Link.REL_LAST)).isNotNull(); + assertThat(response.getBody().getLink(Link.REL_NEXT)).isNotNull(); + assertThat(response.getBody().getLink(Link.REL_PREVIOUS)).isNotNull(); + assertThat(response.getBody().getLink(Link.REL_SELF).getHref().endsWith(parameters)).isTrue(); } /** @@ -123,7 +177,7 @@ class WorkbasketControllerIntTest { HttpMethod.DELETE, new HttpEntity<>(restHelper.getHeadersBusinessAdmin()), Void.class); - assertEquals(HttpStatus.ACCEPTED, response.getStatusCode()); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.ACCEPTED); } @Test @@ -135,7 +189,7 @@ class WorkbasketControllerIntTest { HttpMethod.DELETE, restHelper.defaultRequest(), Void.class); - assertEquals(HttpStatus.NO_CONTENT, response.getStatusCode()); + assertThat(response.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT); ResponseEntity response2 = template.exchange( @@ -144,11 +198,11 @@ class WorkbasketControllerIntTest { HttpMethod.GET, restHelper.defaultRequest(), ParameterizedTypeReference.forType(DistributionTargetListResource.class)); - assertEquals(HttpStatus.OK, response2.getStatusCode()); + assertThat(response2.getStatusCode()).isEqualTo(HttpStatus.OK); Iterator iterator = response2.getBody().getContent().iterator(); while (iterator.hasNext()) { - assertNotEquals( - "WBI:100000000000000000000000000000000007", iterator.next().getWorkbasketId()); + assertThat(iterator.next().getWorkbasketId()) + .isNotEqualTo("WBI:100000000000000000000000000000000007"); } } }