HTTP status 409 (Conflict) on EntityVersionMismatchException

This commit is contained in:
ViacheslavKlimov 2024-07-01 14:11:57 +03:00
parent 4b7b69313f
commit 8a3f99d651
6 changed files with 47 additions and 1 deletions

View File

@ -64,6 +64,7 @@ import org.thingsboard.server.common.data.asset.AssetProfile;
import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeInfo;
import org.thingsboard.server.common.data.exception.EntityVersionMismatchException;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
import org.thingsboard.server.common.data.exception.ThingsboardException;
import org.thingsboard.server.common.data.id.AlarmCommentId;
@ -381,6 +382,8 @@ public abstract class BaseController {
log.warn("Database error: {} - {}", errorType, ExceptionUtils.getRootCauseMessage(exception));
}
return new ThingsboardException("Database error", ThingsboardErrorCode.GENERAL);
} else if (exception instanceof EntityVersionMismatchException) {
return new ThingsboardException(exception.getMessage(), exception, ThingsboardErrorCode.CONFLICT);
}
return new ThingsboardException(exception.getMessage(), exception, ThingsboardErrorCode.GENERAL);
}

View File

@ -91,6 +91,7 @@ public class ThingsboardErrorResponseHandler extends ResponseEntityExceptionHand
errorCodeToStatusMap.put(ThingsboardErrorCode.TOO_MANY_REQUESTS, HttpStatus.TOO_MANY_REQUESTS);
errorCodeToStatusMap.put(ThingsboardErrorCode.TOO_MANY_UPDATES, HttpStatus.TOO_MANY_REQUESTS);
errorCodeToStatusMap.put(ThingsboardErrorCode.SUBSCRIPTION_VIOLATION, HttpStatus.FORBIDDEN);
errorCodeToStatusMap.put(ThingsboardErrorCode.CONFLICT, HttpStatus.CONFLICT);
}
private static ThingsboardErrorCode statusToErrorCode(HttpStatus status) {

View File

@ -1585,6 +1585,22 @@ public class DeviceControllerTest extends AbstractControllerTest {
Assert.assertEquals(newAttributeValue, actualAttribute.get("value"));
}
@Test
public void testSaveDeviceWithOutdatedVersion() throws Exception {
Device device = createDevice("Device v1");
assertThat(device.getVersion()).isOne();
device.setName("Device v2");
device = doPost("/api/device", device, Device.class);
assertThat(device.getVersion()).isEqualTo(2);
device.setVersion(1);
String response = doPost("/api/device", device).andExpect(status().isConflict())
.andReturn().getResponse().getContentAsString();
assertThat(JacksonUtil.toJsonNode(response).get("message").asText())
.containsIgnoringCase("already changed by someone else");
}
private Device createDevice(String name) {
Device device = new Device();
device.setName(name);

View File

@ -0,0 +1,24 @@
/**
* Copyright © 2016-2024 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.common.data.exception;
public class EntityVersionMismatchException extends RuntimeException {
public EntityVersionMismatchException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@ -29,6 +29,7 @@ public enum ThingsboardErrorCode {
ITEM_NOT_FOUND(32),
TOO_MANY_REQUESTS(33),
TOO_MANY_UPDATES(34),
CONFLICT(35),
SUBSCRIPTION_VIOLATION(40),
PASSWORD_VIOLATION(45);

View File

@ -27,6 +27,7 @@ import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.common.data.HasVersion;
import org.thingsboard.server.common.data.exception.EntityVersionMismatchException;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.DaoUtil;
@ -78,7 +79,7 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D>
try {
entity = doSave(entity, isNew);
} catch (OptimisticLockException e) {
throw new IllegalStateException("The entity was already changed by someone else");
throw new EntityVersionMismatchException("The entity was already changed by someone else", e);
}
return DaoUtil.getData(entity);
}