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, getStatusCode
addNote, getAdditionalNotes, getHttpResponse, getMessage, getProjectKey, getSphereRequest, httpSummary, setHttpRequest, setProjectKey, setSphereRequest, setUnderlyingHttpResponse
addSuppressed, fillInStackTrace, getCause, getLocalizedMessage, getStackTrace, getSuppressed, initCause, printStackTrace, printStackTrace, printStackTrace, setStackTrace, toString
clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait
getMessage, getStatusCode, hasErrorCode, of, typeReference
public 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.