diff --git a/application/src/main/java/org/thingsboard/server/controller/BaseController.java b/application/src/main/java/org/thingsboard/server/controller/BaseController.java index 84a8151316..af62e04cff 100644 --- a/application/src/main/java/org/thingsboard/server/controller/BaseController.java +++ b/application/src/main/java/org/thingsboard/server/controller/BaseController.java @@ -318,7 +318,7 @@ public abstract class BaseController { checkUserId(new UserId(entityId.getId())); return; case ENTITY_VIEW: - checkEntityViewId(entityViewService.findEntityViewById(new EntityViewId(entityId.getId()))); + checkEntityView(entityViewService.findEntityViewById(new EntityViewId(entityId.getId()))); return; default: throw new IllegalArgumentException("Unsupported entity type: " + entityId.getEntityType()); @@ -351,14 +351,14 @@ public abstract class BaseController { try { validateId(entityViewId, "Incorrect entityViewId " + entityViewId); EntityView entityView = entityViewService.findEntityViewById(entityViewId); - checkEntityViewId(entityView); + checkEntityView(entityView); return entityView; } catch (Exception e) { throw handleException(e, false); } } - protected void checkEntityViewId(EntityView entityView) throws ThingsboardException { + protected void checkEntityView(EntityView entityView) throws ThingsboardException { checkNotNull(entityView); checkTenantId(entityView.getTenantId()); if (entityView.getCustomerId() != null && !entityView.getCustomerId().getId().equals(ModelConstants.NULL_UUID)) { diff --git a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java index e6f149e05c..0ba35e85ad 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -204,7 +204,7 @@ public class EntityViewController extends BaseController { List entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(query).get()); entityViews = entityViews.stream().filter(entityView -> { try { - checkEntityViewId(entityView); + checkEntityView(entityView); return true; } catch (ThingsboardException e) { return false; diff --git a/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java b/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java index a9e94e9184..c8a5da8151 100644 --- a/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java +++ b/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java @@ -24,7 +24,7 @@ import java.util.Arrays; @RunWith(ClasspathSuite.class) @ClasspathSuite.ClassnameFilters({ - "org.thingsboard.server.controller.sql.EntityViewControllerSqlTest", + "org.thingsboard.server.controller.sql.*Test", }) public class ControllerSqlTestSuite { diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java index 6e7eba08c8..29ee9e46a0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewServiceImpl.java @@ -15,6 +15,7 @@ */ package org.thingsboard.server.dao.entityview; +import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.Futures; import com.google.common.util.concurrent.ListenableFuture; import lombok.extern.slf4j.Slf4j; @@ -49,6 +50,7 @@ import org.thingsboard.server.dao.service.DataValidator; import org.thingsboard.server.dao.service.PaginatedRemover; import org.thingsboard.server.dao.tenant.TenantDao; +import javax.annotation.Nullable; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -57,6 +59,7 @@ import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; import static org.thingsboard.server.common.data.CacheConstants.ENTITY_VIEW_CACHE; +import static org.thingsboard.server.common.data.CacheConstants.RELATIONS_CACHE; import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID; import static org.thingsboard.server.dao.service.Validator.validateId; import static org.thingsboard.server.dao.service.Validator.validatePageLink; @@ -197,7 +200,30 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti log.trace("Executing findEntityViewsByTenantIdAndEntityIdAsync, tenantId [{}], entityId [{}]", tenantId, entityId); validateId(tenantId, INCORRECT_TENANT_ID + tenantId); validateId(entityId.getId(), "Incorrect entityId" + entityId); - return entityViewDao.findEntityViewsByTenantIdAndEntityIdAsync(tenantId.getId(), entityId.getId()); + + List tenantIdAndEntityId = new ArrayList<>(); + tenantIdAndEntityId.add(tenantId); + tenantIdAndEntityId.add(entityId); + + Cache cache = cacheManager.getCache(ENTITY_VIEW_CACHE); + List fromCache = cache.get(tenantIdAndEntityId, List.class); + if (fromCache != null) { + return Futures.immediateFuture(fromCache); + } else { + ListenableFuture> entityViewsFuture = entityViewDao.findEntityViewsByTenantIdAndEntityIdAsync(tenantId.getId(), entityId.getId()); + Futures.addCallback(entityViewsFuture, + new FutureCallback>() { + @Override + public void onSuccess(@Nullable List result) { + cache.putIfAbsent(tenantIdAndEntityId, result); + } + @Override + public void onFailure(Throwable t) { + log.error("Error while finding entity views by tenantId and entityId", t); + } + }); + return entityViewsFuture; + } } @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityViewId}") @@ -206,9 +232,8 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti log.trace("Executing deleteEntityView [{}]", entityViewId); validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId); deleteEntityRelations(entityViewId); - Cache cache = cacheManager.getCache(ENTITY_VIEW_CACHE); EntityView entityView = entityViewDao.findById(entityViewId.getId()); - cache.evict(Arrays.asList(entityView.getTenantId(), entityView.getEntityId())); + cacheManager.getCache(ENTITY_VIEW_CACHE).evict(Arrays.asList(entityView.getTenantId(), entityView.getEntityId())); entityViewDao.removeById(entityViewId.getId()); } diff --git a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java index c5dcc0f62d..40e00ec009 100644 --- a/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java +++ b/rule-engine/rule-engine-components/src/main/java/org/thingsboard/rule/engine/action/TbCopyAttributesToEntityViewNode.java @@ -42,6 +42,7 @@ import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; +import static org.thingsboard.rule.engine.api.TbRelationTypes.FAILURE; import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @Slf4j @@ -49,9 +50,10 @@ import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; type = ComponentType.ACTION, name = "copy attributes", configClazz = EmptyNodeConfiguration.class, - nodeDescription = "Copy attributes from asset/device to entity view", + nodeDescription = "Copy attributes from asset/device to entity view and changes message originator to related entity view", nodeDetails = "Copy attributes from asset/device to related entity view according to entity view configuration. \n " + - "Copy will be done only for attributes that are between start and end dates and according to attribute keys configuration", + "Copy will be done only for attributes that are between start and end dates and according to attribute keys configuration. \n" + + "Changes message originator to related entity view and produces new messages according to count of updated entity views", uiResources = {"static/rulenode/rulenode-core-config.js"}, configDirective = "tbNodeEmptyConfig", icon = "content_copy" @@ -110,7 +112,8 @@ public class TbCopyAttributesToEntityViewNode implements TbNode { new FutureCallback() { @Override public void onSuccess(@Nullable Void result) { - ctx.tellNext(msg, SUCCESS); + TbMsg updMsg = ctx.transformMsg(msg, msg.getType(), entityView.getId(), msg.getMetaData(), msg.getData()); + ctx.tellNext(updMsg, SUCCESS); } @Override @@ -123,7 +126,7 @@ public class TbCopyAttributesToEntityViewNode implements TbNode { }, t -> ctx.tellFailure(msg, t)); } else { - ctx.tellNext(msg, TbRelationTypes.FAILURE); + ctx.tellNext(msg, FAILURE); } }