Details
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 af62e04..84a8151 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 26a48da..e6f149e 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<EntityView> 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 e866bc8..395f902 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<Entit
}
@Override
- public List<EntityView> findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink) {
+ public List<EntityView> findEntityViewsByTenantId(UUID tenantId, TextPageLink pageLink) {
log.debug("Try to find entity views by tenantId [{}] and pageLink [{}]", tenantId, pageLink);
List<EntityViewEntity> 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 742cb92..ba43385 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<EntityView> {
* @param pageLink the page link
* @return the list of entity view objects
*/
- List<EntityView> findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink);
+ List<EntityView> 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 89b7e2f..19f326c 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<EntityView> findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink);
+ EntityView findEntityViewById(EntityViewId entityViewId);
- void deleteEntityViewsByTenantId(TenantId tenantId);
+ TextPageData<EntityView> findEntityViewByTenantId(TenantId tenantId, TextPageLink pageLink);
- TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId,
- TextPageLink pageLink);
+ TextPageData<EntityView> findEntityViewsByTenantIdAndCustomerId(TenantId tenantId, CustomerId customerId, TextPageLink pageLink);
- void unassignCustomerEntityViews(TenantId tenantId, CustomerId customerId);
+ ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query);
ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId);
- ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query);
-
ListenableFuture<List<EntityView>> 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 8647af7..79ceff2 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<String> keys) {
- if (keys != null && !keys.isEmpty()) {
- ListenableFuture<List<AttributeKvEntry>> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys);
- Futures.addCallback(getAttrFuture, new FutureCallback<List<AttributeKvEntry>>() {
- @Override
- public void onSuccess(@Nullable List<AttributeKvEntry> attributeKvEntries) {
- if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) {
- List<AttributeKvEntry> 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,64 +120,67 @@ 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<Object> 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<EntityView> entityViewFuture
+ = Futures.immediateFuture(entityViewDao.findById(entityViewId.getId()));
+ Futures.addCallback(entityViewFuture,
+ new FutureCallback<EntityView>() {
+ @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<EntityView> 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<EntityView> entityViews = entityViewDao.findEntityViewByTenantId(tenantId.getId(), pageLink);
+ List<EntityView> 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<EntityView> 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<EntityView> 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<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId) {
- log.trace("Executing findEntityViewById [{}]", entityViewId);
- validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
- return entityViewDao.findByIdAsync(entityViewId.getId());
- }
-
- @Override
public ListenableFuture<List<EntityView>> findEntityViewsByQuery(EntityViewSearchQuery query) {
ListenableFuture<List<EntityRelation>> relations = relationService.findByQuery(query.toEntitySearchQuery());
ListenableFuture<List<EntityView>> entityViews = Futures.transformAsync(relations, r -> {
@@ -236,11 +199,98 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
}
@Override
+ public ListenableFuture<EntityView> findEntityViewByIdAsync(EntityViewId entityViewId) {
+ log.trace("Executing findEntityViewById [{}]", entityViewId);
+ validateId(entityViewId, INCORRECT_ENTITY_VIEW_ID + entityViewId);
+ return entityViewDao.findByIdAsync(entityViewId.getId());
+ }
+
+ @Override
public ListenableFuture<List<EntityView>> 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<Object> tenantAndEntityIds = Arrays.asList(tenantId, entityId);
+ Cache cache = cacheManager.getCache(ENTITY_VIEW_CACHE);
+ List<EntityView> fromCache = cache.get(tenantAndEntityIds, List.class);
+ if (fromCache != null) {
+ return Futures.immediateFuture(fromCache);
+ } else {
+ ListenableFuture<List<EntityView>> entityViewsFuture =
+ entityViewDao.findEntityViewsByTenantIdAndEntityIdAsync(tenantId.getId(), entityId.getId());
+ Futures.addCallback(entityViewsFuture,
+ new FutureCallback<List<EntityView>>() {
+ @Override
+ public void onSuccess(@Nullable List<EntityView> 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<String> keys) {
+ if (keys != null && !keys.isEmpty()) {
+ ListenableFuture<List<AttributeKvEntry>> getAttrFuture = attributesService.find(entityView.getEntityId(), scope, keys);
+ Futures.addCallback(getAttrFuture, new FutureCallback<List<AttributeKvEntry>>() {
+ @Override
+ public void onSuccess(@Nullable List<AttributeKvEntry> attributeKvEntries) {
+ if (attributeKvEntries != null && !attributeKvEntries.isEmpty()) {
+ List<AttributeKvEntry> 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<EntityView> entityViewValidator =
@@ -296,7 +346,7 @@ public class EntityViewServiceImpl extends AbstractEntityService implements Enti
@Override
protected List<EntityView> 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 0cd1b2b..912c9d5 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<EntityViewEntity,
}
@Override
- public List<EntityView> findEntityViewByTenantId(UUID tenantId, TextPageLink pageLink) {
+ public List<EntityView> 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 d609620..c5dcc0f 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<List<EntityView>> entityViewsFuture =
ctx.getEntityViewService().findEntityViewsByTenantIdAndEntityIdAsync(ctx.getTenantId(), msg.getOriginator());
- withCallback(entityViewsFuture,
+
+ DonAsynchron.withCallback(entityViewsFuture,
entityViews -> {
- List<ListenableFuture<List<Void>>> saveFutures = new ArrayList<>();
for (EntityView entityView : entityViews) {
- if ((entityView.getEndTimeMs() != 0 && entityView.getEndTimeMs() > now && entityView.getStartTimeMs() < now) ||
- (entityView.getEndTimeMs() == 0 && entityView.getStartTimeMs() < now)) {
- Set<AttributeKvEntry> 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<AttributeKvEntry> attributes =
+ JsonConverter.convertToAttributes(new JsonParser().parse(msg.getData())).getAttributes();
List<AttributeKvEntry> 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<Void>() {
+ @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<List<List<Void>>, Object>() {
- @Nullable
- @Override
- public Object apply(@Nullable List<List<Void>> lists) {
- ctx.tellNext(msg, TbRelationTypes.SUCCESS);
- return null;
- }
- });
},
t -> ctx.tellFailure(msg, t));
} else {