TSK-1088 optimistic locking on workbasket update

- Added optimistic locking for workbasket update
- Adjusted WorkbasketDefinitionController
- Added tests in UpdateWorkbasketAccTest
- Added tests in WorkbasketControllerIntTest
- Changed ConcurrencyException HTTP-Status Code to CONFLICT (409)
This commit is contained in:
Jörg Heffner 2020-02-05 16:27:24 +01:00
parent 91f17fb221
commit dcc72d1781
8 changed files with 229 additions and 51 deletions

View File

@ -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.

View File

@ -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");

View File

@ -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);
}
}

View File

@ -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);

View File

@ -99,7 +99,7 @@ public class TaskanaRestExceptionHandler extends ResponseEntityExceptionHandler
@ExceptionHandler(ConcurrencyException.class)
protected ResponseEntity<Object> handleConcurrencyException(
ConcurrencyException ex, WebRequest req) {
return buildResponse(ex, req, HttpStatus.LOCKED);
return buildResponse(ex, req, HttpStatus.CONFLICT);
}
@ExceptionHandler(WorkbasketInUseException.class)

View File

@ -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<WorkbasketResource> 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<WorkbasketResource> result;
if (workbasketId.equals(workbasketResource.workbasketId)) {

View File

@ -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<Void> 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();

View File

@ -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<WorkbasketResource> initialWorkbasketResourceRequestResponse =
template.exchange(
restHelper.toUrl(Mapping.URL_WORKBASKET_ID, workbasketId),
HttpMethod.GET,
new HttpEntity<String>(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<String>(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<DistributionTargetListResource> 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<DistributionTargetResource> iterator = response2.getBody().getContent().iterator();
while (iterator.hasNext()) {
assertNotEquals(
"WBI:100000000000000000000000000000000007", iterator.next().getWorkbasketId());
assertThat(iterator.next().getWorkbasketId())
.isNotEqualTo("WBI:100000000000000000000000000000000007");
}
}
}