Browse Source

Introduce optimistic locking and 'version' for entities

pull/11112/head
ViacheslavKlimov 2 years ago
parent
commit
66563e3459
  1. 17
      application/src/main/data/upgrade/3.7.0/schema_update.sql
  2. 4
      application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java
  3. 5
      application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java
  4. 37
      common/data/src/main/java/org/thingsboard/server/common/data/Device.java
  5. 2
      common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java
  6. 24
      common/data/src/main/java/org/thingsboard/server/common/data/HasVersion.java
  7. 34
      dao/src/main/java/org/thingsboard/server/dao/model/BaseVersionedSqlEntity.java
  8. 1
      dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java
  9. 7
      dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java
  10. 29
      dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java
  11. 13
      dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java
  12. 9
      dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java
  13. 1
      dao/src/main/resources/sql/schema-entities.sql
  14. 13
      dao/src/test/java/org/thingsboard/server/dao/service/DeviceServiceTest.java

17
application/src/main/data/upgrade/3.7.0/schema_update.sql

@ -0,0 +1,17 @@
--
-- 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.
--
ALTER TABLE device ADD COLUMN IF NOT EXISTS version INT DEFAULT 0;

4
application/src/main/java/org/thingsboard/server/service/sync/ie/importing/csv/AbstractBulkImportService.java

@ -33,6 +33,7 @@ import org.thingsboard.server.common.data.AttributeScope;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.HasAdditionalInfo; import org.thingsboard.server.common.data.HasAdditionalInfo;
import org.thingsboard.server.common.data.HasTenantId; import org.thingsboard.server.common.data.HasTenantId;
import org.thingsboard.server.common.data.HasVersion;
import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.StringUtils;
import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.ActionType;
@ -147,6 +148,9 @@ public abstract class AbstractBulkImportService<E extends HasId<? extends Entity
if (entity.getId() != null) { if (entity.getId() != null) {
importedEntityInfo.setOldEntity((E) entity.getClass().getConstructor(entity.getClass()).newInstance(entity)); importedEntityInfo.setOldEntity((E) entity.getClass().getConstructor(entity.getClass()).newInstance(entity));
importedEntityInfo.setUpdated(true); importedEntityInfo.setUpdated(true);
if (entity instanceof HasVersion versionedEntity) {
versionedEntity.setVersion(null); // to overwrite the entity regardless of concurrent changes
}
} else { } else {
setOwners(entity, user); setOwners(entity, user);
} }

5
application/src/test/java/org/thingsboard/server/controller/DeviceControllerTest.java

@ -192,7 +192,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
Mockito.reset(tbClusterService, auditLogService, gatewayNotificationsService); Mockito.reset(tbClusterService, auditLogService, gatewayNotificationsService);
savedDevice.setName("My new device"); savedDevice.setName("My new device");
doPost("/api/device", savedDevice, Device.class); savedDevice = doPost("/api/device", savedDevice, Device.class);
testNotifyEntityAllOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(), savedTenant.getId(), testNotifyEntityAllOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(), savedTenant.getId(),
tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED); tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED);
@ -247,7 +247,7 @@ public class DeviceControllerTest extends AbstractControllerTest {
Mockito.reset(tbClusterService, auditLogService, gatewayNotificationsService); Mockito.reset(tbClusterService, auditLogService, gatewayNotificationsService);
savedDevice.setName("My new device"); savedDevice.setName("My new device");
doPost("/api/device", savedDevice, Device.class); savedDevice = doPost("/api/device", savedDevice, Device.class);
testNotifyEntityAllOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(), savedTenant.getId(), testNotifyEntityAllOneTime(savedDevice, savedDevice.getId(), savedDevice.getId(), savedTenant.getId(),
tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED); tenantAdmin.getCustomerId(), tenantAdmin.getId(), tenantAdmin.getEmail(), ActionType.UPDATED);
@ -1592,4 +1592,5 @@ public class DeviceControllerTest extends AbstractControllerTest {
device.setType("default"); device.setType("default");
return doPost("/api/device", device, Device.class); return doPost("/api/device", device, Device.class);
} }
} }

