Browse Source

Add syncManager for EntityStateListener because of actor creation problem

pull/9083/head
Andrii Landiak 3 years ago
parent
commit
987bcf476c
  1. 8
      application/src/main/java/org/thingsboard/server/controller/DashboardController.java
  2. 3
      application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java
  3. 47
      application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java
  4. 49
      application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java
  5. 14
      application/src/main/java/org/thingsboard/server/service/entitiy/tenant/DefaultTbTenantService.java
  6. 1
      application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java
  7. 2
      application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java
  8. 24
      application/src/main/java/org/thingsboard/server/service/rule/DefaultTbRuleChainService.java
  9. 3
      application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java
  10. 23
      common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityStateSyncManager.java
  11. 10
      dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java
  12. 10
      dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
  13. 12
      dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java
  14. 10
      dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java
  15. 34
      dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityStateSyncManager.java
  16. 10
      dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java
  17. 1
      dao/src/main/java/org/thingsboard/server/dao/eventsourcing/DeleteEntityEvent.java
  18. 48
      dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java

8
application/src/main/java/org/thingsboard/server/controller/DashboardController.java

@ -527,7 +527,7 @@ public class DashboardController extends BaseController {
} }
Tenant tenant = tenantService.findTenantById(getTenantId()); Tenant tenant = tenantService.findTenantById(getTenantId());
JsonNode additionalInfo = tenant.getAdditionalInfo(); JsonNode additionalInfo = tenant.getAdditionalInfo();
if (additionalInfo == null || !(additionalInfo instanceof ObjectNode)) { if (!(additionalInfo instanceof ObjectNode)) {
additionalInfo = JacksonUtil.newObjectNode(); additionalInfo = JacksonUtil.newObjectNode();
} }
if (homeDashboardInfo.getDashboardId() != null) { if (homeDashboardInfo.getDashboardId() != null) {
@ -553,8 +553,7 @@ public class DashboardController extends BaseController {
} }
return new HomeDashboardInfo(dashboardId, hideDashboardToolbar); return new HomeDashboardInfo(dashboardId, hideDashboardToolbar);
} }
} catch (Exception e) { } catch (Exception ignored) {}
}
return null; return null;
} }
@ -570,8 +569,7 @@ public class DashboardController extends BaseController {
} }
return new HomeDashboard(dashboard, hideDashboardToolbar); return new HomeDashboard(dashboard, hideDashboardToolbar);
} }
} catch (Exception e) { } catch (Exception ignored) {}
}
return null; return null;
} }

3
application/src/main/java/org/thingsboard/server/service/edge/DefaultEdgeNotificationService.java

@ -239,7 +239,4 @@ public class DefaultEdgeNotificationService implements EdgeNotificationService {
log.error("[{}] Can't push to edge updates, edgeNotificationMsg [{}]", tenantId, edgeNotificationMsg, throwable); log.error("[{}] Can't push to edge updates, edgeNotificationMsg [{}]", tenantId, edgeNotificationMsg, throwable);
callback.onFailure(throwable); callback.onFailure(throwable);
} }
} }

47
application/src/main/java/org/thingsboard/server/service/edge/EdgeEventSourcingListener.java

