thingsboard-aplcache

Details

diff --git a/application/src/main/resources/thingsboard.yml b/application/src/main/resources/thingsboard.yml
index 5c00448..b133f03 100644
--- a/application/src/main/resources/thingsboard.yml
+++ b/application/src/main/resources/thingsboard.yml
@@ -241,7 +241,7 @@ spring:
     password: "${SPRING_DATASOURCE_PASSWORD:}"
 
 
-# Postgres DAO Configuration
+# PostgreSQL DAO Configuration
 #spring:
 #  data:
 #    jpa:
diff --git a/application/src/main/scripts/windows/install.bat b/application/src/main/scripts/windows/install.bat
index b49ca84..b54c0d9 100644
--- a/application/src/main/scripts/windows/install.bat
+++ b/application/src/main/scripts/windows/install.bat
@@ -82,6 +82,8 @@ SET SQL_DATA_FOLDER=%BASE%\data\sql
 SET jarfile=%BASE%\lib\${pkg.name}.jar
 SET installDir=%BASE%\data
 
+PUSHD %BASE%\conf
+
 java -cp %jarfile% -Dloader.main=org.thingsboard.server.ThingsboardInstallApplication^
                     -Dinstall.data_dir=%installDir%^
                     -Dinstall.load_demo=%loadDemo%^
@@ -92,8 +94,10 @@ java -cp %jarfile% -Dloader.main=org.thingsboard.server.ThingsboardInstallApplic
 
 if errorlevel 1 (
    @echo ThingsBoard installation failed!
+   POPD
    exit /b %errorlevel%
 )
+POPD
 
 %BASE%${pkg.name}.exe install
 
diff --git a/application/src/main/scripts/windows/upgrade.bat b/application/src/main/scripts/windows/upgrade.bat
index 9039d50..d1381bb 100644
--- a/application/src/main/scripts/windows/upgrade.bat
+++ b/application/src/main/scripts/windows/upgrade.bat
@@ -26,6 +26,8 @@ SET SQL_DATA_FOLDER=%BASE%\data\sql
 SET jarfile=%BASE%\lib\${pkg.name}.jar
 SET installDir=%BASE%\data
 
+PUSHD %BASE%\conf
+
 java -cp %jarfile% -Dloader.main=org.thingsboard.server.ThingsboardInstallApplication^
                     -Dinstall.data_dir=%installDir%^
                     -Dspring.jpa.hibernate.ddl-auto=none^
@@ -36,8 +38,10 @@ java -cp %jarfile% -Dloader.main=org.thingsboard.server.ThingsboardInstallApplic
 
 if errorlevel 1 (
    @echo ThingsBoard upgrade failed!
+   POPD
    exit /b %errorlevel%
 )
+POPD
 
 @ECHO ThingsBoard upgraded successfully!
 
diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
index 4fb9db5..3486960 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
@@ -118,17 +118,23 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
     private Alarm createAlarm(Alarm alarm) throws InterruptedException, ExecutionException {
         log.debug("New Alarm : {}", alarm);
         Alarm saved = alarmDao.save(alarm);
-        EntityRelationsQuery query = new EntityRelationsQuery();
-        query.setParameters(new RelationsSearchParameters(saved.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE));
-        List<EntityId> parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList());
-        for (EntityId parentId : parentEntities) {
-            createAlarmRelation(parentId, saved.getId(), saved.getStatus(), true);
-        }
-        createAlarmRelation(alarm.getOriginator(), saved.getId(), saved.getStatus(), true);
+        createAlarmRelations(saved);
         return saved;
     }
 