37
common/data/src/main/java/org/thingsboard/server/common/data/Device.java

@ -22,6 +22,7 @@ import io.swagger.v3.oas.annotations.media.Schema;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.Getter; import lombok.Getter;
import lombok.Setter; import lombok.Setter;
import lombok.ToString;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.device.data.DeviceData; import org.thingsboard.server.common.data.device.data.DeviceData;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
@ -38,8 +39,9 @@ import java.util.Optional;
@Schema @Schema
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
@Slf4j @Slf4j
public class Device extends BaseDataWithAdditionalInfo<DeviceId> implements HasLabel, HasTenantId, HasCustomerId, HasOtaPackage, ExportableEntity<DeviceId> { public class Device extends BaseDataWithAdditionalInfo<DeviceId> implements HasLabel, HasTenantId, HasCustomerId, HasOtaPackage, HasVersion, ExportableEntity<DeviceId> {
private static final long serialVersionUID = 2807343040519543363L; private static final long serialVersionUID = 2807343040519543363L;
@ -65,6 +67,8 @@ public class Device extends BaseDataWithAdditionalInfo<DeviceId> implements HasL
@Getter @Setter @Getter @Setter
private DeviceId externalId; private DeviceId externalId;
@Getter @Setter
private Integer version;
public Device() { public Device() {
super(); super();
@ -86,6 +90,7 @@ public class Device extends BaseDataWithAdditionalInfo<DeviceId> implements HasL
this.firmwareId = device.getFirmwareId(); this.firmwareId = device.getFirmwareId();
this.softwareId = device.getSoftwareId(); this.softwareId = device.getSoftwareId();
this.externalId = device.getExternalId(); this.externalId = device.getExternalId();
this.version = device.getVersion();
} }
public Device updateDevice(Device device) { public Device updateDevice(Device device) {
@ -100,6 +105,7 @@ public class Device extends BaseDataWithAdditionalInfo<DeviceId> implements HasL
this.setSoftwareId(device.getSoftwareId()); this.setSoftwareId(device.getSoftwareId());
Optional.ofNullable(device.getAdditionalInfo()).ifPresent(this::setAdditionalInfo); Optional.ofNullable(device.getAdditionalInfo()).ifPresent(this::setAdditionalInfo);
this.setExternalId(device.getExternalId()); this.setExternalId(device.getExternalId());
this.setVersion(device.getVersion());
return this; return this;
} }
@ -225,33 +231,4 @@ public class Device extends BaseDataWithAdditionalInfo<DeviceId> implements HasL
return super.getAdditionalInfo(); return super.getAdditionalInfo();
} }
@Override
public String toString() {
StringBuilder builder = new StringBuilder();
builder.append("Device [tenantId=");
builder.append(tenantId);
builder.append(", customerId=");
builder.append(customerId);
builder.append(", name=");
builder.append(name);
builder.append(", type=");
builder.append(type);
builder.append(", label=");
builder.append(label);
builder.append(", deviceProfileId=");
builder.append(deviceProfileId);
builder.append(", deviceData=");
builder.append(firmwareId);
builder.append(", firmwareId=");
builder.append(deviceData);
builder.append(", additionalInfo=");
builder.append(getAdditionalInfo());
builder.append(", createdTime=");
builder.append(createdTime);
builder.append(", id=");
builder.append(id);
builder.append("]");
return builder.toString();
}
} }

2
common/data/src/main/java/org/thingsboard/server/common/data/DeviceInfo.java