@ -21,16 +21,12 @@ import org.springframework.stereotype.Component;
import org.springframework.transaction.event.TransactionalEventListener; import org.springframework.transaction.event.TransactionalEventListener;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cluster.TbClusterService; import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.ApiUsageState;
import org.thingsboard.server.common.data.EdgeUtils; import org.thingsboard.server.common.data.EdgeUtils;
import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.OtaPackageInfo; import org.thingsboard.server.common.data.OtaPackageInfo;
import org.thingsboard.server.common.data.TbResource;
import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.User;
import org.thingsboard.server.common.data.alarm.AlarmApiCallResult; import org.thingsboard.server.common.data.alarm.AlarmApiCallResult;
import org.thingsboard.server.common.data.audit.ActionType; import org.thingsboard.server.common.data.audit.ActionType;
import org.thingsboard.server.common.data.edge.Edge;
import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.edge.EdgeEventActionType; import org.thingsboard.server.common.data.edge.EdgeEventActionType;
import org.thingsboard.server.common.data.edge.EdgeEventType; import org.thingsboard.server.common.data.edge.EdgeEventType;
import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelation;
@ -79,7 +75,7 @@ public class EdgeEventSourcingListener {
return; return;
} }
try { try {
if (!isValidEdgeEventEntity(event.getEntity())) { if (!isValidEdgeEventEntity(event)) {
return; return;
} }
log.trace("[{}] SaveEntityEvent called: {}", event.getTenantId(), event); log.trace("[{}] SaveEntityEvent called: {}", event.getTenantId(), event);
@ -150,24 +146,29 @@ public class EdgeEventSourcingListener {
} }
} }
private boolean isValidEdgeEventEntity(Object entity) { private boolean isValidEdgeEventEntity(SaveEntityEvent<?> event) {
if (entity instanceof OtaPackageInfo) { switch (event.getEntityId().getEntityType()) {
OtaPackageInfo otaPackageInfo = (OtaPackageInfo) entity; case RULE_CHAIN:
return otaPackageInfo.hasUrl() || otaPackageInfo.isHasData(); RuleChain ruleChain = (RuleChain) event.getEntity();
} else if (entity instanceof RuleChain) { return RuleChainType.EDGE.equals(ruleChain.getType());
RuleChain ruleChain = (RuleChain) entity; case USER:
return RuleChainType.EDGE.equals(ruleChain.getType()); User user = (User) event.getEntity();
} else if (entity instanceof User) { return !Authority.SYS_ADMIN.equals(user.getAuthority());
User user = (User) entity; case OTA_PACKAGE:
return !Authority.SYS_ADMIN.equals(user.getAuthority()); OtaPackageInfo otaPackageInfo = (OtaPackageInfo) event.getEntity();
} else if (entity instanceof AlarmApiCallResult) { return otaPackageInfo.hasUrl() || otaPackageInfo.isHasData();
AlarmApiCallResult alarmApiCallResult = (AlarmApiCallResult) entity; case ALARM:
return alarmApiCallResult.isModified(); if (event.getEntity() instanceof AlarmApiCallResult) {
} else if (entity instanceof Edge || AlarmApiCallResult alarmApiCallResult = (AlarmApiCallResult) event.getEntity();
entity instanceof ApiUsageState || return alarmApiCallResult.isModified();
entity instanceof TbResource || }
entity instanceof EdgeEvent) { break;
return false; case TENANT:
return !event.getAdded();
case API_USAGE_STATE:
case TB_RESOURCE:
case EDGE:
return false;
} }
// Default: If the entity doesn't match any of the conditions, consider it as valid. // Default: If the entity doesn't match any of the conditions, consider it as valid.
return true; return true;

49
application/src/main/java/org/thingsboard/server/service/entitiy/EntityStateSourcingListener.java

@ -15,6 +15,7 @@
*/ */
package org.thingsboard.server.service.entitiy; package org.thingsboard.server.service.entitiy;
import com.fasterxml.jackson.core.type.TypeReference;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -35,19 +36,25 @@ import org.thingsboard.server.common.data.edge.EdgeEvent;
import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.DeviceId;
import org.thingsboard.server.common.data.id.EdgeId; import org.thingsboard.server.common.data.id.EdgeId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.msg.TbMsgType; import org.thingsboard.server.common.data.msg.TbMsgType;
import org.thingsboard.server.common.data.notification.NotificationRequest; import org.thingsboard.server.common.data.notification.NotificationRequest;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent; import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
import org.thingsboard.server.common.data.rule.RuleChain;
import org.thingsboard.server.common.data.rule.RuleChainType;
import org.thingsboard.server.common.data.security.DeviceCredentials; import org.thingsboard.server.common.data.security.DeviceCredentials;
import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.TbMsg;
import org.thingsboard.server.common.msg.TbMsgDataType; import org.thingsboard.server.common.msg.TbMsgDataType;
import org.thingsboard.server.common.msg.TbMsgMetaData; import org.thingsboard.server.common.msg.TbMsgMetaData;
import org.thingsboard.server.dao.entity.EntityStateSyncManager;
import org.thingsboard.server.dao.eventsourcing.ActionEntityEvent; import org.thingsboard.server.dao.eventsourcing.ActionEntityEvent;
import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent; import org.thingsboard.server.dao.eventsourcing.DeleteEntityEvent;
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent; import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
import org.thingsboard.server.dao.tenant.TenantService;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.util.Set;
@Component @Component
@RequiredArgsConstructor @RequiredArgsConstructor
@ -55,6 +62,8 @@ import javax.annotation.PostConstruct;
public class EntityStateSourcingListener { public class EntityStateSourcingListener {
private final TbClusterService tbClusterService; private final TbClusterService tbClusterService;
private final TenantService tenantService;
private final EntityStateSyncManager entityStateSyncManager;
@PostConstruct @PostConstruct
public void init() { public void init() {
@ -63,6 +72,9 @@ public class EntityStateSourcingListener {
@TransactionalEventListener(fallbackExecution = true) @TransactionalEventListener(fallbackExecution = true)
public void handleEvent(SaveEntityEvent<?> event) { public void handleEvent(SaveEntityEvent<?> event) {
if (entityStateSyncManager.isSync()) {
return;
}
log.trace("[{}] SaveEntityEvent called: {}", event.getTenantId(), event); log.trace("[{}] SaveEntityEvent called: {}", event.getTenantId(), event);
TenantId tenantId = event.getTenantId(); TenantId tenantId = event.getTenantId();
EntityId entityId = event.getEntityId(); EntityId entityId = event.getEntityId();
@ -77,6 +89,12 @@ public class EntityStateSourcingListener {
case NOTIFICATION_RULE: case NOTIFICATION_RULE:
tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityId, lifecycleEvent); tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityId, lifecycleEvent);
break; break;
case RULE_CHAIN:
RuleChain ruleChain = (RuleChain) event.getEntity();
if (RuleChainType.CORE.equals(ruleChain.getType())) {
tbClusterService.broadcastEntityStateChangeEvent(ruleChain.getTenantId(), ruleChain.getId(), lifecycleEvent);
}
break;
case TENANT: case TENANT:
Tenant tenant = (Tenant) event.getEntity(); Tenant tenant = (Tenant) event.getEntity();
onTenantUpdate(tenant, lifecycleEvent); onTenantUpdate(tenant, lifecycleEvent);
@ -124,6 +142,17 @@ public class EntityStateSourcingListener {
case NOTIFICATION_RULE: case NOTIFICATION_RULE:
tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityId, ComponentLifecycleEvent.DELETED); tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityId, ComponentLifecycleEvent.DELETED);
break; break;
case RULE_CHAIN:
RuleChain ruleChain = (RuleChain) event.getEntity();
Set<RuleChainId> referencingRuleChainIds = JacksonUtil.fromString(event.getBody(), new TypeReference<>() {});
if (RuleChainType.CORE.equals(ruleChain.getType())) {
if (referencingRuleChainIds != null) {
referencingRuleChainIds.forEach(referencingRuleChainId ->
tbClusterService.broadcastEntityStateChangeEvent(tenantId, referencingRuleChainId, ComponentLifecycleEvent.UPDATED));
}
tbClusterService.broadcastEntityStateChangeEvent(tenantId, ruleChain.getId(), ComponentLifecycleEvent.DELETED);
}
break;
case TENANT: case TENANT:
Tenant tenant = (Tenant) event.getEntity(); Tenant tenant = (Tenant) event.getEntity();
onTenantDeleted(tenant); onTenantDeleted(tenant);
@ -154,11 +183,6 @@ public class EntityStateSourcingListener {
} }
} }
private void onDeviceProfileDelete(TenantId tenantId, EntityId entityId, DeviceProfile deviceProfile) {
tbClusterService.onDeviceProfileDelete(deviceProfile, null);
tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityId, ComponentLifecycleEvent.DELETED);
}
@TransactionalEventListener(fallbackExecution = true) @TransactionalEventListener(fallbackExecution = true)
public void handleEvent(ActionEntityEvent<?> event) { public void handleEvent(ActionEntityEvent<?> event) {
log.trace("[{}] ActionEntityEvent called: {}", event.getTenantId(), event); log.trace("[{}] ActionEntityEvent called: {}", event.getTenantId(), event);
@ -178,6 +202,11 @@ public class EntityStateSourcingListener {
tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), lifecycleEvent); tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), lifecycleEvent);
} }
private void onTenantDeleted(Tenant tenant) {
tbClusterService.onTenantDelete(tenant, null);
tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), ComponentLifecycleEvent.DELETED);
}
private void onTenantProfileUpdate(TenantProfile tenantProfile, ComponentLifecycleEvent lifecycleEvent) { private void onTenantProfileUpdate(TenantProfile tenantProfile, ComponentLifecycleEvent lifecycleEvent) {
tbClusterService.onTenantProfileChange(tenantProfile, null); tbClusterService.onTenantProfileChange(tenantProfile, null);
tbClusterService.broadcastEntityStateChangeEvent(TenantId.SYS_TENANT_ID, tenantProfile.getId(), lifecycleEvent); tbClusterService.broadcastEntityStateChangeEvent(TenantId.SYS_TENANT_ID, tenantProfile.getId(), lifecycleEvent);
@ -198,6 +227,11 @@ public class EntityStateSourcingListener {
return null; return null;
} }
private void onDeviceProfileDelete(TenantId tenantId, EntityId entityId, DeviceProfile deviceProfile) {
tbClusterService.onDeviceProfileDelete(deviceProfile, null);
tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityId, ComponentLifecycleEvent.DELETED);
}
private void onDeviceUpdate(Object entity, Object oldEntity) { private void onDeviceUpdate(Object entity, Object oldEntity) {
Device device = (Device) entity; Device device = (Device) entity;
Device oldDevice = null; Device oldDevice = null;
@ -207,11 +241,6 @@ public class EntityStateSourcingListener {
tbClusterService.onDeviceUpdated(device, oldDevice); tbClusterService.onDeviceUpdated(device, oldDevice);
} }
private void onTenantDeleted(Tenant tenant) {
tbClusterService.onTenantDelete(tenant, null);
tbClusterService.broadcastEntityStateChangeEvent(tenant.getId(), tenant.getId(), ComponentLifecycleEvent.DELETED);
}
private void handleEdgeEvent(TenantId tenantId, EntityId entityId, Object entity, ComponentLifecycleEvent lifecycleEvent) { private void handleEdgeEvent(TenantId tenantId, EntityId entityId, Object entity, ComponentLifecycleEvent lifecycleEvent) {
if (entity instanceof Edge) { if (entity instanceof Edge) {
tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityId, lifecycleEvent); tbClusterService.broadcastEntityStateChangeEvent(tenantId, entityId, lifecycleEvent);

14
application/src/main/java/org/thingsboard/server/service/entitiy/tenant/DefaultTbTenantService.java

@ -16,10 +16,13 @@
package org.thingsboard.server.service.entitiy.tenant; package org.thingsboard.server.service.entitiy.tenant;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.Tenant;
import org.thingsboard.server.common.data.TenantProfile; import org.thingsboard.server.common.data.TenantProfile;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.entity.EntityStateSyncManager;
import org.thingsboard.server.dao.eventsourcing.SaveEntityEvent;
import org.thingsboard.server.dao.tenant.TbTenantProfileCache; import org.thingsboard.server.dao.tenant.TbTenantProfileCache;
import org.thingsboard.server.dao.tenant.TenantProfileService; import org.thingsboard.server.dao.tenant.TenantProfileService;
import org.thingsboard.server.dao.tenant.TenantService; import org.thingsboard.server.dao.tenant.TenantService;
@ -43,12 +46,18 @@ public class DefaultTbTenantService extends AbstractTbEntityService implements T
private final TbQueueService tbQueueService; private final TbQueueService tbQueueService;
private final TenantProfileService tenantProfileService; private final TenantProfileService tenantProfileService;
private final EntitiesVersionControlService versionControlService; private final EntitiesVersionControlService versionControlService;
private final ApplicationEventPublisher eventPublisher;
private final EntityStateSyncManager entityStateSyncManager;
@Override @Override
public Tenant save(Tenant tenant) throws Exception { public Tenant save(Tenant tenant) throws Exception {
boolean created = tenant.getId() == null; boolean created = tenant.getId() == null;
Tenant oldTenant = !created ? tenantService.findTenantById(tenant.getId()) : null; Tenant oldTenant = !created ? tenantService.findTenantById(tenant.getId()) : null;
if (created) {
entityStateSyncManager.getSync().set(true);
}
Tenant savedTenant = checkNotNull(tenantService.saveTenant(tenant)); Tenant savedTenant = checkNotNull(tenantService.saveTenant(tenant));
if (created) { if (created) {
installScripts.createDefaultRuleChains(savedTenant.getId()); installScripts.createDefaultRuleChains(savedTenant.getId());
@ -56,6 +65,11 @@ public class DefaultTbTenantService extends AbstractTbEntityService implements T
} }
tenantProfileCache.evict(savedTenant.getId()); tenantProfileCache.evict(savedTenant.getId());
if (created) {
entityStateSyncManager.getSync().remove();
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(TenantId.SYS_TENANT_ID).entityId(savedTenant.getId()).entity(savedTenant).added(true).build());
}
TenantProfile oldTenantProfile = oldTenant != null ? tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, oldTenant.getTenantProfileId()) : null; TenantProfile oldTenantProfile = oldTenant != null ? tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, oldTenant.getTenantProfileId()) : null;
TenantProfile newTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenant.getTenantProfileId()); TenantProfile newTenantProfile = tenantProfileService.findTenantProfileById(TenantId.SYS_TENANT_ID, savedTenant.getTenantProfileId());
tbQueueService.updateQueuesByTenants(Collections.singletonList(savedTenant.getTenantId()), newTenantProfile, oldTenantProfile); tbQueueService.updateQueuesByTenants(Collections.singletonList(savedTenant.getTenantId()), newTenantProfile, oldTenantProfile);

1
application/src/main/java/org/thingsboard/server/service/entitiy/user/TbUserService.java

@ -23,6 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
public interface TbUserService { public interface TbUserService {
User save(TenantId tenantId, CustomerId customerId, User tbUser, boolean sendActivationMail, HttpServletRequest request, User user) throws ThingsboardException; User save(TenantId tenantId, CustomerId customerId, User tbUser, boolean sendActivationMail, HttpServletRequest request, User user) throws ThingsboardException;
void delete(TenantId tenantId, CustomerId customerId, User user, User responsibleUser) throws ThingsboardException; void delete(TenantId tenantId, CustomerId customerId, User user, User responsibleUser) throws ThingsboardException;

2
application/src/main/java/org/thingsboard/server/service/install/InstallScripts.java

@ -171,7 +171,7 @@ public class InstallScripts {
return createRuleChainFromFile(tenantId, getDeviceProfileDefaultRuleChainTemplateFilePath(), ruleChainName); return createRuleChainFromFile(tenantId, getDeviceProfileDefaultRuleChainTemplateFilePath(), ruleChainName);
} }
public RuleChain createRuleChainFromFile(TenantId tenantId, Path templateFilePath, String newRuleChainName) throws IOException { public RuleChain createRuleChainFromFile(TenantId tenantId, Path templateFilePath, String newRuleChainName) {
JsonNode ruleChainJson = JacksonUtil.toJsonNode(templateFilePath.toFile()); JsonNode ruleChainJson = JacksonUtil.toJsonNode(templateFilePath.toFile());
RuleChain ruleChain = JacksonUtil.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class); RuleChain ruleChain = JacksonUtil.treeToValue(ruleChainJson.get("ruleChain"), RuleChain.class);
RuleChainMetaData ruleChainMetaData = JacksonUtil.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class); RuleChainMetaData ruleChainMetaData = JacksonUtil.treeToValue(ruleChainJson.get("metadata"), RuleChainMetaData.class);

24
application/src/main/java/org/thingsboard/server/service/rule/DefaultTbRuleChainService.java

@ -179,10 +179,6 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
try { try {
RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain)); RuleChain savedRuleChain = checkNotNull(ruleChainService.saveRuleChain(ruleChain));
autoCommit(user, savedRuleChain.getId()); autoCommit(user, savedRuleChain.getId());
if (RuleChainType.CORE.equals(savedRuleChain.getType())) {
tbClusterService.broadcastEntityStateChangeEvent(tenantId, savedRuleChain.getId(),
actionType.equals(ActionType.ADDED) ? ComponentLifecycleEvent.CREATED : ComponentLifecycleEvent.UPDATED);
}
logEntityActionService.logEntityAction(tenantId, savedRuleChain.getId(), savedRuleChain, null, actionType, user); logEntityActionService.logEntityAction(tenantId, savedRuleChain.getId(), savedRuleChain, null, actionType, user);
return savedRuleChain; return savedRuleChain;
} catch (Exception e) { } catch (Exception e) {
@ -204,13 +200,6 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
referencingRuleChainIds.remove(ruleChain.getId()); referencingRuleChainIds.remove(ruleChain.getId());
if (RuleChainType.CORE.equals(ruleChain.getType())) {
referencingRuleChainIds.forEach(referencingRuleChainId ->
tbClusterService.broadcastEntityStateChangeEvent(tenantId, referencingRuleChainId, ComponentLifecycleEvent.UPDATED));
tbClusterService.broadcastEntityStateChangeEvent(tenantId, ruleChain.getId(), ComponentLifecycleEvent.DELETED);
}
logEntityActionService.logEntityAction(tenantId, ruleChainId, ruleChain, null, ActionType.DELETED, user, ruleChainId.toString()); logEntityActionService.logEntityAction(tenantId, ruleChainId, ruleChain, null, ActionType.DELETED, user, ruleChainId.toString());
} catch (Exception e) { } catch (Exception e) {
logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.RULE_CHAIN), ActionType.DELETED, logEntityActionService.logEntityAction(tenantId, emptyId(EntityType.RULE_CHAIN), ActionType.DELETED,
@ -224,7 +213,6 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
try { try {
RuleChain savedRuleChain = installScripts.createDefaultRuleChain(tenantId, request.getName()); RuleChain savedRuleChain = installScripts.createDefaultRuleChain(tenantId, request.getName());
autoCommit(user, savedRuleChain.getId()); autoCommit(user, savedRuleChain.getId());
tbClusterService.broadcastEntityStateChangeEvent(tenantId, savedRuleChain.getId(), ComponentLifecycleEvent.CREATED);
logEntityActionService.logEntityAction(tenantId, savedRuleChain.getId(), savedRuleChain, ActionType.ADDED, user); logEntityActionService.logEntityAction(tenantId, savedRuleChain.getId(), savedRuleChain, ActionType.ADDED, user);
return savedRuleChain; return savedRuleChain;
} catch (Exception e) { } catch (Exception e) {
@ -243,18 +231,11 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
RuleChain previousRootRuleChain = ruleChainService.getRootTenantRuleChain(tenantId); RuleChain previousRootRuleChain = ruleChainService.getRootTenantRuleChain(tenantId);
if (ruleChainService.setRootRuleChain(tenantId, ruleChainId)) { if (ruleChainService.setRootRuleChain(tenantId, ruleChainId)) {
if (previousRootRuleChain != null) { if (previousRootRuleChain != null) {
RuleChainId previousRootRuleChainId = previousRootRuleChain.getId(); previousRootRuleChain = ruleChainService.findRuleChainById(tenantId, previousRootRuleChain.getId());
previousRootRuleChain = ruleChainService.findRuleChainById(tenantId, previousRootRuleChainId); logEntityActionService.logEntityAction(tenantId, previousRootRuleChain.getId(), previousRootRuleChain,
tbClusterService.broadcastEntityStateChangeEvent(tenantId, previousRootRuleChainId,
ComponentLifecycleEvent.UPDATED);
logEntityActionService.logEntityAction(tenantId, previousRootRuleChainId, previousRootRuleChain,
ActionType.UPDATED, user); ActionType.UPDATED, user);
} }
ruleChain = ruleChainService.findRuleChainById(tenantId, ruleChainId); ruleChain = ruleChainService.findRuleChainById(tenantId, ruleChainId);
tbClusterService.broadcastEntityStateChangeEvent(tenantId, ruleChainId,
ComponentLifecycleEvent.UPDATED);
logEntityActionService.logEntityAction(tenantId, ruleChainId, ruleChain, ActionType.UPDATED, user); logEntityActionService.logEntityAction(tenantId, ruleChainId, ruleChain, ActionType.UPDATED, user);
} }
return ruleChain; return ruleChain;
@ -293,7 +274,6 @@ public class DefaultTbRuleChainService extends AbstractTbEntityService implement
RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaDataId)); RuleChainMetaData savedRuleChainMetaData = checkNotNull(ruleChainService.loadRuleChainMetaData(tenantId, ruleChainMetaDataId));
if (RuleChainType.CORE.equals(ruleChain.getType())) { if (RuleChainType.CORE.equals(ruleChain.getType())) {
tbClusterService.broadcastEntityStateChangeEvent(tenantId, ruleChainId, ComponentLifecycleEvent.UPDATED);
updatedRuleChains.forEach(updatedRuleChain -> updatedRuleChains.forEach(updatedRuleChain ->
tbClusterService.broadcastEntityStateChangeEvent(tenantId, updatedRuleChain.getId(), ComponentLifecycleEvent.UPDATED)); tbClusterService.broadcastEntityStateChangeEvent(tenantId, updatedRuleChain.getId(), ComponentLifecycleEvent.UPDATED));
} }

3
application/src/main/java/org/thingsboard/server/service/security/auth/oauth2/AbstractOAuth2ClientMapper.java

@ -24,7 +24,6 @@ import org.springframework.security.authentication.UsernamePasswordAuthenticatio
import org.springframework.security.core.userdetails.UsernameNotFoundException; import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.thingsboard.common.util.JacksonUtil; import org.thingsboard.common.util.JacksonUtil;
import org.thingsboard.server.cluster.TbClusterService;
import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.Customer;
import org.thingsboard.server.common.data.DashboardInfo; import org.thingsboard.server.common.data.DashboardInfo;
import org.thingsboard.server.common.data.StringUtils; import org.thingsboard.server.common.data.StringUtils;
@ -88,7 +87,7 @@ public abstract class AbstractOAuth2ClientMapper {
@Value("${edges.enabled}") @Value("${edges.enabled}")
@Getter @Getter
private boolean edgesEnabled; private boolean edgesEnabled;
private final Lock userCreationLock = new ReentrantLock(); private final Lock userCreationLock = new ReentrantLock();
protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2Registration registration) { protected SecurityUser getOrCreateSecurityUserFromOAuth2User(OAuth2User oauth2User, OAuth2Registration registration) {

23
common/dao-api/src/main/java/org/thingsboard/server/dao/entity/EntityStateSyncManager.java

@ -0,0 +1,23 @@
/**
* Copyright © 2016-2023 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.entity;
public interface EntityStateSyncManager {
ThreadLocal<Boolean> getSync();
boolean isSync();
}

10
dao/src/main/java/org/thingsboard/server/dao/asset/AssetProfileServiceImpl.java

@ -111,17 +111,13 @@ public class AssetProfileServiceImpl extends AbstractCachedEntityService<AssetPr
return toAssetProfileInfo(findAssetProfileById(tenantId, assetProfileId)); return toAssetProfileInfo(findAssetProfileById(tenantId, assetProfileId));
} }
@Override
public AssetProfile saveAssetProfile(AssetProfile assetProfile, boolean doValidate) {
return doSaveAssetProfile(assetProfile, doValidate);
}
@Override @Override
public AssetProfile saveAssetProfile(AssetProfile assetProfile) { public AssetProfile saveAssetProfile(AssetProfile assetProfile) {
return doSaveAssetProfile(assetProfile, true); return saveAssetProfile(assetProfile, true);
} }
private AssetProfile doSaveAssetProfile(AssetProfile assetProfile, boolean doValidate) { @Override
public AssetProfile saveAssetProfile(AssetProfile assetProfile, boolean doValidate) {
log.trace("Executing saveAssetProfile [{}]", assetProfile); log.trace("Executing saveAssetProfile [{}]", assetProfile);
AssetProfile oldAssetProfile = null; AssetProfile oldAssetProfile = null;
if (doValidate) { if (doValidate) {

10
dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java

@ -132,17 +132,13 @@ public class BaseAssetService extends AbstractCachedEntityService<AssetCacheKey,
.orElse(null), true); .orElse(null), true);
} }
@Override
public Asset saveAsset(Asset asset, boolean doValidate) {
return doSaveAsset(asset, doValidate);
}
@Override @Override
public Asset saveAsset(Asset asset) { public Asset saveAsset(Asset asset) {
return doSaveAsset(asset, true); return saveAsset(asset, true);
} }
private Asset doSaveAsset(Asset asset, boolean doValidate) { @Override
public Asset saveAsset(Asset asset, boolean doValidate) {
log.trace("Executing saveAsset [{}]", asset); log.trace("Executing saveAsset [{}]", asset);
Asset oldAsset = null; Asset oldAsset = null;
if (doValidate) { if (doValidate) {

12
dao/src/main/java/org/thingsboard/server/dao/dashboard/DashboardServiceImpl.java

@ -137,23 +137,19 @@ public class DashboardServiceImpl extends AbstractEntityService implements Dashb
return dashboardInfoDao.findByIdAsync(tenantId, dashboardId.getId()); return dashboardInfoDao.findByIdAsync(tenantId, dashboardId.getId());
} }
@Override
public Dashboard saveDashboard(Dashboard dashboard, boolean doValidate) {
return doSaveDashboard(dashboard, doValidate);
}
@Override @Override
public Dashboard saveDashboard(Dashboard dashboard) { public Dashboard saveDashboard(Dashboard dashboard) {
return doSaveDashboard(dashboard, true); return saveDashboard(dashboard, true);
} }
private Dashboard doSaveDashboard(Dashboard dashboard, boolean doValidate) { @Override
public Dashboard saveDashboard(Dashboard dashboard, boolean doValidate) {
log.trace("Executing saveDashboard [{}]", dashboard); log.trace("Executing saveDashboard [{}]", dashboard);
if (doValidate) { if (doValidate) {
dashboardValidator.validate(dashboard, DashboardInfo::getTenantId); dashboardValidator.validate(dashboard, DashboardInfo::getTenantId);
} }
try { try {
var saved = dashboardDao.save(dashboard.getTenantId(), dashboard); Dashboard saved = dashboardDao.save(dashboard.getTenantId(), dashboard);
publishEvictEvent(new DashboardTitleEvictEvent(saved.getId())); publishEvictEvent(new DashboardTitleEvictEvent(saved.getId()));
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(saved.getTenantId()) eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(saved.getTenantId())
.entityId(saved.getId()).added(dashboard.getId() == null).build()); .entityId(saved.getId()).added(dashboard.getId() == null).build());

10
dao/src/main/java/org/thingsboard/server/dao/device/DeviceProfileServiceImpl.java

@ -142,17 +142,13 @@ public class DeviceProfileServiceImpl extends AbstractCachedEntityService<Device
return toDeviceProfileInfo(findDeviceProfileById(tenantId, deviceProfileId)); return toDeviceProfileInfo(findDeviceProfileById(tenantId, deviceProfileId));
} }
@Override
public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile, boolean doValidate) {
return doSaveDeviceProfile(deviceProfile, doValidate);
}
@Override @Override
public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile) { public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile) {
return doSaveDeviceProfile(deviceProfile, true); return saveDeviceProfile(deviceProfile, true);
} }
private DeviceProfile doSaveDeviceProfile(DeviceProfile deviceProfile, boolean doValidate) { @Override
public DeviceProfile saveDeviceProfile(DeviceProfile deviceProfile, boolean doValidate) {
log.trace("Executing saveDeviceProfile [{}]", deviceProfile); log.trace("Executing saveDeviceProfile [{}]", deviceProfile);
if (deviceProfile.getProfileData() != null && deviceProfile.getProfileData().getProvisionConfiguration() instanceof X509CertificateChainProvisionConfiguration) { if (deviceProfile.getProfileData() != null && deviceProfile.getProfileData().getProvisionConfiguration() instanceof X509CertificateChainProvisionConfiguration) {
X509CertificateChainProvisionConfiguration x509Configuration = (X509CertificateChainProvisionConfiguration) deviceProfile.getProfileData().getProvisionConfiguration(); X509CertificateChainProvisionConfiguration x509Configuration = (X509CertificateChainProvisionConfiguration) deviceProfile.getProfileData().getProvisionConfiguration();

34
dao/src/main/java/org/thingsboard/server/dao/entity/DefaultEntityStateSyncManager.java

@ -0,0 +1,34 @@
/**
* Copyright © 2016-2023 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.entity;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
@Component
@Slf4j
public class DefaultEntityStateSyncManager implements EntityStateSyncManager {
@Getter
private final ThreadLocal<Boolean> sync = new ThreadLocal<>();
@Override
public boolean isSync() {
Boolean sync = this.sync.get();
return sync != null && sync;
}
}

10
dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java

@ -101,17 +101,13 @@ public class EntityViewServiceImpl extends AbstractCachedEntityService<EntityVie
cache.evict(keys); cache.evict(keys);
} }
@Override
public EntityView saveEntityView(EntityView entityView, boolean doValidate) {
return doSaveEntityView(entityView, doValidate);
}
@Override @Override
public EntityView saveEntityView(EntityView entityView) { public EntityView saveEntityView(EntityView entityView) {
return doSaveEntityView(entityView, true); return saveEntityView(entityView, true);
} }
private EntityView doSaveEntityView(EntityView entityView, boolean doValidate) { @Override
public EntityView saveEntityView(EntityView entityView, boolean doValidate) {
log.trace("Executing save entity view [{}]", entityView); log.trace("Executing save entity view [{}]", entityView);
EntityView old = null; EntityView old = null;
if (doValidate) { if (doValidate) {

1
dao/src/main/java/org/thingsboard/server/dao/eventsourcing/DeleteEntityEvent.java

@ -28,6 +28,7 @@ public class DeleteEntityEvent<T> {
private final EntityId entityId; private final EntityId entityId;
private final EdgeId edgeId; private final EdgeId edgeId;
private final T entity; private final T entity;
private final String body;
@Builder.Default @Builder.Default
private final long ts = System.currentTimeMillis(); private final long ts = System.currentTimeMillis();

48
dao/src/main/java/org/thingsboard/server/dao/rule/BaseRuleChainService.java

@ -38,6 +38,7 @@ import org.thingsboard.server.common.data.id.RuleChainId;
import org.thingsboard.server.common.data.id.RuleNodeId; import org.thingsboard.server.common.data.id.RuleNodeId;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.page.PageData; import org.thingsboard.server.common.data.page.PageData;
import org.thingsboard.server.common.data.page.PageDataIterable;
import org.thingsboard.server.common.data.page.PageLink; import org.thingsboard.server.common.data.page.PageLink;
import org.thingsboard.server.common.data.plugin.ComponentClusteringMode; import org.thingsboard.server.common.data.plugin.ComponentClusteringMode;
import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntityRelation;
@ -73,6 +74,7 @@ import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@ -135,6 +137,8 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
} else if (!previousRootRuleChain.getId().equals(ruleChain.getId())) { } else if (!previousRootRuleChain.getId().equals(ruleChain.getId())) {
previousRootRuleChain.setRoot(false); previousRootRuleChain.setRoot(false);
ruleChainDao.save(tenantId, previousRootRuleChain); ruleChainDao.save(tenantId, previousRootRuleChain);
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId)
.entityId(previousRootRuleChain.getId()).entity(previousRootRuleChain).added(false).build());
setRootAndSave(tenantId, ruleChain); setRootAndSave(tenantId, ruleChain);
return true; return true;
} }
@ -145,6 +149,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
private void setRootAndSave(TenantId tenantId, RuleChain ruleChain) { private void setRootAndSave(TenantId tenantId, RuleChain ruleChain) {
ruleChain.setRoot(true); ruleChain.setRoot(true);
ruleChainDao.save(tenantId, ruleChain); ruleChainDao.save(tenantId, ruleChain);
eventPublisher.publishEvent(SaveEntityEvent.builder().tenantId(tenantId).entityId(ruleChain.getId()).entity(ruleChain).added(false).build());
} }
@Override @Override
@ -290,11 +295,11 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
List<EntityRelation> nodeRelations = getRuleNodeRelations(tenantId, node.getId()); List<EntityRelation> nodeRelations = getRuleNodeRelations(tenantId, node.getId());
for (EntityRelation nodeRelation : nodeRelations) { for (EntityRelation nodeRelation : nodeRelations) {
String type = nodeRelation.getType(); String type = nodeRelation.getType();
if (nodeRelation.getTo().getEntityType() == EntityType.RULE_NODE) { if (EntityType.RULE_NODE.equals(nodeRelation.getTo().getEntityType())) {
RuleNodeId toNodeId = new RuleNodeId(nodeRelation.getTo().getId()); RuleNodeId toNodeId = new RuleNodeId(nodeRelation.getTo().getId());
int toIndex = ruleNodeIndexMap.get(toNodeId); int toIndex = ruleNodeIndexMap.get(toNodeId);
ruleChainMetaData.addConnectionInfo(fromIndex, toIndex, type); ruleChainMetaData.addConnectionInfo(fromIndex, toIndex, type);
} else if (nodeRelation.getTo().getEntityType() == EntityType.RULE_CHAIN) { } else if (EntityType.RULE_CHAIN.equals(nodeRelation.getTo().getEntityType())) {
log.warn("[{}][{}] Unsupported node relation: {}", tenantId, ruleChainId, nodeRelation.getTo()); log.warn("[{}][{}] Unsupported node relation: {}", tenantId, ruleChainId, nodeRelation.getTo());
} }
} }
@ -410,29 +415,24 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
public void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId) { public void deleteRuleChainById(TenantId tenantId, RuleChainId ruleChainId) {
Validator.validateId(ruleChainId, "Incorrect rule chain id for delete request."); Validator.validateId(ruleChainId, "Incorrect rule chain id for delete request.");
RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId()); RuleChain ruleChain = ruleChainDao.findById(tenantId, ruleChainId.getId());
List<RuleNode> referencingRuleNodes = getReferencingRuleChainNodes(tenantId, ruleChainId);
Set<RuleChainId> referencingRuleChainIds = referencingRuleNodes.stream().map(RuleNode::getRuleChainId).collect(Collectors.toSet());
if (ruleChain != null) { if (ruleChain != null) {
if (ruleChain.isRoot()) { if (ruleChain.isRoot()) {
throw new DataValidationException("Deletion of Root Tenant Rule Chain is prohibited!"); throw new DataValidationException("Deletion of Root Tenant Rule Chain is prohibited!");
} }
if (RuleChainType.EDGE.equals(ruleChain.getType())) { if (RuleChainType.EDGE.equals(ruleChain.getType())) {
PageLink pageLink = new PageLink(DEFAULT_PAGE_SIZE); for (Edge edge : new PageDataIterable<>(link -> edgeService.findEdgesByTenantIdAndEntityId(tenantId, ruleChainId, link), DEFAULT_PAGE_SIZE)) {
PageData<Edge> pageData; if (edge.getRootRuleChainId() != null && edge.getRootRuleChainId().equals(ruleChainId)) {
do { throw new DataValidationException("Can't delete rule chain that is root for edge [" + edge.getName() + "]. Please assign another root rule chain first to the edge!");
pageData = edgeService.findEdgesByTenantIdAndEntityId(tenantId, ruleChainId, pageLink);
if (pageData != null && pageData.getData() != null && !pageData.getData().isEmpty()) {
for (Edge edge : pageData.getData()) {
if (edge.getRootRuleChainId() != null && edge.getRootRuleChainId().equals(ruleChainId)) {
throw new DataValidationException("Can't delete rule chain that is root for edge [" + edge.getName() + "]. Please assign another root rule chain first to the edge!");
}
}
if (pageData.hasNext()) {
pageLink = pageLink.nextPageLink();
}
} }
} while (pageData != null && pageData.hasNext()); }
} }
} }
checkRuleNodesAndDelete(tenantId, ruleChainId); checkRuleNodesAndDelete(tenantId, ruleChain, referencingRuleChainIds);
referencingRuleChainIds.remove(ruleChainId);
} }
@Override @Override
@ -731,11 +731,15 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
return ruleNodeDao.save(tenantId, ruleNode); return ruleNodeDao.save(tenantId, ruleNode);
} }
private void checkRuleNodesAndDelete(TenantId tenantId, RuleChainId ruleChainId) { private void checkRuleNodesAndDelete(TenantId tenantId, RuleChain ruleChain, Set<RuleChainId> referencingRuleChainIds) {
try { try {
entityCountService.publishCountEntityEvictEvent(tenantId, EntityType.RULE_CHAIN); entityCountService.publishCountEntityEvictEvent(tenantId, EntityType.RULE_CHAIN);
ruleChainDao.removeById(tenantId, ruleChainId.getId()); ruleChainDao.removeById(tenantId, ruleChain.getUuidId());
eventPublisher.publishEvent(DeleteEntityEvent.builder().tenantId(tenantId).entityId(ruleChainId).build());
if (referencingRuleChainIds != null) {
referencingRuleChainIds.remove(ruleChain.getId());
}
eventPublisher.publishEvent(DeleteEntityEvent.builder().tenantId(tenantId).entityId(ruleChain.getId()).entity(ruleChain).body(JacksonUtil.toString(referencingRuleChainIds)).build());
} catch (Exception t) { } catch (Exception t) {
ConstraintViolationException e = extractConstraintViolationException(t).orElse(null); ConstraintViolationException e = extractConstraintViolationException(t).orElse(null);
if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_default_rule_chain_device_profile")) { if (e != null && e.getConstraintName() != null && e.getConstraintName().equalsIgnoreCase("fk_default_rule_chain_device_profile")) {
@ -746,7 +750,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
throw t; throw t;
} }
} }
deleteRuleNodes(tenantId, ruleChainId); deleteRuleNodes(tenantId, ruleChain.getId());
} }
private void deleteRuleNodes(TenantId tenantId, List<RuleNode> ruleNodes) { private void deleteRuleNodes(TenantId tenantId, List<RuleNode> ruleNodes) {
@ -815,7 +819,7 @@ public class BaseRuleChainService extends AbstractEntityService implements RuleC
@Override @Override
protected void removeEntity(TenantId tenantId, RuleChain entity) { protected void removeEntity(TenantId tenantId, RuleChain entity) {
checkRuleNodesAndDelete(tenantId, entity.getId()); checkRuleNodesAndDelete(tenantId, entity, null);
} }
}; };

Loading…
Cancel
Save