thingsboard-memoizeit

Details

diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java
index fe0c2ef..2dcd60a 100644
--- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java
+++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RemoteToRuleChainTellNextMsg.java
@@ -28,7 +28,7 @@ import java.io.Serializable;
  * Created by ashvayka on 19.03.18.
  */
 @Data
-final class RemoteToRuleChainTellNextMsg extends RuleNodeToRuleChainTellNextMsg implements TenantAwareMsg, RuleChainAwareMsg, Serializable {
+final class RemoteToRuleChainTellNextMsg extends RuleNodeToRuleChainTellNextMsg implements TenantAwareMsg, RuleChainAwareMsg {
 
     private static final long serialVersionUID = 2459605482321657447L;
     private final TenantId tenantId;
diff --git a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java
index 9414892..9914463 100644
--- a/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java
+++ b/application/src/main/java/org/thingsboard/server/actors/ruleChain/RuleNodeToRuleChainTellNextMsg.java
@@ -21,14 +21,16 @@ import org.thingsboard.server.common.msg.MsgType;
 import org.thingsboard.server.common.msg.TbActorMsg;
 import org.thingsboard.server.common.msg.TbMsg;
 
+import java.io.Serializable;
 import java.util.Set;
 
 /**
  * Created by ashvayka on 19.03.18.
  */
 @Data
-class RuleNodeToRuleChainTellNextMsg implements TbActorMsg {
+class RuleNodeToRuleChainTellNextMsg implements TbActorMsg, Serializable {
 
+    private static final long serialVersionUID = 4577026446412871820L;
     private final RuleNodeId originator;
     private final Set<String> relationTypes;
     private final TbMsg msg;
diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml
index 9f6192b..f510ec4 100644
--- a/application/src/main/resources/thingsboard.yml
+++ b/application/src/main/resources/thingsboard.yml
@@ -291,6 +291,9 @@ caffeine:
     devices:
       timeToLiveInMinutes: 1440
       maxSize: 100000
+    assets:
+      timeToLiveInMinutes: 1440
+      maxSize: 100000
 
 redis:
   # standalone or cluster
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java b/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java
index 88f7631..21de402 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/CacheConstants.java
@@ -19,4 +19,5 @@ public class CacheConstants {
     public static final String DEVICE_CREDENTIALS_CACHE = "deviceCredentials";
     public static final String RELATIONS_CACHE = "relations";
     public static final String DEVICE_CACHE = "devices";
+    public static final String ASSET_CACHE = "assets";
 }
diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java
index 6dc15c0..e373f0e 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/asset/AssetService.java
@@ -34,7 +34,7 @@ public interface AssetService {
 
     ListenableFuture<Asset> findAssetByIdAsync(AssetId assetId);
 
-    Optional<Asset> findAssetByTenantIdAndName(TenantId tenantId, String name);
+    Asset findAssetByTenantIdAndName(TenantId tenantId, String name);
 
     Asset saveAsset(Asset asset);
 
diff --git a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
index 1eafb07..6c8b609 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/asset/BaseAssetService.java
@@ -21,6 +21,10 @@ import com.google.common.util.concurrent.Futures;
 import com.google.common.util.concurrent.ListenableFuture;
 import lombok.extern.slf4j.Slf4j;
 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.springframework.util.StringUtils;
 import org.thingsboard.server.common.data.Customer;
@@ -48,15 +52,12 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
 import java.util.List;
-import java.util.Optional;
 import java.util.stream.Collectors;
 
+import static org.thingsboard.server.common.data.CacheConstants.ASSET_CACHE;
 import static org.thingsboard.server.dao.DaoUtil.toUUIDs;
 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.validateIds;
-import static org.thingsboard.server.dao.service.Validator.validatePageLink;
-import static org.thingsboard.server.dao.service.Validator.validateString;
+import static org.thingsboard.server.dao.service.Validator.*;
 
 @Service
 @Slf4j
@@ -75,6 +76,9 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
     @Autowired
     private CustomerDao customerDao;
 
+    @Autowired
+    private CacheManager cacheManager;
+
     @Override
     public Asset findAssetById(AssetId assetId) {
         log.trace("Executing findAssetById [{}]", assetId);
@@ -89,13 +93,16 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
         return assetDao.findByIdAsync(assetId.getId());
     }
 
+    @Cacheable(cacheNames = ASSET_CACHE, key = "{#tenantId, #name}")
     @Override
-    public Optional<Asset> findAssetByTenantIdAndName(TenantId tenantId, String name) {
+    public Asset findAssetByTenantIdAndName(TenantId tenantId, String name) {
         log.trace("Executing findAssetByTenantIdAndName [{}][{}]", tenantId, name);
         validateId(tenantId, INCORRECT_TENANT_ID + tenantId);
-        return assetDao.findAssetsByTenantIdAndName(tenantId.getId(), name);
+        return assetDao.findAssetsByTenantIdAndName(tenantId.getId(), name)
+                .orElse(null);
     }
 
+    @CacheEvict(cacheNames = ASSET_CACHE, key = "{#asset.tenantId, #asset.name}")
     @Override
     public Asset saveAsset(Asset asset) {
         log.trace("Executing saveAsset [{}]", asset);
@@ -122,6 +129,14 @@ public class BaseAssetService extends AbstractEntityService implements AssetServ
         log.trace("Executing deleteAsset [{}]", assetId);
         validateId(assetId, INCORRECT_ASSET_ID + assetId);
         deleteEntityRelations(assetId);
+
+        Cache cache = cacheManager.getCache(ASSET_CACHE);
+        Asset asset = assetDao.findById(assetId.getId());
+        List<Object> list = new ArrayList<>();
+        list.add(asset.getTenantId());
+        list.add(asset.getName());
+        cache.evict(list);
+
         assetDao.removeById(assetId.getId());
     }
 
diff --git a/dao/src/test/resources/application-test.properties b/dao/src/test/resources/application-test.properties
index f2dab45..20cf91c 100644
--- a/dao/src/test/resources/application-test.properties
+++ b/dao/src/test/resources/application-test.properties
@@ -21,6 +21,9 @@ caffeine.specs.deviceCredentials.maxSize=100000
 caffeine.specs.devices.timeToLiveInMinutes=1440
 caffeine.specs.devices.maxSize=100000
 
+caffeine.specs.assets.timeToLiveInMinutes=1440
+caffeine.specs.assets.maxSize=100000
+
 caching.specs.devices.timeToLiveInMinutes=1440
 caching.specs.devices.maxSize=100000
 
diff --git a/ui/src/app/locale/locale.constant-it_IT.json b/ui/src/app/locale/locale.constant-it_IT.json
index e8f973b..cdae11a 100644
--- a/ui/src/app/locale/locale.constant-it_IT.json
+++ b/ui/src/app/locale/locale.constant-it_IT.json
@@ -498,25 +498,25 @@
         "public-link": "Link pubblico",
         "copy-public-link": "Copia link pubblico",
         "public-link-copied-message": "Link pubblico della dashboard copiato negli appunti",
-        "manage-states": "Manage dashboard states",
-        "states": "Dashboard states",
-        "search-states": "Search dashboard states",
-        "selected-states": "{ count, plural, 1 {1 dashboard state} other {# dashboard states} } selected",
-        "edit-state": "Edit dashboard state",
-        "delete-state": "Delete dashboard state",
-        "add-state": "Add dashboard state",
-        "state": "Dashboard state",
+        "manage-states": "Gestisci stati dashboard",
+        "states": "Stati dashboard",
+        "search-states": "Ricerca stati dashboard",
+        "selected-states": "{ count, plural, 1 {1 stato dashboard selezionato} other {# stati dashboard selezionati} }",
+        "edit-state": "Modifica stato dashboard",
+        "delete-state": "Elimina stato dashboard",
+        "add-state": "Aggiungi stato dashboard",
+        "state": "Stato dashboard",
         "state-name": "Nome",
-        "state-name-required": "Dashboard state name is required.",
-        "state-id": "State Id",
-        "state-id-required": "Dashboard state id is required.",
-        "state-id-exists": "Dashboard state with the same id is already exists.",
-        "is-root-state": "Root state",
-        "delete-state-title": "Delete dashboard state",
-        "delete-state-text": "Are you sure you want delete dashboard state with name '{{stateName}}'?",
+        "state-name-required": "Nome stato dashboard obbligatorio.",
+        "state-id": "Id stato",
+        "state-id-required": "Id stato dashboard obbligatorio.",
+        "state-id-exists": "Uno stato della dashboard con lo stesso id è già presente.",
+        "is-root-state": "Stato radice",
+        "delete-state-title": "Elimina stato dashboard",
+        "delete-state-text": "Sei sicuro di voler eliminare lo stato della dashboard di nome '{{stateName}}'?",
         "show-details": "Mostra dettagli",
         "hide-details": "Nascondi dettagli",
-        "select-state": "Select target state",
+        "select-state": "Seleziona stato target",
         "state-controller": "Stato controller"
     },
     "datakey": {
@@ -570,7 +570,7 @@
         "alias-required": "Alias dispositivo richesto.",
         "remove-alias": "Rimuovi alias dispositivo",
         "add-alias": "Aggiungi alias dispositivo",
-        "name-starts-with": "Dispositivo il cui nome comincia per",
+        "name-starts-with": "Dispositivo il cui nome inizia per",
         "device-list": "Lista dispositivi",
         "use-device-name-filter": "Usa filtro",
         "device-list-empty": "Nessun dispositivo selezionato.",
@@ -680,7 +680,7 @@
         "entity-list-empty": "Nessuna entità selezionata.",
         "entity-type-list-empty": "Nessun tipo di entità selezionato.",
         "entity-name-filter-required": "Filtro nome entità obbligatorio.",
-        "entity-name-filter-no-entity-matched": "No entities starting with '{{entity}}' were found.",
+        "entity-name-filter-no-entity-matched": "Nessuna entità che inizia per '{{entity}}' è stata trovata.",
         "all-subtypes": "Tutte",
         "select-entities": "Seleziona entità",
         "no-aliases-found": "Nessun alias trovato.",
@@ -733,7 +733,7 @@
         "type-rulechains": "Rule chains",
         "list-of-rulechains": "{ count, plural, 1 {One rule chain} other {List of # rule chains} }",
         "rulechain-name-starts-with": "Rule chains whose names start with '{{prefix}}'",
-        "type-current-customer": "Current Customer",
+        "type-current-customer": "Cliente attuale",
         "search": "Ricerca entità",
         "selected-entities": "{ count, plural, 1 {1 entità selezionata} other {# entità selezionate} }",
         "entity-name": "Nome entità",
@@ -788,13 +788,13 @@
         "delete-extension-text": "Attenzione, dopo la conferma l'estensione e tutti i suoi data non saranno più recuperabili.",
         "delete-extensions-title": "Sei sicuro di voler eliminare { count, plural, 1 {1 estensione} other {# estensioni} }?",
         "delete-extensions-text": "Attenzione, dopo la conferma tutte le estensioni selezionate saranno eliminate.",
-        "converters": "Converters",
-        "converter-id": "Converter id",
+        "converters": "Convertitori",
+        "converter-id": "Id convertitore",
         "configuration": "Configurazione",
-        "converter-configurations": "Converter configurations",
+        "converter-configurations": "Configurazioni convertitore",
         "token": "Token di sicurezza",
-        "add-converter": "Add converter",
-        "add-config": "Add converter configuration",
+        "add-converter": "Aggiungi convertitore",
+        "add-config": "Aggiungi configurazione convertitore",
         "device-name-expression": "Device name expression",
         "device-type-expression": "Device type expression",
         "custom": "Custom",
@@ -828,7 +828,7 @@
         "drop-file": "Trascina un file o fai clic per selezionare un file da caricare.",
         "mapping": "Mapping",
         "topic-filter": "Filtro topic",
-        "converter-type": "Converter type",
+        "converter-type": "Tipo convertitore",
         "converter-json": "Json",
         "json-name-expression": "Device name json expression",
         "topic-name-expression": "Device name topic expression",
@@ -847,10 +847,10 @@
         "converter-json-required": "Convertitore json obbligatorio.",
         "converter-json-parse": "Unable to parse converter json.",
         "filter-expression": "Filter expression",
-        "connect-requests": "Connect requests",
-        "add-connect-request": "Add connect request",
-        "disconnect-requests": "Disconnect requests",
-        "add-disconnect-request": "Add disconnect request",
+        "connect-requests": "Richieste di connessione",
+        "add-connect-request": "Aggiungi richiesta di connessione",
+        "disconnect-requests": "Richieste di disconnessione",
+        "add-disconnect-request": "Aggiungi richiesta di disconnessione",
         "attribute-requests": "Attribute requests",
         "add-attribute-request": "Add attribute request",
         "attribute-updates": "Attribute updates",
@@ -919,8 +919,8 @@
             "not-available": "Non disponibile"
         },
 
-        "export-extensions-configuration": "Export extensions configuration",
-        "import-extensions-configuration": "Import extensions configuration",
+        "export-extensions-configuration": "Esporta configurazione estensioni",
+        "import-extensions-configuration": "Importa configurazione estensioni",
         "import-extensions": "Importa estensione",
         "import-extension": "Importa estensione",
         "export-extension": "Esporta estensione",
@@ -928,7 +928,7 @@
         "invalid-file-error": "File estensione non valido"
     },
     "fullscreen": {
-        "expand": "Expand to fullscreen",
+        "expand": "Espandi a tutto schermo",
         "exit": "Esci da schermo intero",
         "toggle": "Commuta modalità schermo intero",
         "fullscreen": "Schermo intero"
@@ -937,16 +937,16 @@
         "function": "Funzione"
     },
     "grid": {
-        "delete-item-title": "Are you sure you want to delete this item?",
-        "delete-item-text": "Be careful, after the confirmation this item and all related data will become unrecoverable.",
-        "delete-items-title": "Are you sure you want to delete { count, plural, 1 {1 item} other {# items} }?",
-        "delete-items-action-title": "Delete { count, plural, 1 {1 item} other {# items} }",
-        "delete-items-text": "Be careful, after the confirmation all selected items will be removed and all related data will become unrecoverable.",
-        "add-item-text": "Add new item",
-        "no-items-text": "No items found",
-        "item-details": "Item details",
-        "delete-item": "Delete Item",
-        "delete-items": "Delete Items",
+        "delete-item-title": "Sei sicuro di voler eliminare questo elemento?",
+        "delete-item-text": "Attenzione, dopo la conferma questo elemento e tutti i suoi dati non saranno più recuperabili.",
+        "delete-items-title": "Sei sicuro di voler eliminare { count, plural, 1 {1 elemento} other {# elementi} }?",
+        "delete-items-action-title": "Elimina { count, plural, 1 {1 elemento} other {# elementi} }",
+        "delete-items-text": "Attenzione, dopo la conferma tutti gli elementi selezionati saranno rimossi e i relativi dati non saranno più recuperabili.",
+        "add-item-text": "Aggiungi nuovo elemento",
+        "no-items-text": "Nessun elemento trovato",
+        "item-details": "Dettagli elemento",
+        "delete-item": "Elimina elemento",
+        "delete-items": "Elimina elementi",
         "scroll-to-top": "Scroll to top"
     },
     "help": {
@@ -985,7 +985,7 @@
         "settings": "Impostazioni layout",
         "color": "Colore",
         "main": "Main",
-        "right": "Right",
+        "right": "Destra",
         "select": "Select target layout"
     },
     "legend": {