@ -18,11 +18,13 @@ package org.thingsboard.server.common.data;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data; import lombok.Data;
import lombok.EqualsAndHashCode; import lombok.EqualsAndHashCode;
import lombok.ToString;
import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceId;
@Schema @Schema
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class DeviceInfo extends Device { public class DeviceInfo extends Device {
private static final long serialVersionUID = -3004579925090663691L; private static final long serialVersionUID = -3004579925090663691L;

24
common/data/src/main/java/org/thingsboard/server/common/data/HasVersion.java

@ -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;
public interface HasVersion {
Integer getVersion();
void setVersion(Integer version);
}

34
dao/src/main/java/org/thingsboard/server/dao/model/BaseVersionedSqlEntity.java

@ -0,0 +1,34 @@
/**
* 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.dao.model;
import jakarta.persistence.Column;
import jakarta.persistence.MappedSuperclass;
import jakarta.persistence.Version;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.HasVersion;
@Data
@EqualsAndHashCode(callSuper = true)
@MappedSuperclass
public abstract class BaseVersionedSqlEntity<D> extends BaseSqlEntity<D> implements HasVersion {
@Version
@Column(name = ModelConstants.VERSION_PROPERTY)
protected Integer version;
}

1
dao/src/main/java/org/thingsboard/server/dao/model/ModelConstants.java

@ -49,6 +49,7 @@ public class ModelConstants {
public static final String SEARCH_TEXT_PROPERTY = "search_text"; public static final String SEARCH_TEXT_PROPERTY = "search_text";
public static final String ADDITIONAL_INFO_PROPERTY = "additional_info"; public static final String ADDITIONAL_INFO_PROPERTY = "additional_info";
public static final String ENTITY_TYPE_PROPERTY = "entity_type"; public static final String ENTITY_TYPE_PROPERTY = "entity_type";
public static final String VERSION_PROPERTY = "version";
public static final String ENTITY_TYPE_COLUMN = ENTITY_TYPE_PROPERTY; public static final String ENTITY_TYPE_COLUMN = ENTITY_TYPE_PROPERTY;
public static final String TENANT_ID_COLUMN = "tenant_id"; public static final String TENANT_ID_COLUMN = "tenant_id";

7
dao/src/main/java/org/thingsboard/server/dao/model/sql/AbstractDeviceEntity.java

@ -32,7 +32,7 @@ import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.DeviceProfileId; import org.thingsboard.server.common.data.id.DeviceProfileId;
import org.thingsboard.server.common.data.id.OtaPackageId; import org.thingsboard.server.common.data.id.OtaPackageId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.model.BaseSqlEntity; import org.thingsboard.server.dao.model.BaseVersionedSqlEntity;
import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.util.mapping.JsonConverter; import org.thingsboard.server.dao.util.mapping.JsonConverter;
@ -41,7 +41,7 @@ import java.util.UUID;
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@MappedSuperclass @MappedSuperclass
public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEntity<T> { public abstract class AbstractDeviceEntity<T extends Device> extends BaseVersionedSqlEntity<T> {
@Column(name = ModelConstants.DEVICE_TENANT_ID_PROPERTY, columnDefinition = "uuid") @Column(name = ModelConstants.DEVICE_TENANT_ID_PROPERTY, columnDefinition = "uuid")
private UUID tenantId; private UUID tenantId;
@ -111,6 +111,7 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
if (device.getExternalId() != null) { if (device.getExternalId() != null) {
this.externalId = device.getExternalId().getId(); this.externalId = device.getExternalId().getId();
} }
this.version = device.getVersion();
} }
public AbstractDeviceEntity(DeviceEntity deviceEntity) { public AbstractDeviceEntity(DeviceEntity deviceEntity) {
@ -127,6 +128,7 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
this.firmwareId = deviceEntity.getFirmwareId(); this.firmwareId = deviceEntity.getFirmwareId();
this.softwareId = deviceEntity.getSoftwareId(); this.softwareId = deviceEntity.getSoftwareId();
this.externalId = deviceEntity.getExternalId(); this.externalId = deviceEntity.getExternalId();
this.version = deviceEntity.getVersion();
} }
protected Device toDevice() { protected Device toDevice() {
@ -155,6 +157,7 @@ public abstract class AbstractDeviceEntity<T extends Device> extends BaseSqlEnti
if (externalId != null) { if (externalId != null) {
device.setExternalId(new DeviceId(externalId)); device.setExternalId(new DeviceId(externalId));
} }
device.setVersion(version);
return device; return device;
} }

29
dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java

@ -18,11 +18,15 @@ package org.thingsboard.server.dao.sql;
import com.datastax.oss.driver.api.core.uuid.Uuids; import com.datastax.oss.driver.api.core.uuid.Uuids;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.util.concurrent.ListenableFuture; import com.google.common.util.concurrent.ListenableFuture;
import jakarta.persistence.EntityManager;
import jakarta.persistence.OptimisticLockException;
import jakarta.persistence.PersistenceContext;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.jdbc.core.JdbcTemplate; import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.common.data.HasVersion;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.Dao; import org.thingsboard.server.dao.Dao;
import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.DaoUtil;
@ -47,6 +51,9 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D>
@Autowired @Autowired
protected JdbcTemplate jdbcTemplate; protected JdbcTemplate jdbcTemplate;
@PersistenceContext
private EntityManager entityManager;
protected abstract Class<E> getEntityClass(); protected abstract Class<E> getEntityClass();
protected abstract JpaRepository<E, UUID> getRepository(); protected abstract JpaRepository<E, UUID> getRepository();
@ -68,12 +75,30 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D>
entity.setUuid(uuid); entity.setUuid(uuid);
entity.setCreatedTime(Uuids.unixTimestamp(uuid)); entity.setCreatedTime(Uuids.unixTimestamp(uuid));
} }
entity = doSave(entity, isNew); try {
entity = doSave(entity, isNew);
} catch (OptimisticLockException e) {
throw new IllegalStateException("The entity was already changed by someone else");
}
return DaoUtil.getData(entity); return DaoUtil.getData(entity);
} }
protected E doSave(E entity, boolean isNew) { protected E doSave(E entity, boolean isNew) {
return getRepository().save(entity); if (isNew) {
entityManager.persist(entity);
} else {
if (entity instanceof HasVersion versionedEntity) {
if (versionedEntity.getVersion() == null) {
HasVersion existingEntity = entityManager.find(versionedEntity.getClass(), entity.getUuid());
versionedEntity.setVersion(existingEntity.getVersion()); // manually resetting the version to latest to allow force overwrite of the entity
}
entity = entityManager.merge(entity);
entityManager.flush();
} else {
entity = entityManager.merge(entity);
}
}
return entity;
} }
@Override @Override

13
dao/src/main/java/org/thingsboard/server/dao/sql/JpaPartitionedAbstractDao.java

@ -18,24 +18,13 @@ package org.thingsboard.server.dao.sql;
import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseEntity;
import org.thingsboard.server.dao.util.SqlDao; import org.thingsboard.server.dao.util.SqlDao;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
@SqlDao @SqlDao
public abstract class JpaPartitionedAbstractDao<E extends BaseEntity<D>, D> extends JpaAbstractDao<E, D> { public abstract class JpaPartitionedAbstractDao<E extends BaseEntity<D>, D> extends JpaAbstractDao<E, D> {
@PersistenceContext
private EntityManager entityManager;
@Override @Override
protected E doSave(E entity, boolean isNew) { protected E doSave(E entity, boolean isNew) {
createPartition(entity); createPartition(entity);
if (isNew) { return super.doSave(entity, isNew);
entityManager.persist(entity);
} else {
entity = entityManager.merge(entity);
}
return entity;
} }
public abstract void createPartition(E entity); public abstract void createPartition(E entity);

9
dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java

@ -22,7 +22,6 @@ import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable; import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.Device;
import org.thingsboard.server.common.data.DeviceIdInfo; import org.thingsboard.server.common.data.DeviceIdInfo;
import org.thingsboard.server.common.data.DeviceInfo; import org.thingsboard.server.common.data.DeviceInfo;
@ -81,14 +80,6 @@ public class JpaDeviceDao extends JpaAbstractDao<DeviceEntity, Device> implement
return DaoUtil.getData(deviceRepository.findDeviceInfoById(deviceId)); return DaoUtil.getData(deviceRepository.findDeviceInfoById(deviceId));
} }
@Override
@Transactional
public Device saveAndFlush(TenantId tenantId, Device device) {
Device result = this.save(tenantId, device);
deviceRepository.flush();
return result;
}
@Override @Override
public PageData<Device> findDevicesByTenantId(UUID tenantId, PageLink pageLink) { public PageData<Device> findDevicesByTenantId(UUID tenantId, PageLink pageLink) {
if (StringUtils.isEmpty(pageLink.getTextSearch())) { if (StringUtils.isEmpty(pageLink.getTextSearch())) {

1
dao/src/main/resources/sql/schema-entities.sql

@ -340,6 +340,7 @@ CREATE TABLE IF NOT EXISTS device (
firmware_id uuid, firmware_id uuid,
software_id uuid, software_id uuid,
external_id uuid, external_id uuid,
version INT DEFAULT 0,
CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name), CONSTRAINT device_name_unq_key UNIQUE (tenant_id, name),
CONSTRAINT device_external_id_unq_key UNIQUE (tenant_id, external_id), CONSTRAINT device_external_id_unq_key UNIQUE (tenant_id, external_id),
CONSTRAINT fk_device_profile FOREIGN KEY (device_profile_id) REFERENCES device_profile(id), CONSTRAINT fk_device_profile FOREIGN KEY (device_profile_id) REFERENCES device_profile(id),

13
dao/src/test/java/org/thingsboard/server/dao/service/DeviceServiceTest.java

@ -368,7 +368,7 @@ public class DeviceServiceTest extends AbstractServiceTest {
Device device = new Device(); Device device = new Device();
device.setType(deviceProfile.getName()); device.setType(deviceProfile.getName());
device.setTenantId(tenantId); device.setTenantId(tenantId);
device.setName("My device"+ StringUtils.randomAlphabetic(5)); device.setName("My device" + StringUtils.randomAlphabetic(5));
DefaultTransactionDefinition def = new DefaultTransactionDefinition(); DefaultTransactionDefinition def = new DefaultTransactionDefinition();
TransactionStatus status = platformTransactionManager.getTransaction(def); TransactionStatus status = platformTransactionManager.getTransaction(def);
@ -945,8 +945,8 @@ public class DeviceServiceTest extends AbstractServiceTest {
deviceInfosWithLabel.stream() deviceInfosWithLabel.stream()
.anyMatch( .anyMatch(
d -> d.getId().equals(savedDevice.getId()) d -> d.getId().equals(savedDevice.getId())
&& d.getTenantId().equals(tenantId) && d.getTenantId().equals(tenantId)
&& d.getLabel().equals(savedDevice.getLabel()) && d.getLabel().equals(savedDevice.getLabel())
) )
); );
@ -1004,9 +1004,9 @@ public class DeviceServiceTest extends AbstractServiceTest {
deviceInfosWithLabel.stream() deviceInfosWithLabel.stream()
.anyMatch( .anyMatch(
d -> d.getId().equals(savedDevice.getId()) d -> d.getId().equals(savedDevice.getId())
&& d.getTenantId().equals(tenantId) && d.getTenantId().equals(tenantId)
&& d.getDeviceProfileName().equals(savedDevice.getType()) && d.getDeviceProfileName().equals(savedDevice.getType())
&& d.getLabel().equals(savedDevice.getLabel()) && d.getLabel().equals(savedDevice.getLabel())
) )
); );
@ -1072,4 +1072,5 @@ public class DeviceServiceTest extends AbstractServiceTest {
) )
); );
} }
} }

Loading…
Cancel
Save