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 af62e04cff..84a8151316 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: - checkEntityView(entityViewService.findEntityViewById(new EntityViewId(entityId.getId()))); + checkEntityViewId(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); - checkEntityView(entityView); + checkEntityViewId(entityView); return entityView; } catch (Exception e) { throw handleException(e, false); } } - protected void checkEntityView(EntityView entityView) throws ThingsboardException { + protected void checkEntityViewId(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 26a48daff6..e6f149e05c 100644 --- a/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java +++ b/application/src/main/java/org/thingsboard/server/controller/EntityViewController.java @@ -17,7 +17,14 @@ package org.thingsboard.server.controller; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.web.bind.annotation.*; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; +import org.springframework.web.bind.annotation.RestController; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.EntityType; import org.thingsboard.server.common.data.EntityView; @@ -49,13 +56,10 @@ public class EntityViewController extends BaseController { @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @RequestMapping(value = "/entityView/{entityViewId}", method = RequestMethod.GET) @ResponseBody - public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) - throws ThingsboardException { - + public EntityView getEntityViewById(@PathVariable(ENTITY_VIEW_ID) String strEntityViewId) throws ThingsboardException { checkParameter(ENTITY_VIEW_ID, strEntityViewId); try { - EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); - return checkEntityViewId(entityViewId); + return checkEntityViewId(new EntityViewId(toUUID(strEntityViewId))); } catch (Exception e) { throw handleException(e); } @@ -70,13 +74,10 @@ public class EntityViewController extends BaseController { EntityView savedEntityView = checkNotNull(entityViewService.saveEntityView(entityView)); logEntityAction(savedEntityView.getId(), savedEntityView, null, entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, null); - return savedEntityView; - } catch (Exception e) { logEntityAction(emptyId(EntityType.ENTITY_VIEW), entityView, null, entityView.getId() == null ? ActionType.ADDED : ActionType.UPDATED, e); - throw handleException(e); } } @@ -90,7 +91,6 @@ public class EntityViewController extends BaseController { EntityViewId entityViewId = new EntityViewId(toUUID(strEntityViewId)); EntityView entityView = checkEntityViewId(entityViewId); entityViewService.deleteEntityView(entityViewId); - logEntityAction(entityViewId, entityView, entityView.getCustomerId(), ActionType.DELETED,null, strEntityViewId); } catch (Exception e) { @@ -117,11 +117,9 @@ public class EntityViewController extends BaseController { checkEntityViewId(entityViewId); EntityView savedEntityView = checkNotNull(entityViewService.assignEntityViewToCustomer(entityViewId, customerId)); - logEntityAction(entityViewId, savedEntityView, savedEntityView.getCustomerId(), ActionType.ASSIGNED_TO_CUSTOMER, null, strEntityViewId, strCustomerId, customer.getName()); - return savedEntityView; } catch (Exception e) { logEntityAction(emptyId(EntityType.ENTITY_VIEW), null, @@ -143,9 +141,7 @@ public class EntityViewController extends BaseController { throw new IncorrectParameterException("Entity View isn't assigned to any customer!"); } Customer customer = checkCustomerId(entityView.getCustomerId()); - EntityView savedEntityView = checkNotNull(entityViewService.unassignEntityViewFromCustomer(entityViewId)); - logEntityAction(entityViewId, entityView, entityView.getCustomerId(), ActionType.UNASSIGNED_FROM_CUSTOMER, null, strEntityViewId, customer.getId().toString(), customer.getName()); @@ -208,7 +204,7 @@ public class EntityViewController extends BaseController { List entityViews = checkNotNull(entityViewService.findEntityViewsByQuery(query).get()); entityViews = entityViews.stream().filter(entityView -> { try { - checkEntityView(entityView); + checkEntityViewId(entityView); return true; } catch (ThingsboardException e) { return false; diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java index e866bc89b8..395f9022b0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/CassandraEntityViewDao.java @@ -78,7 +78,7 @@ public class CassandraEntityViewDao extends CassandraAbstractSearchTextDao findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink) { + public List findEntityViewsByTenantId(UUID tenantId, TextPageLink pageLink) { log.debug("Try to find entity views by tenantId [{}] and pageLink [{}]", tenantId, pageLink); List entityViewEntities = findPageWithTextSearch(ENTITY_VIEW_BY_TENANT_AND_SEARCH_TEXT_COLUMN_FAMILY_NAME, diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java index 742cb92d90..ba433855e2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewDao.java @@ -45,7 +45,7 @@ public interface EntityViewDao extends Dao { * @param pageLink the page link * @return the list of entity view objects */ - List findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink); + List findEntityViewsByTenantId(UUID tenantId, TextPageLink pageLink); /** * Find entity views by tenantId and entity view name. diff --git a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java index 89b7e2f85c..19f326c0bc 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java +++ b/dao/src/main/java/org/thingsboard/server/dao/entityview/EntityViewService.java @@ -32,28 +32,27 @@ import java.util.List; */ public interface EntityViewService { - EntityView findEntityViewById(EntityViewId entityViewId); - EntityView saveEntityView(EntityView entityView); EntityView assignEntityViewToCustomer(EntityViewId entityViewId, CustomerId customerId); EntityView unassignEntityViewFromCustomer(EntityViewId entityViewId); - void deleteEntityView(EntityViewId entityViewId); + void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId); - TextPageData findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink); + EntityView findEntityViewById(EntityViewId entityViewId); - void deleteEntityViewsByTenantId(TenantId tenantId); + TextPageData findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink); - TextPageData findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, - TextPageLink pageLink); + TextPageData findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink); - void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId); + ListenableFuture> findEntityViewsByQuery(EntityViewSearchQuery query); ListenableFuture findEntityViewByIdAsync(EntityViewId entityViewId); - ListenableFuture> findEntityViewsByQuery(EntityViewSearchQuery query); - ListenableFuture> findEntityViewsByTenantIdAndEntityIdAsync(TenantId tenantId, EntityId entityId); + + void deleteEntityView(EntityViewId entityViewId); + + void deleteEntityViewsByTenantId(TenantId tenantId); } 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 8647af7fe4..79ceff2351 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 @@ -24,7 +24,6 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.cache.Cache; import org.springframework.cache.CacheManager; import org.springframework.cache.annotation.CacheEvict; -import org.springframework.cache.annotation.Cacheable; import org.springframework.stereotype.Service; import org.thingsboard.server.common.data.Customer; import org.thingsboard.server.common.data.DataConstants; @@ -41,6 +40,7 @@ import org.thingsboard.server.common.data.page.TextPageData; import org.thingsboard.server.common.data.page.TextPageLink; import org.thingsboard.server.common.data.relation.EntityRelation; import org.thingsboard.server.common.data.relation.EntitySearchDirection; +import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.attributes.AttributesService; import org.thingsboard.server.dao.customer.CustomerDao; import org.thingsboard.server.dao.entity.AbstractEntityService; @@ -54,13 +54,14 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; +import java.util.UUID; +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.dao.model.ModelConstants.NULL_UUID; import static org.thingsboard.server.dao.service.Validator.validateId; import static org.thingsboard.server.dao.service.Validator.validatePageLink; -import static org.thingsboard.server.dao.service.Validator.validateString; /** * Created by Victor Basanets on 8/28/2017. @@ -73,6 +74,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti public static final String INCORRECT_PAGE_LINK = "Incorrect page link "; public static final String INCORRECT_CUSTOMER_ID = "Incorrect customerId "; public static final String INCORRECT_ENTITY_VIEW_ID = "Incorrect entityViewId "; + private static final int DEFAULT_LIMIT = 100; @Autowired private EntityViewDao entityViewDao; @@ -89,13 +91,6 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti @Autowired private CacheManager cacheManager; - @Override - public EntityView findEntityViewById(EntityViewId entityViewId) { - log.trace("Executing findEntityViewById [{}]", entityViewId); - validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId); - return entityViewDao.findById(entityViewId.getId()); - } - @CacheEvict(cacheNames = ENTITY_VIEW_CACHE, key = "{#entityView.tenantId, #entityView.name}") @Override public EntityView saveEntityView(EntityView entityView) { @@ -110,41 +105,6 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti return savedEntityView; } - private void copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection keys) { - if (keys != null && !keys.isEmpty()) { - ListenableFuture> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys); - Futures.addCallback(getAttrFuture, new FutureCallback>() { - @Override - public void onSuccess(@Nullable List attributeKvEntries) { - if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) { - List filteredAttributes = - attributeKvEntries.stream() - .filter(attributeKvEntry -> { - if (entityView.getStartTimeMs() == 0 && entityView.getEndTimeMs() == 0) { - return true; - } - if (entityView.getEndTimeMs() == 0 && entityView.getStartTimeMs() < attributeKvEntry.getLastUpdateTs()) { - return true; - } - if (entityView.getStartTimeMs() == 0 && entityView.getEndTimeMs() > attributeKvEntry.getLastUpdateTs()) { - return true; - } - return entityView.getStartTimeMs() < attributeKvEntry.getLastUpdateTs() - && entityView.getEndTimeMs() > attributeKvEntry.getLastUpdateTs(); - }).collect(Collectors.toList()); - attributesService.save(entityView.getId(), scope, filteredAttributes); - } - } - - @Override - public void onFailure(Throwable throwable) { - log.error("Failed to fetch [{}] attributes [{}] for [{}] entity [{}]", - scope, keys, entityView.getEntityId().getEntityType().name(), entityView.getEntityId().getId().toString(), throwable); - } - }); - } - } - @Override public EntityView assignEntityViewToCustomer(EntityViewId entityViewId, CustomerId customerId) { EntityView entityView = findEntityViewById(entityViewId); @@ -160,63 +120,66 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti } @Override - public void deleteEntityView(EntityViewId entityViewId) { - log.trace("Executing deleteEntityView [{}]", entityViewId); - Cache cache = cacheManager.getCache(ENTITY_VIEW_CACHE); + public void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId) { + log.trace("Executing unassignCustomerEntityViews, tenantId [{}], customerId [{}]", tenantId, customerId); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); + new CustomerEntityViewsUnAssigner(tenantId).removeEntities(customerId); + } + + + @Override + public EntityView findEntityViewById(EntityViewId entityViewId) { + log.trace("Executing findEntityViewById [{}]", entityViewId); validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId); - deleteEntityRelations(entityViewId); - EntityView entityView = entityViewDao.findById(entityViewId.getId()); - cache.evict(Arrays.asList(entityView.getTenantId(), entityView.getName())); - entityViewDao.removeById(entityViewId.getId()); + List ids = Arrays.asList(entityViewId.getId()); + Cache cache = cacheManager.getCache(ENTITY_VIEW_CACHE); + EntityView fromCache = cache.get(ids, EntityView.class); + if (fromCache != null) { + return fromCache; + } else { + ListenableFuture entityViewFuture + = Futures.immediateFuture(entityViewDao.findById(entityViewId.getId())); + Futures.addCallback(entityViewFuture, + new FutureCallback() { + @Override + public void onSuccess(@Nullable EntityView result) { + cache.putIfAbsent(ids, result); + } + @Override + public void onFailure(Throwable t) {} + }); + try { + return entityViewFuture.get(); + } catch (Exception e) { + log.error(e.getMessage()); + } + } + return entityViewDao.findById(entityViewId.getId()); } @Override public TextPageData findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink) { - log.trace("Executing findEntityViewByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); + log.trace("Executing findEntityViewsByTenantId, tenantId [{}], pageLink [{}]", tenantId, pageLink); validateId(tenantId, INCORRECT_TENANT_ID + tenantId); validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink); - List entityViews = entityViewDao.findEntityViewByTenantId(tenantId.getId(), pageLink); + List entityViews = entityViewDao.findEntityViewsByTenantId(tenantId.getId(), pageLink); return new TextPageData<>(entityViews, pageLink); } - @Override - public void deleteEntityViewsByTenantId(TenantId tenantId) { - log.trace("Executing deleteEntityViewsByTenantId, tenantId [{}]", tenantId); - validateId(tenantId, INCORRECT_TENANT_ID + tenantId); - tenantEntityViewRemover.removeEntities(tenantId); - } - @Override public TextPageData findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink) { - log.trace("Executing findEntityViewByTenantIdAndCustomerId, tenantId [{}], customerId [{}]," + " pageLink [{}]", tenantId, customerId, pageLink); - validateId(tenantId, INCORRECT_TENANT_ID + tenantId); validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); validatePageLink(pageLink, INCORRECT_PAGE_LINK + pageLink); List entityViews = entityViewDao.findEntityViewsByTenantIdAndCustomerId(tenantId.getId(), customerId.getId(), pageLink); - return new TextPageData<>(entityViews, pageLink); } - @Override - public void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId) { - log.trace("Executing unassignCustomerEntityViews, tenantId [{}], customerId [{}]", tenantId, customerId); - validateId(tenantId, INCORRECT_TENANT_ID + tenantId); - validateId(customerId, INCORRECT_CUSTOMER_ID + customerId); - new CustomerEntityViewsUnAssigner(tenantId).removeEntities(customerId); - } - - @Override - public ListenableFuture findEntityViewByIdAsync(EntityViewId entityViewId) { - log.trace("Executing findEntityViewById [{}]", entityViewId); - validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId); - return entityViewDao.findByIdAsync(entityViewId.getId()); - } - @Override public ListenableFuture> findEntityViewsByQuery(EntityViewSearchQuery query) { ListenableFuture> relations = relationService.findByQuery(query.toEntitySearchQuery()); @@ -235,12 +198,99 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti return entityViews; } + @Override + public ListenableFuture findEntityViewByIdAsync(EntityViewId entityViewId) { + log.trace("Executing findEntityViewById [{}]", entityViewId); + validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId); + return entityViewDao.findByIdAsync(entityViewId.getId()); + } + @Override public ListenableFuture> findEntityViewsByTenantIdAndEntityIdAsync(TenantId tenantId, EntityId entityId) { 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 tenantAndEntityIds = Arrays.asList(tenantId, entityId); + Cache cache = cacheManager.getCache(ENTITY_VIEW_CACHE); + List fromCache = cache.get(tenantAndEntityIds, 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(tenantAndEntityIds, result); + } + @Override + public void onFailure(Throwable t) {} + }); + return entityViewsFuture; + } + } + + @Override + public void deleteEntityView(EntityViewId entityViewId) { + log.trace("Executing deleteEntityView [{}]", entityViewId); + validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId); + deleteEntityRelations(entityViewId); + cacheEvict(entityViewId, cacheManager.getCache(ENTITY_VIEW_CACHE)); + entityViewDao.removeById(entityViewId.getId()); + } + + @Override + public void deleteEntityViewsByTenantId(TenantId tenantId) { + log.trace("Executing deleteEntityViewsByTenantId, tenantId [{}]", tenantId); + validateId(tenantId, INCORRECT_TENANT_ID + tenantId); + entityViewDao.findEntityViewsByTenantId(tenantId.getId(), new TextPageLink(DEFAULT_LIMIT)).stream() + .map(view -> view.getId()) + .collect(Collectors.toList()) + .forEach(id -> cacheEvict(id, cacheManager.getCache(ENTITY_VIEW_CACHE))); + tenantEntityViewRemover.removeEntities(tenantId); + } + + private void cacheEvict(EntityViewId entityViewId, Cache cache) { + EntityView entityView = entityViewDao.findById(entityViewId.getId()); + cache.evict(Arrays.asList(entityView.getTenantId(), entityView.getName())); + cache.evict(Arrays.asList(entityView.getTenantId(), entityView.getEntityId())); + } + + private void copyAttributesFromEntityToEntityView(EntityView entityView, String scope, Collection keys) { + if (keys != null && !keys.isEmpty()) { + ListenableFuture> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys); + Futures.addCallback(getAttrFuture, new FutureCallback>() { + @Override + public void onSuccess(@Nullable List attributeKvEntries) { + if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) { + List filteredAttributes = + attributeKvEntries.stream() + .filter(attributeKvEntry -> { + if (entityView.getStartTimeMs() == 0 && entityView.getEndTimeMs() == 0) { + return true; + } + if (entityView.getEndTimeMs() == 0 && entityView.getStartTimeMs() < attributeKvEntry.getLastUpdateTs()) { + return true; + } + if (entityView.getStartTimeMs() == 0 && entityView.getEndTimeMs() > attributeKvEntry.getLastUpdateTs()) { + return true; + } + return entityView.getStartTimeMs() < attributeKvEntry.getLastUpdateTs() + && entityView.getEndTimeMs() > attributeKvEntry.getLastUpdateTs(); + }).collect(Collectors.toList()); + attributesService.save(entityView.getId(), scope, filteredAttributes); + } + } + + @Override + public void onFailure(Throwable throwable) { + log.error("Failed to fetch [{}] attributes [{}] for [{}] entity [{}]", + scope, keys, entityView.getEntityId().getEntityType().name(), entityView.getEntityId().getId().toString(), throwable); + } + }); + } } private DataValidator entityViewValidator = @@ -296,7 +346,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti @Override protected List findEntities(TenantId id, TextPageLink pageLink) { - return entityViewDao.findEntityViewByTenantId(id.getId(), pageLink); + return entityViewDao.findEntityViewsByTenantId(id.getId(), pageLink); } @Override diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java index 0cd1b2b0d6..912c9d5eed 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/entityview/JpaEntityViewDao.java @@ -66,7 +66,7 @@ public class JpaEntityViewDao extends JpaAbstractSearchTextDao findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink) { + public List findEntityViewsByTenantId(UUID tenantId, TextPageLink pageLink) { return DaoUtil.convertDataList( entityViewRepository.findByTenantId( fromTimeUUID(tenantId), 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 d609620edf..c5dcc0f62d 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 @@ -15,9 +15,7 @@ */ package org.thingsboard.rule.engine.action; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.google.common.base.Function; -import com.google.common.util.concurrent.Futures; +import com.google.common.util.concurrent.FutureCallback; import com.google.common.util.concurrent.ListenableFuture; import com.google.gson.JsonParser; import lombok.extern.slf4j.Slf4j; @@ -28,24 +26,23 @@ import org.thingsboard.rule.engine.api.TbNode; import org.thingsboard.rule.engine.api.TbNodeConfiguration; import org.thingsboard.rule.engine.api.TbNodeException; import org.thingsboard.rule.engine.api.TbRelationTypes; +import org.thingsboard.rule.engine.api.util.DonAsynchron; import org.thingsboard.rule.engine.api.util.TbNodeUtils; import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.EntityView; import org.thingsboard.server.common.data.kv.AttributeKvEntry; -import org.thingsboard.server.common.data.kv.TsKvEntry; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.common.msg.TbMsg; import org.thingsboard.server.common.msg.session.SessionMsgType; import org.thingsboard.server.common.transport.adaptor.JsonConverter; import javax.annotation.Nullable; -import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.concurrent.ExecutionException; import java.util.stream.Collectors; -import static org.thingsboard.rule.engine.api.util.DonAsynchron.withCallback; +import static org.thingsboard.rule.engine.api.TbRelationTypes.SUCCESS; @Slf4j @RuleNode( @@ -70,25 +67,22 @@ public class TbCopyAttributesToEntityViewNode implements TbNode { @Override public void onMsg(TbContext ctx, TbMsg msg) throws ExecutionException, InterruptedException, TbNodeException { - if (msg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) || - msg.getType().equals(DataConstants.ATTRIBUTES_DELETED) || - msg.getType().equals(DataConstants.ATTRIBUTES_UPDATED)) { + if (!msg.getMetaData().getData().isEmpty()) { long now = System.currentTimeMillis(); - String scope; - if (msg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name())) { - scope = DataConstants.CLIENT_SCOPE; - } else { - scope = msg.getMetaData().getValue("scope"); - } + String scope = msg.getType().equals(SessionMsgType.POST_ATTRIBUTES_REQUEST.name()) ? + DataConstants.CLIENT_SCOPE : msg.getMetaData().getValue("scope"); + ListenableFuture> entityViewsFuture = ctx.getEntityViewService().findEntityViewsByTenantIdAndEntityIdAsync(ctx.getTenantId(), msg.getOriginator()); - withCallback(entityViewsFuture, + + DonAsynchron.withCallback(entityViewsFuture, entityViews -> { - List>> saveFutures = new ArrayList<>(); for (EntityView entityView : entityViews) { - if ((entityView.getEndTimeMs() != 0 && entityView.getEndTimeMs() > now && entityView.getStartTimeMs() < now) || - (entityView.getEndTimeMs() == 0 && entityView.getStartTimeMs() < now)) { - Set attributes = JsonConverter.convertToAttributes(new JsonParser().parse(msg.getData())).getAttributes(); + long startTime = entityView.getStartTimeMs(); + long endTime = entityView.getEndTimeMs(); + if ((endTime != 0 && endTime > now && startTime < now) || (endTime == 0 && startTime < now)) { + Set attributes = + JsonConverter.convertToAttributes(new JsonParser().parse(msg.getData())).getAttributes(); List filteredAttributes = attributes.stream() .filter(attr -> { @@ -110,19 +104,22 @@ public class TbCopyAttributesToEntityViewNode implements TbNode { return entityView.getKeys().getAttributes().getSh().contains(attr.getKey()); } return false; - }) - .collect(Collectors.toList()); - saveFutures.add(ctx.getAttributesService().save(entityView.getId(), scope, new ArrayList<>(filteredAttributes))); + }).collect(Collectors.toList()); + + ctx.getTelemetryService().saveAndNotify(entityView.getId(), scope, filteredAttributes, + new FutureCallback() { + @Override + public void onSuccess(@Nullable Void result) { + ctx.tellNext(msg, SUCCESS); + } + + @Override + public void onFailure(Throwable t) { + ctx.tellFailure(msg, t); + } + }); } } - Futures.transform(Futures.allAsList(saveFutures), new Function>, Object>() { - @Nullable - @Override - public Object apply(@Nullable List> lists) { - ctx.tellNext(msg, TbRelationTypes.SUCCESS); - return null; - } - }); }, t -> ctx.tellFailure(msg, t)); } else {