public class ConcurrentModificationException extends ClientErrorException implements ErrorResponse
This error occurs if you try to update or delete a resource using an outdated version (Versioned.getVersion()).
Do not confuse it with java.util.ConcurrentModificationException, especially in imports.
Example how this could happen:
//Given we have a product withTaxedProduct(client(), product -> { //And given we have an empty cart withCart(client(), cart -> { //when a customer clicks enter to cart final int variantId = 1; final int quantity = 2; final CartUpdateCommand cartUpdateCommand = CartUpdateCommand.of(cart, AddLineItem.of(product, variantId, quantity)); final Cart successfulUpdatedCart = client().executeBlocking(cartUpdateCommand); assertThat(successfulUpdatedCart.getVersion()).isGreaterThan(cart.getVersion()); //and by accident again final Throwable throwable = catchThrowable(() -> client().executeBlocking(cartUpdateCommand)); assertThat(throwable).isInstanceOf(ConcurrentModificationException.class); return successfulUpdatedCart; }); });See the test code.
In case the update or deletion should executed in the same shape anyway you could get the current version and try to execute again:
Current version from exception:
withTaxedProduct(client(), product -> { withCart(client(), cart -> { //when a customer clicks enter to cart final int variantId = 1; final int quantity = 2; final CartUpdateCommand cartUpdateCommand = CartUpdateCommand.of(cart, AddLineItem.of(product, variantId, quantity)); client().executeBlocking(cartUpdateCommand);//successful attempt in another thread/machine/container/tab //the operation will increase the version number of the cart //warning: ignoring version conflicts can be very poor behaviour on some use cases //we show this here if you want to execute the command anyway Cart updated2; try { updated2 = client().executeBlocking(cartUpdateCommand); } catch (final ConcurrentModificationException e) { final CartUpdateCommand commandWithCurrentCartVersion = cartUpdateCommand.withVersion(e.getCurrentVersion()); updated2 = client().executeBlocking(commandWithCurrentCartVersion); } return updated2; }); });See the test code.
Current version by executing a get request:
withTaxedProduct(client(), product -> { withCart(client(), cart -> { //when a customer clicks enter to cart final int variantId = 1; final int quantity = 2; final CartUpdateCommand cartUpdateCommand = CartUpdateCommand.of(cart, AddLineItem.of(product, variantId, quantity)); client().executeBlocking(cartUpdateCommand);//successful attempt in another thread/machine/container/tab //the operation will increase the version number of the cart //warning: ignoring version conflicts can be very poor behaviour on some use cases //we show this here if you want to execute the command anyway Cart updated2; try { updated2 = client().executeBlocking(cartUpdateCommand); } catch (final ConcurrentModificationException e) { final Cart cartWithCurrentVersion = client().executeBlocking(CartByIdGet.of(cart)); final CartUpdateCommand commandWithCurrentCartVersion = cartUpdateCommand.withVersion(cartWithCurrentVersion); updated2 = client().executeBlocking(commandWithCurrentCartVersion); } return updated2; }); });See the test code.
httpResponse| Constructor and Description |
|---|
ConcurrentModificationException() |
ConcurrentModificationException(ErrorResponse errorResponse) |
| Modifier and Type | Method and Description |
|---|---|
Long |
getCurrentVersion()
Gets the version of the object at the time of the failed command.
|
List<? extends SphereError> |
getErrors() |
getJsonBody, getStatusCodeaddNote, getAdditionalNotes, getHttpResponse, getMessage, getProjectKey, getSphereRequest, httpSummary, setHttpRequest, setProjectKey, setSphereRequest, setUnderlyingHttpResponseaddSuppressed, fillInStackTrace, getCause, getLocalizedMessage, getStackTrace, getSuppressed, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toStringclone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, waitgetMessage, getStatusCode, hasErrorCode, of, typeReferencepublic ConcurrentModificationException()
public ConcurrentModificationException(ErrorResponse errorResponse)
public List<? extends SphereError> getErrors()
getErrors in interface ErrorResponse@Nullable public Long getCurrentVersion()
withCategory(client(), cat -> { final CategoryUpdateCommand cmd = CategoryUpdateCommand.of(cat, ChangeName.of(LocalizedString.ofEnglish("new"))); final Category successfulUpdatedCategory = client().executeBlocking(cmd); final Throwable throwable = catchThrowable(() -> client().executeBlocking(cmd));//same command twice assertThat(throwable).isInstanceOf(ConcurrentModificationException.class); final ConcurrentModificationException exception = (ConcurrentModificationException) throwable; assertThat(exception.getCurrentVersion()) .isGreaterThanOrEqualTo(successfulUpdatedCategory.getVersion()); });See the test code.