-    protected ListenableFuture<Alarm> updateAlarm(Alarm update) {
+    private void createAlarmRelations(Alarm alarm) throws InterruptedException, ExecutionException {
+        if (alarm.isPropagate()) {
+            EntityRelationsQuery query = new EntityRelationsQuery();
+            query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE));
+            List<EntityId> parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList());
+            for (EntityId parentId : parentEntities) {
+                createAlarmRelation(parentId, alarm.getId(), alarm.getStatus(), true);
+            }
+        }
+        createAlarmRelation(alarm.getOriginator(), alarm.getId(), alarm.getStatus(), true);
+    }
+
+    private ListenableFuture<Alarm> updateAlarm(Alarm update) {
         alarmDataValidator.validate(update);
         return getAndUpdate(update.getId(), new Function<Alarm, Alarm>() {
             @Nullable
@@ -146,8 +152,17 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
     private Alarm updateAlarm(Alarm oldAlarm, Alarm newAlarm) {
         AlarmStatus oldStatus = oldAlarm.getStatus();
         AlarmStatus newStatus = newAlarm.getStatus();
+        boolean oldPropagate = oldAlarm.isPropagate();
+        boolean newPropagate = newAlarm.isPropagate();
         Alarm result = alarmDao.save(merge(oldAlarm, newAlarm));
-        if (oldStatus != newStatus) {
+        if (!oldPropagate && newPropagate) {
+            try {
+                createAlarmRelations(result);
+            } catch (InterruptedException | ExecutionException e) {
+                log.warn("Failed to update alarm relations [{}]", result, e);
+                throw new RuntimeException(e);
+            }
+        } else if (oldStatus != newStatus) {
             updateRelations(oldAlarm, oldStatus, newStatus);
         }
         return result;
@@ -315,16 +330,19 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
         existing.setStatus(alarm.getStatus());
         existing.setSeverity(alarm.getSeverity());
         existing.setDetails(alarm.getDetails());
+        existing.setPropagate(existing.isPropagate() || alarm.isPropagate());
         return existing;
     }
 
     private void updateRelations(Alarm alarm, AlarmStatus oldStatus, AlarmStatus newStatus) {
         try {
-            EntityRelationsQuery query = new EntityRelationsQuery();
-            query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE));
-            List<EntityId> parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList());
-            for (EntityId parentId : parentEntities) {
-                updateAlarmRelation(parentId, alarm.getId(), oldStatus, newStatus);
+            if (alarm.isPropagate()) {
+                EntityRelationsQuery query = new EntityRelationsQuery();
+                query.setParameters(new RelationsSearchParameters(alarm.getOriginator(), EntitySearchDirection.TO, Integer.MAX_VALUE));
+                List<EntityId> parentEntities = relationService.findByQuery(query).get().stream().map(r -> r.getFrom()).collect(Collectors.toList());
+                for (EntityId parentId : parentEntities) {
+                    updateAlarmRelation(parentId, alarm.getId(), oldStatus, newStatus);
+                }
             }
             updateAlarmRelation(alarm.getOriginator(), alarm.getId(), oldStatus, newStatus);
         } catch (ExecutionException | InterruptedException e) {
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java
index e94fb4d..ee32444 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java
@@ -20,6 +20,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.repository.CrudRepository;
 import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
 import org.thingsboard.server.common.data.UUIDConverter;
 import org.thingsboard.server.common.data.id.ComponentDescriptorId;
 import org.thingsboard.server.common.data.page.TextPageLink;
@@ -102,11 +103,13 @@ public class JpaBaseComponentDescriptorDao extends JpaAbstractSearchTextDao<Comp
     }
 
     @Override
+    @Transactional
     public void deleteById(ComponentDescriptorId componentId) {
         removeById(componentId.getId());
     }
 
     @Override
+    @Transactional
     public void deleteByClazz(String clazz) {
         componentDescriptorRepository.deleteByClazz(clazz);
     }
diff --git a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmServiceTest.java b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmServiceTest.java
index 65e25e8..b208e75 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmServiceTest.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/service/BaseAlarmServiceTest.java
@@ -99,6 +99,7 @@ public abstract class BaseAlarmServiceTest extends AbstractServiceTest {
         long ts = System.currentTimeMillis();
         Alarm alarm = Alarm.builder().tenantId(tenantId).originator(childId)
                 .type(TEST_ALARM)
+                .propagate(false)
                 .severity(AlarmSeverity.CRITICAL).status(AlarmStatus.ACTIVE_UNACK)
                 .startTs(ts).build();
 
@@ -121,6 +122,28 @@ public abstract class BaseAlarmServiceTest extends AbstractServiceTest {
                         new TimePageLink(1, 0L, System.currentTimeMillis(), false)
                 ).build()).get();
         Assert.assertNotNull(alarms.getData());
+        Assert.assertEquals(0, alarms.getData().size());
+
+        created.setPropagate(true);
+        created = alarmService.createOrUpdateAlarm(created);
+
+        // Check child relation
+        alarms = alarmService.findAlarms(AlarmQuery.builder()
+                .affectedEntityId(childId)
+                .status(AlarmStatus.ACTIVE_UNACK).pageLink(
+                        new TimePageLink(1, 0L, System.currentTimeMillis(), false)
+                ).build()).get();
+        Assert.assertNotNull(alarms.getData());
+        Assert.assertEquals(1, alarms.getData().size());
+        Assert.assertEquals(created, alarms.getData().get(0));
+
+        // Check parent relation
+        alarms = alarmService.findAlarms(AlarmQuery.builder()
+                .affectedEntityId(parentId)
+                .status(AlarmStatus.ACTIVE_UNACK).pageLink(
+                        new TimePageLink(1, 0L, System.currentTimeMillis(), false)
+                ).build()).get();
+        Assert.assertNotNull(alarms.getData());
         Assert.assertEquals(1, alarms.getData().size());
         Assert.assertEquals(created, alarms.getData().get(0));
 
diff --git a/extensions-core/src/main/resources/AlarmProcessorDescriptor.json b/extensions-core/src/main/resources/AlarmProcessorDescriptor.json
index 32a4a50..534cc4e 100644
--- a/extensions-core/src/main/resources/AlarmProcessorDescriptor.json
+++ b/extensions-core/src/main/resources/AlarmProcessorDescriptor.json
@@ -27,7 +27,8 @@
       },
       "alarmPropagateFlag": {
         "title": "Propagate Alarm",
-        "type": "boolean"
+        "type": "boolean",
+        "default": true
       },
       "alarmDetailsTemplate": {
         "title": "Alarm details",