thingsboard-aplcache

Changes

.mvn/jvm.config 1(+0 -1)

Details

diff --git a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
index ae9d967..5dd738b 100644
--- a/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
+++ b/application/src/main/java/org/thingsboard/server/actors/ActorSystemContext.java
@@ -37,6 +37,7 @@ import org.thingsboard.server.common.data.plugin.ComponentLifecycleEvent;
 import org.thingsboard.server.common.msg.cluster.ServerAddress;
 import org.thingsboard.server.common.transport.auth.DeviceAuthService;
 import org.thingsboard.server.controller.plugin.PluginWebSocketMsgEndpoint;
+import org.thingsboard.server.dao.alarm.AlarmService;
 import org.thingsboard.server.dao.asset.AssetService;
 import org.thingsboard.server.dao.attributes.AttributesService;
 import org.thingsboard.server.dao.customer.CustomerService;
@@ -106,6 +107,9 @@ public class ActorSystemContext {
     @Getter private EventService eventService;
 
     @Autowired
+    @Getter private AlarmService alarmService;
+
+    @Autowired
     @Getter @Setter private PluginWebSocketMsgEndpoint wsMsgEndpoint;
 
     @Value("${actors.session.sync.timeout}")
diff --git a/application/src/main/java/org/thingsboard/server/actors/rule/RuleProcessingContext.java b/application/src/main/java/org/thingsboard/server/actors/rule/RuleProcessingContext.java
index f425f8f..4c31fd0 100644
--- a/application/src/main/java/org/thingsboard/server/actors/rule/RuleProcessingContext.java
+++ b/application/src/main/java/org/thingsboard/server/actors/rule/RuleProcessingContext.java
@@ -15,22 +15,27 @@
  */
 package org.thingsboard.server.actors.rule;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import org.thingsboard.server.actors.ActorSystemContext;
 import org.thingsboard.server.common.data.Event;
+import org.thingsboard.server.common.data.alarm.Alarm;
+import org.thingsboard.server.common.data.alarm.AlarmId;
 import org.thingsboard.server.common.data.id.*;
+import org.thingsboard.server.dao.alarm.AlarmService;
 import org.thingsboard.server.dao.event.EventService;
 import org.thingsboard.server.dao.timeseries.TimeseriesService;
-import org.thingsboard.server.extensions.api.device.DeviceAttributes;
 import org.thingsboard.server.common.msg.device.ToDeviceActorMsg;
 import org.thingsboard.server.extensions.api.device.DeviceMetaData;
 import org.thingsboard.server.extensions.api.rules.RuleContext;
 
 import java.util.Optional;
+import java.util.concurrent.ExecutionException;
 
 public class RuleProcessingContext implements RuleContext {
 
     private final TimeseriesService tsService;
     private final EventService eventService;
+    private final AlarmService alarmService;
     private final RuleId ruleId;
     private TenantId tenantId;
     private CustomerId customerId;
@@ -40,6 +45,7 @@ public class RuleProcessingContext implements RuleContext {
     RuleProcessingContext(ActorSystemContext systemContext, RuleId ruleId) {
         this.tsService = systemContext.getTsService();
         this.eventService = systemContext.getEventService();
+        this.alarmService = systemContext.getAlarmService();
         this.ruleId = ruleId;
     }
 
@@ -77,6 +83,25 @@ public class RuleProcessingContext implements RuleContext {
         return eventService.findEvent(tenantId, deviceId, eventType, eventUid);
     }
 
+    @Override
+    public Alarm createOrUpdateAlarm(Alarm alarm) {
+        alarm.setTenantId(tenantId);
+        return alarmService.createOrUpdateAlarm(alarm);
+    }
+
+    public Optional<Alarm> findLatestAlarm(EntityId originator, String alarmType) {
+        try {
+            return Optional.ofNullable(alarmService.findLatestByOriginatorAndType(tenantId, originator, alarmType).get());
+        } catch (InterruptedException | ExecutionException e) {
+            throw new RuntimeException("Failed to lookup alarm!", e);
+        }
+    }
+
+    @Override
+    public ListenableFuture<Boolean> clearAlarm(AlarmId alarmId, long clearTs) {
+        return alarmService.clearAlarm(alarmId, clearTs);
+    }
+
     private void checkEvent(Event event) {
         if (event.getTenantId() == null) {
             event.setTenantId(tenantId);
diff --git a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseSchemaService.java b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseSchemaService.java
index f5fad09..fc92de8 100644
--- a/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseSchemaService.java
+++ b/application/src/main/java/org/thingsboard/server/service/install/SqlDatabaseSchemaService.java
@@ -20,10 +20,12 @@ import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.context.annotation.Profile;
 import org.springframework.stereotype.Service;
+import org.thingsboard.server.dao.util.SqlDao;
 
 @Service
 @Profile("install")
 @Slf4j
+@SqlDao
 public class SqlDatabaseSchemaService implements DatabaseSchemaService {
 
     @Value("${install.data_dir}")
diff --git a/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java b/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java
index e6f27a4..3caca2b 100644
--- a/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java
+++ b/application/src/main/java/org/thingsboard/server/ThingsboardInstallApplication.java
@@ -17,16 +17,14 @@
 package org.thingsboard.server;
 
 import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.SpringBootConfiguration;
 import org.springframework.context.ConfigurableApplicationContext;
 import org.springframework.context.annotation.ComponentScan;
 import org.thingsboard.server.install.ThingsboardInstallService;
 
 import java.util.Arrays;
 
-@EnableAutoConfiguration
-@SpringBootApplication
+@SpringBootConfiguration
 @ComponentScan({"org.thingsboard.server.install",
         "org.thingsboard.server.service.component",
         "org.thingsboard.server.service.install",
diff --git a/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java b/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java
index 052b61a..8be6105 100644
--- a/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java
+++ b/application/src/test/java/org/thingsboard/server/controller/AbstractControllerTest.java
@@ -80,7 +80,6 @@ import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppC
 @ActiveProfiles("test")
 @RunWith(SpringRunner.class)
 @ContextConfiguration(classes = AbstractControllerTest.class, loader = SpringBootContextLoader.class)
-@TestPropertySource(locations = {"classpath:cassandra-test.properties", "classpath:application-test.properties", "classpath:nosql-test.properties"})
 @DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)
 @Configuration
 @ComponentScan({"org.thingsboard.server"})
diff --git a/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java b/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java
new file mode 100644
index 0000000..b969227
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/ControllerSqlTestSuite.java
@@ -0,0 +1,36 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller;
+
+import org.junit.ClassRule;
+import org.junit.extensions.cpsuite.ClasspathSuite;
+import org.junit.runner.RunWith;
+import org.thingsboard.server.dao.CustomSqlUnit;
+
+import java.util.Arrays;
+
+@RunWith(ClasspathSuite.class)
+@ClasspathSuite.ClassnameFilters({
+        "org.thingsboard.server.controller.sql.*SqlTest",
+        })
+public class ControllerSqlTestSuite {
+
+    @ClassRule
+    public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
+            Arrays.asList("sql/schema.sql", "sql/system-data.sql"),
+            "sql/drop-all-tables.sql",
+            "sql-test.properties");
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/AdminControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/AdminControllerNoSqlTest.java
new file mode 100644
index 0000000..6ec28e7
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/AdminControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseAdminControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class AdminControllerNoSqlTest extends BaseAdminControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/AssetControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/AssetControllerNoSqlTest.java
new file mode 100644
index 0000000..a4bd152
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/AssetControllerNoSqlTest.java
@@ -0,0 +1,27 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseAssetControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+import org.thingsboard.server.dao.util.NoSqlDao;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class AssetControllerNoSqlTest extends BaseAssetControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/AuthControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/AuthControllerNoSqlTest.java
new file mode 100644
index 0000000..4896d22
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/AuthControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseAuthControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class AuthControllerNoSqlTest extends BaseAuthControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/ComponentDescriptorControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/ComponentDescriptorControllerNoSqlTest.java
new file mode 100644
index 0000000..f3aa3e8
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/ComponentDescriptorControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseComponentDescriptorControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class ComponentDescriptorControllerNoSqlTest extends BaseComponentDescriptorControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/CustomerControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/CustomerControllerNoSqlTest.java
new file mode 100644
index 0000000..2fa3067
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/CustomerControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseCustomerControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class CustomerControllerNoSqlTest extends BaseCustomerControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/DashboardControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/DashboardControllerNoSqlTest.java
new file mode 100644
index 0000000..2a7af40
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/DashboardControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseDashboardControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class DashboardControllerNoSqlTest extends BaseDashboardControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/DeviceControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/DeviceControllerNoSqlTest.java
new file mode 100644
index 0000000..47f1c9e
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/DeviceControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseDeviceControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class DeviceControllerNoSqlTest extends BaseDeviceControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/PluginControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/PluginControllerNoSqlTest.java
new file mode 100644
index 0000000..c25eca1
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/PluginControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BasePluginControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class PluginControllerNoSqlTest extends BasePluginControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/RuleControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/RuleControllerNoSqlTest.java
new file mode 100644
index 0000000..3bf64fb
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/RuleControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseRuleControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class RuleControllerNoSqlTest extends BaseRuleControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/TenantControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/TenantControllerNoSqlTest.java
new file mode 100644
index 0000000..7cb34d3
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/TenantControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseTenantControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class TenantControllerNoSqlTest extends BaseTenantControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/UserControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/UserControllerNoSqlTest.java
new file mode 100644
index 0000000..6540347
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/UserControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseUserControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class UserControllerNoSqlTest extends BaseUserControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/WidgetsBundleControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/WidgetsBundleControllerNoSqlTest.java
new file mode 100644
index 0000000..02b4c07
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/WidgetsBundleControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseWidgetsBundleControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class WidgetsBundleControllerNoSqlTest extends BaseWidgetsBundleControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/nosql/WidgetTypeControllerNoSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/nosql/WidgetTypeControllerNoSqlTest.java
new file mode 100644
index 0000000..852f453
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/nosql/WidgetTypeControllerNoSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.nosql;
+
+import org.thingsboard.server.controller.BaseWidgetTypeControllerTest;
+import org.thingsboard.server.dao.service.DaoNoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoNoSqlTest
+public class WidgetTypeControllerNoSqlTest extends BaseWidgetTypeControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/AdminControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/AdminControllerSqlTest.java
new file mode 100644
index 0000000..2491c32
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/AdminControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseAdminControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class AdminControllerSqlTest extends BaseAdminControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/AssetControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/AssetControllerSqlTest.java
new file mode 100644
index 0000000..519cc38
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/AssetControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseAssetControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class AssetControllerSqlTest extends BaseAssetControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/AuthControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/AuthControllerSqlTest.java
new file mode 100644
index 0000000..cb2b1f0
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/AuthControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseAuthControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class AuthControllerSqlTest extends BaseAuthControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/ComponentDescriptorControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/ComponentDescriptorControllerSqlTest.java
new file mode 100644
index 0000000..d96b3dd
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/ComponentDescriptorControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseComponentDescriptorControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class ComponentDescriptorControllerSqlTest extends BaseComponentDescriptorControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/CustomerControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/CustomerControllerSqlTest.java
new file mode 100644
index 0000000..8d3ba49
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/CustomerControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseCustomerControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class CustomerControllerSqlTest extends BaseCustomerControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/DashboardControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/DashboardControllerSqlTest.java
new file mode 100644
index 0000000..7ce48c7
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/DashboardControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseDashboardControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class DashboardControllerSqlTest extends BaseDashboardControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/DeviceControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/DeviceControllerSqlTest.java
new file mode 100644
index 0000000..8505e64
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/DeviceControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseDeviceControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class DeviceControllerSqlTest extends BaseDeviceControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/PluginControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/PluginControllerSqlTest.java
new file mode 100644
index 0000000..3d750c5
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/PluginControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BasePluginControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class PluginControllerSqlTest extends BasePluginControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/RuleControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/RuleControllerSqlTest.java
new file mode 100644
index 0000000..d70d550
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/RuleControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseRuleControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class RuleControllerSqlTest extends BaseRuleControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/TenantControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/TenantControllerSqlTest.java
new file mode 100644
index 0000000..582dc61
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/TenantControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseTenantControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class TenantControllerSqlTest extends BaseTenantControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/UserControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/UserControllerSqlTest.java
new file mode 100644
index 0000000..9b7fc3b
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/UserControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseUserControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class UserControllerSqlTest extends BaseUserControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/WidgetsBundleControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/WidgetsBundleControllerSqlTest.java
new file mode 100644
index 0000000..7e2e481
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/WidgetsBundleControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseWidgetsBundleControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class WidgetsBundleControllerSqlTest extends BaseWidgetsBundleControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/controller/sql/WidgetTypeControllerSqlTest.java b/application/src/test/java/org/thingsboard/server/controller/sql/WidgetTypeControllerSqlTest.java
new file mode 100644
index 0000000..db0cd3a
--- /dev/null
+++ b/application/src/test/java/org/thingsboard/server/controller/sql/WidgetTypeControllerSqlTest.java
@@ -0,0 +1,26 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.controller.sql;
+
+import org.thingsboard.server.controller.BaseWidgetTypeControllerTest;
+import org.thingsboard.server.dao.service.DaoSqlTest;
+
+/**
+ * Created by Valerii Sosliuk on 6/28/2017.
+ */
+@DaoSqlTest
+public class WidgetTypeControllerSqlTest extends BaseWidgetTypeControllerTest {
+}
diff --git a/application/src/test/java/org/thingsboard/server/system/SystemSqlTestSuite.java b/application/src/test/java/org/thingsboard/server/system/SystemSqlTestSuite.java
index 1f62027..21667a7 100644
--- a/application/src/test/java/org/thingsboard/server/system/SystemSqlTestSuite.java
+++ b/application/src/test/java/org/thingsboard/server/system/SystemSqlTestSuite.java
@@ -33,8 +33,7 @@ public class SystemSqlTestSuite {
     public static CustomSqlUnit sqlUnit = new CustomSqlUnit(
             Arrays.asList("sql/schema.sql", "sql/system-data.sql"),
             "sql/drop-all-tables.sql",
-            "sql-test.properties"
-    );
+            "sql-test.properties");
 
 
 }
diff --git a/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java
index 478d5c8..f9d70fa 100644
--- a/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java
+++ b/common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java
@@ -110,7 +110,6 @@ public class EntityRelation {
         if (to != null ? !to.equals(that.to) : that.to != null) return false;
         if (type != null ? !type.equals(that.type) : that.type != null) return false;
         return typeGroup == that.typeGroup;
-
     }
 
     @Override
diff --git a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java
index 63fba03..0c54f71 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/alarm/AlarmService.java
@@ -18,6 +18,7 @@ package org.thingsboard.server.dao.alarm;
 import com.google.common.util.concurrent.ListenableFuture;
 import org.thingsboard.server.common.data.alarm.*;
 import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.id.TenantId;
 import org.thingsboard.server.common.data.page.TimePageData;
 
 /**
@@ -40,4 +41,6 @@ public interface AlarmService {
     AlarmSeverity findHighestAlarmSeverity(EntityId entityId, AlarmSearchStatus alarmSearchStatus,
                                            AlarmStatus alarmStatus);
 
+    ListenableFuture<Alarm> findLatestByOriginatorAndType(TenantId tenantId, EntityId originator, String type);
+
 }
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 81f670a..d52df0f 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
@@ -27,6 +27,7 @@ import org.springframework.util.StringUtils;
 import org.thingsboard.server.common.data.Tenant;
 import org.thingsboard.server.common.data.alarm.*;
 import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.id.TenantId;
 import org.thingsboard.server.common.data.page.TimePageData;
 import org.thingsboard.server.common.data.page.TimePageLink;
 import org.thingsboard.server.common.data.relation.EntityRelation;
@@ -111,6 +112,10 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
         }
     }
 
+    public ListenableFuture<Alarm> findLatestByOriginatorAndType(TenantId tenantId, EntityId originator, String type) {
+        return alarmDao.findLatestByOriginatorAndType(tenantId, originator, type);
+    }
+
     private Alarm createAlarm(Alarm alarm) throws InterruptedException, ExecutionException {
         log.debug("New Alarm : {}", alarm);
         Alarm saved = alarmDao.save(alarm);
@@ -204,15 +209,15 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
         validateId(alarmId, "Incorrect alarmId " + alarmId);
         return Futures.transform(alarmDao.findAlarmByIdAsync(alarmId.getId()),
                 (AsyncFunction<Alarm, AlarmInfo>) alarm1 -> {
-                AlarmInfo alarmInfo = new AlarmInfo(alarm1);
-                return Futures.transform(
-                    entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), (Function<String, AlarmInfo>)
-                        originatorName -> {
-                            alarmInfo.setOriginatorName(originatorName);
-                            return alarmInfo;
-                        }
-                );
-        });
+                    AlarmInfo alarmInfo = new AlarmInfo(alarm1);
+                    return Futures.transform(
+                            entityService.fetchEntityNameAsync(alarmInfo.getOriginator()), (Function<String, AlarmInfo>)
+                                    originatorName -> {
+                                        alarmInfo.setOriginatorName(originatorName);
+                                        return alarmInfo;
+                                    }
+                    );
+                });
     }
 
     @Override
@@ -234,7 +239,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
                     ));
                 }
                 return Futures.successfulAsList(alarmFutures);
-             });
+            });
         }
         return Futures.transform(alarms, new Function<List<AlarmInfo>, TimePageData<AlarmInfo>>() {
             @Nullable
@@ -247,7 +252,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
 
     @Override
     public AlarmSeverity findHighestAlarmSeverity(EntityId entityId, AlarmSearchStatus alarmSearchStatus,
-                                                                    AlarmStatus alarmStatus) {
+                                                  AlarmStatus alarmStatus) {
         TimePageLink nextPageLink = new TimePageLink(100);
         boolean hasNext = true;
         AlarmSeverity highestSeverity = null;
@@ -321,7 +326,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
             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) {
             log.warn("[{}] Failed to update relations. Old status: [{}], New status: [{}]", alarm.getId(), oldStatus, newStatus);
diff --git a/dao/src/test/java/org/thingsboard/server/dao/CustomSqlUnit.java b/dao/src/test/java/org/thingsboard/server/dao/CustomSqlUnit.java
index 491e642..9649ad8 100644
--- a/dao/src/test/java/org/thingsboard/server/dao/CustomSqlUnit.java
+++ b/dao/src/test/java/org/thingsboard/server/dao/CustomSqlUnit.java
@@ -58,6 +58,8 @@ public class CustomSqlUnit extends ExternalResource {
 
     @Override
     public void before() {
+        cleanUpDb();
+
         Connection conn = null;
         try {
             conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword);
@@ -81,6 +83,10 @@ public class CustomSqlUnit extends ExternalResource {
 
     @Override
     public void after() {
+        cleanUpDb();
+    }
+
+    private void cleanUpDb() {
         Connection conn = null;
         try {
             conn = DriverManager.getConnection(dbUrl, dbUserName, dbPassword);
diff --git a/dao/src/test/resources/sql-test.properties b/dao/src/test/resources/sql-test.properties
index be6d353..0bcc789 100644
--- a/dao/src/test/resources/sql-test.properties
+++ b/dao/src/test/resources/sql-test.properties
@@ -1,4 +1,4 @@
-database.type=sql
+ database.type=sql
 
 spring.jpa.show-sql=false
 spring.jpa.hibernate.ddl-auto=validate
@@ -6,5 +6,5 @@ spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect
 
 spring.datasource.username=sa
 spring.datasource.password=
-spring.datasource.url=jdbc:hsqldb:mem:testDb;sql.enforce_size=false
+spring.datasource.url=jdbc:hsqldb:file:/tmp/testDb;sql.enforce_size=false
 spring.datasource.driverClassName=org.hsqldb.jdbc.JDBCDriver
\ No newline at end of file
diff --git a/extensions-api/src/main/java/org/thingsboard/server/extensions/api/rules/RuleContext.java b/extensions-api/src/main/java/org/thingsboard/server/extensions/api/rules/RuleContext.java
index 73f6576..6b381be 100644
--- a/extensions-api/src/main/java/org/thingsboard/server/extensions/api/rules/RuleContext.java
+++ b/extensions-api/src/main/java/org/thingsboard/server/extensions/api/rules/RuleContext.java
@@ -15,9 +15,12 @@
  */
 package org.thingsboard.server.extensions.api.rules;
 
+import com.google.common.util.concurrent.ListenableFuture;
 import org.thingsboard.server.common.data.Event;
+import org.thingsboard.server.common.data.alarm.Alarm;
+import org.thingsboard.server.common.data.alarm.AlarmId;
+import org.thingsboard.server.common.data.id.EntityId;
 import org.thingsboard.server.common.data.id.RuleId;
-import org.thingsboard.server.extensions.api.device.DeviceAttributes;
 import org.thingsboard.server.extensions.api.device.DeviceMetaData;
 
 import java.util.Optional;
@@ -34,4 +37,9 @@ public interface RuleContext {
 
     Optional<Event> findEvent(String eventType, String eventUid);
 
+    Optional<Alarm> findLatestAlarm(EntityId originator, String alarmType);
+
+    Alarm createOrUpdateAlarm(Alarm alarm);
+
+    ListenableFuture<Boolean> clearAlarm(AlarmId id, long clearTs);
 }
diff --git a/extensions-api/src/main/java/org/thingsboard/server/extensions/api/rules/RuleProcessor.java b/extensions-api/src/main/java/org/thingsboard/server/extensions/api/rules/RuleProcessor.java
index a4125b3..1e4fbf2 100644
--- a/extensions-api/src/main/java/org/thingsboard/server/extensions/api/rules/RuleProcessor.java
+++ b/extensions-api/src/main/java/org/thingsboard/server/extensions/api/rules/RuleProcessor.java
@@ -18,6 +18,8 @@ package org.thingsboard.server.extensions.api.rules;
 import org.thingsboard.server.common.msg.device.ToDeviceActorMsg;
 import org.thingsboard.server.extensions.api.component.ConfigurableComponent;
 
+import javax.script.ScriptException;
+
 /**
  * @author Andrew Shvayka
  */
diff --git a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/BasicJsFilter.java b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/BasicJsFilter.java
index ed94025..8e99807 100644
--- a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/BasicJsFilter.java
+++ b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/BasicJsFilter.java
@@ -75,18 +75,4 @@ public abstract class BasicJsFilter implements RuleFilter<JsFilterConfiguration>
         }
     }
 
-    protected static Object getValue(KvEntry attr) {
-        switch (attr.getDataType()) {
-            case STRING:
-                return attr.getStrValue().get();
-            case LONG:
-                return attr.getLongValue().get();
-            case DOUBLE:
-                return attr.getDoubleValue().get();
-            case BOOLEAN:
-                return attr.getBooleanValue().get();
-        }
-        return null;
-    }
-
 }
diff --git a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/DeviceAttributesFilter.java b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/DeviceAttributesFilter.java
index a63fcab..323de92 100644
--- a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/DeviceAttributesFilter.java
+++ b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/DeviceAttributesFilter.java
@@ -16,9 +16,6 @@
 package org.thingsboard.server.extensions.core.filter;
 
 import lombok.extern.slf4j.Slf4j;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.thingsboard.server.common.data.kv.AttributeKvEntry;
 import org.thingsboard.server.common.msg.core.UpdateAttributesRequest;
 import org.thingsboard.server.common.msg.device.ToDeviceActorMsg;
 import org.thingsboard.server.common.msg.session.FromDeviceMsg;
@@ -28,10 +25,6 @@ import org.thingsboard.server.extensions.api.rules.RuleContext;
 
 import javax.script.Bindings;
 import javax.script.ScriptException;
-import javax.script.SimpleBindings;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
 
 /**
  * @author Andrew Shvayka
@@ -40,25 +33,18 @@ import java.util.Map;
 @Slf4j
 public class DeviceAttributesFilter extends BasicJsFilter {
 
-    public static final String CLIENT_SIDE = "cs";
-    public static final String SERVER_SIDE = "ss";
-    public static final String SHARED = "shared";
-
     @Override
     protected boolean doFilter(RuleContext ctx, ToDeviceActorMsg msg) throws ScriptException {
         return evaluator.execute(toBindings(ctx.getDeviceMetaData().getDeviceAttributes(), msg != null ? msg.getPayload() : null));
     }
 
     private Bindings toBindings(DeviceAttributes attributes, FromDeviceMsg msg) {
-        Bindings bindings = new SimpleBindings();
-        convertListEntries(bindings, CLIENT_SIDE, attributes.getClientSideAttributes());
-        convertListEntries(bindings, SERVER_SIDE, attributes.getServerSideAttributes());
-        convertListEntries(bindings, SHARED, attributes.getServerSidePublicAttributes());
+        Bindings bindings = NashornJsEvaluator.getAttributeBindings(attributes);
 
         if (msg != null) {
             switch (msg.getMsgType()) {
                 case POST_ATTRIBUTES_REQUEST:
-                    updateBindings(bindings, (UpdateAttributesRequest) msg);
+                    bindings = NashornJsEvaluator.updateBindings(bindings, (UpdateAttributesRequest) msg);
                     break;
             }
         }
@@ -66,28 +52,4 @@ public class DeviceAttributesFilter extends BasicJsFilter {
         return bindings;
     }
 
-    private void updateBindings(Bindings bindings, UpdateAttributesRequest msg) {
-        Map<String, Object> attrMap = (Map<String, Object>) bindings.get(CLIENT_SIDE);
-        for (AttributeKvEntry attr : msg.getAttributes()) {
-            if (!CLIENT_SIDE.equalsIgnoreCase(attr.getKey()) && !SERVER_SIDE.equalsIgnoreCase(attr.getKey())
-                    && !SHARED.equalsIgnoreCase(attr.getKey())) {
-                bindings.put(attr.getKey(), getValue(attr));
-            }
-            attrMap.put(attr.getKey(), getValue(attr));
-        }
-        bindings.put(CLIENT_SIDE, attrMap);
-    }
-
-    public static Bindings convertListEntries(Bindings bindings, String attributesVarName, Collection<AttributeKvEntry> attributes) {
-        Map<String, Object> attrMap = new HashMap<>();
-        for (AttributeKvEntry attr : attributes) {
-            if (!CLIENT_SIDE.equalsIgnoreCase(attr.getKey()) && !SERVER_SIDE.equalsIgnoreCase(attr.getKey())
-                    && !SHARED.equalsIgnoreCase(attr.getKey())) {
-                bindings.put(attr.getKey(), getValue(attr));
-            }
-            attrMap.put(attr.getKey(), getValue(attr));
-        }
-        bindings.put(attributesVarName, attrMap);
-        return bindings;
-    }
 }
diff --git a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/DeviceTelemetryFilter.java b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/DeviceTelemetryFilter.java
index 8eaa233..d16258e 100644
--- a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/DeviceTelemetryFilter.java
+++ b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/DeviceTelemetryFilter.java
@@ -23,9 +23,7 @@ import org.thingsboard.server.common.msg.session.FromDeviceMsg;
 import org.thingsboard.server.extensions.api.component.Filter;
 import org.thingsboard.server.extensions.api.rules.RuleContext;
 
-import javax.script.Bindings;
 import javax.script.ScriptException;
-import javax.script.SimpleBindings;
 import java.util.List;
 
 /**
@@ -41,7 +39,7 @@ public class DeviceTelemetryFilter extends BasicJsFilter {
         if (deviceMsg instanceof TelemetryUploadRequest) {
             TelemetryUploadRequest telemetryMsg = (TelemetryUploadRequest) deviceMsg;
             for (List<KvEntry> entries : telemetryMsg.getData().values()) {
-                if (evaluator.execute(toBindings(entries))) {
+                if (evaluator.execute(NashornJsEvaluator.toBindings(entries))) {
                     return true;
                 }
             }
@@ -49,12 +47,4 @@ public class DeviceTelemetryFilter extends BasicJsFilter {
         return false;
     }
 
-    private Bindings toBindings(List<KvEntry> entries) {
-        Bindings bindings = new SimpleBindings();
-        for (KvEntry entry : entries) {
-            bindings.put(entry.getKey(), getValue(entry));
-        }
-        return bindings;
-    }
-
 }
diff --git a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/NashornJsEvaluator.java b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/NashornJsEvaluator.java
index cd3cd07..84b76ca 100644
--- a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/NashornJsEvaluator.java
+++ b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/filter/NashornJsEvaluator.java
@@ -17,10 +17,16 @@ package org.thingsboard.server.extensions.core.filter;
 
 import jdk.nashorn.api.scripting.NashornScriptEngineFactory;
 import lombok.extern.slf4j.Slf4j;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import org.thingsboard.server.common.data.kv.AttributeKvEntry;
+import org.thingsboard.server.common.data.kv.KvEntry;
+import org.thingsboard.server.common.msg.core.UpdateAttributesRequest;
+import org.thingsboard.server.extensions.api.device.DeviceAttributes;
 
 import javax.script.*;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
 
 /**
  * @author Andrew Shvayka
@@ -28,6 +34,9 @@ import javax.script.*;
 @Slf4j
 public class NashornJsEvaluator {
 
+    public static final String CLIENT_SIDE = "cs";
+    public static final String SERVER_SIDE = "ss";
+    public static final String SHARED = "shared";
     private static NashornScriptEngineFactory factory = new NashornScriptEngineFactory();
 
     private CompiledScript engine;
@@ -47,6 +56,65 @@ public class NashornJsEvaluator {
         }
     }
 
+    public static Bindings convertListEntries(Bindings bindings, String attributesVarName, Collection<AttributeKvEntry> attributes) {
+        Map<String, Object> attrMap = new HashMap<>();
+        for (AttributeKvEntry attr : attributes) {
+            if (!CLIENT_SIDE.equalsIgnoreCase(attr.getKey()) && !SERVER_SIDE.equalsIgnoreCase(attr.getKey())
+                    && !SHARED.equalsIgnoreCase(attr.getKey())) {
+                bindings.put(attr.getKey(), getValue(attr));
+            }
+            attrMap.put(attr.getKey(), getValue(attr));
+        }
+        bindings.put(attributesVarName, attrMap);
+        return bindings;
+    }
+
+    public static Bindings updateBindings(Bindings bindings, UpdateAttributesRequest msg) {
+        Map<String, Object> attrMap = (Map<String, Object>) bindings.get(CLIENT_SIDE);
+        for (AttributeKvEntry attr : msg.getAttributes()) {
+            if (!CLIENT_SIDE.equalsIgnoreCase(attr.getKey()) && !SERVER_SIDE.equalsIgnoreCase(attr.getKey())
+                    && !SHARED.equalsIgnoreCase(attr.getKey())) {
+                bindings.put(attr.getKey(), getValue(attr));
+            }
+            attrMap.put(attr.getKey(), getValue(attr));
+        }
+        bindings.put(CLIENT_SIDE, attrMap);
+        return bindings;
+    }
+
+    protected static Object getValue(KvEntry attr) {
+        switch (attr.getDataType()) {
+            case STRING:
+                return attr.getStrValue().get();
+            case LONG:
+                return attr.getLongValue().get();
+            case DOUBLE:
+                return attr.getDoubleValue().get();
+            case BOOLEAN:
+                return attr.getBooleanValue().get();
+        }
+        return null;
+    }
+
+    public static Bindings toBindings(List<KvEntry> entries) {
+        return toBindings(new SimpleBindings(), entries);
+    }
+
+    public static Bindings toBindings(Bindings bindings, List<KvEntry> entries) {
+        for (KvEntry entry : entries) {
+            bindings.put(entry.getKey(), getValue(entry));
+        }
+        return bindings;
+    }
+
+    public static Bindings getAttributeBindings(DeviceAttributes attributes) {
+        Bindings bindings = new SimpleBindings();
+        convertListEntries(bindings, CLIENT_SIDE, attributes.getClientSideAttributes());
+        convertListEntries(bindings, SERVER_SIDE, attributes.getServerSideAttributes());
+        convertListEntries(bindings, SHARED, attributes.getServerSidePublicAttributes());
+        return bindings;
+    }
+
     public Boolean execute(Bindings bindings) throws ScriptException {
         Object eval = engine.eval(bindings);
         if (eval instanceof Boolean) {
diff --git a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/processor/AlarmDeduplicationProcessor.java b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/processor/AlarmDeduplicationProcessor.java
index d7ebfec..4a39ee1 100644
--- a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/processor/AlarmDeduplicationProcessor.java
+++ b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/processor/AlarmDeduplicationProcessor.java
@@ -32,7 +32,7 @@ import java.util.Optional;
 /**
  * @author Andrew Shvayka
  */
-@Processor(name = "Alarm Deduplication Processor", descriptor = "AlarmDeduplicationProcessorDescriptor.json",
+@Processor(name = "(Deprecated) Alarm Deduplication Processor", descriptor = "AlarmDeduplicationProcessorDescriptor.json",
         configuration = AlarmDeduplicationProcessorConfiguration.class)
 @Slf4j
 public class AlarmDeduplicationProcessor extends SimpleRuleLifecycleComponent
diff --git a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/processor/AlarmProcessor.java b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/processor/AlarmProcessor.java
new file mode 100644
index 0000000..3dec45e
--- /dev/null
+++ b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/processor/AlarmProcessor.java
@@ -0,0 +1,213 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.extensions.core.processor;
+
+import java.util.Optional;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.runtime.parser.ParseException;
+import org.thingsboard.server.common.data.alarm.Alarm;
+import org.thingsboard.server.common.data.alarm.AlarmSeverity;
+import org.thingsboard.server.common.data.alarm.AlarmStatus;
+import org.thingsboard.server.common.data.kv.KvEntry;
+import org.thingsboard.server.common.msg.core.TelemetryUploadRequest;
+import org.thingsboard.server.common.msg.core.UpdateAttributesRequest;
+import org.thingsboard.server.common.msg.device.ToDeviceActorMsg;
+import org.thingsboard.server.common.msg.session.FromDeviceMsg;
+import org.thingsboard.server.extensions.api.component.Processor;
+import org.thingsboard.server.extensions.api.rules.*;
+import org.thingsboard.server.extensions.core.filter.NashornJsEvaluator;
+import org.thingsboard.server.extensions.core.utils.VelocityUtils;
+
+import javax.script.Bindings;
+import javax.script.ScriptException;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * @author Andrew Shvayka
+ */
+@Processor(name = "Alarm Processor", descriptor = "AlarmProcessorDescriptor.json",
+        configuration = AlarmProcessorConfiguration.class)
+@Slf4j
+public class AlarmProcessor implements RuleProcessor<AlarmProcessorConfiguration> {
+
+    static final String IS_NEW_ALARM = "isNewAlarm";
+    static final String IS_EXISTING_ALARM = "isExistingAlarm";
+    static final String IS_CLEARED_ALARM = "isClearedAlarm";
+
+    protected NashornJsEvaluator newAlarmEvaluator;
+    protected NashornJsEvaluator clearAlarmEvaluator;
+
+    private ObjectMapper mapper = new ObjectMapper();
+    private AlarmProcessorConfiguration configuration;
+    private AlarmStatus status;
+    private AlarmSeverity severity;
+    private Template alarmTypeTemplate;
+    private Template alarmDetailsTemplate;
+
+
+    @Override
+    public void init(AlarmProcessorConfiguration configuration) {
+        this.configuration = configuration;
+        try {
+            this.alarmTypeTemplate = VelocityUtils.create(configuration.getAlarmTypeTemplate(), "Alarm Type Template");
+            this.alarmDetailsTemplate = VelocityUtils.create(configuration.getAlarmDetailsTemplate(), "Alarm Details Template");
+            this.status = AlarmStatus.valueOf(configuration.getAlarmStatus());
+            this.severity = AlarmSeverity.valueOf(configuration.getAlarmSeverity());
+            initEvaluators();
+        } catch (Exception e) {
+            log.error("Failed to create templates based on provided configuration!", e);
+            throw new RuntimeException("Failed to create templates based on provided configuration!", e);
+        }
+    }
+
+    @Override
+    public void resume() {
+        initEvaluators();
+        log.debug("Resume method was called, but no impl provided!");
+    }
+
+    @Override
+    public void suspend() {
+        destroyEvaluators();
+        log.debug("Suspend method was called, but no impl provided!");
+    }
+
+    @Override
+    public void stop() {
+        destroyEvaluators();
+        log.debug("Stop method was called, but no impl provided!");
+    }
+
+    @Override
+    public RuleProcessingMetaData process(RuleContext ctx, ToDeviceActorMsg wrapper) throws RuleException {
+        RuleProcessingMetaData md = new RuleProcessingMetaData();
+
+        FromDeviceMsg msg = wrapper.getPayload();
+        Bindings bindings = buildBindings(ctx, msg);
+
+        boolean isActiveAlarm;
+        boolean isClearedAlarm;
+
+        try {
+            isActiveAlarm = newAlarmEvaluator.execute(bindings);
+            isClearedAlarm = clearAlarmEvaluator.execute(bindings);
+        } catch (ScriptException e) {
+            log.debug("[{}] Failed to evaluate alarm expressions!", ctx.getRuleId(), e);
+            throw new RuleException("Failed to evaluate alarm expressions!", e);
+        }
+
+        if (!isActiveAlarm && !isClearedAlarm) {
+            log.debug("[{}] Incoming message do not trigger alarm", ctx.getRuleId());
+            return md;
+        }
+
+        Alarm existing = null;
+        if (isActiveAlarm) {
+            Alarm alarm = buildAlarm(ctx, msg);
+            existing = ctx.createOrUpdateAlarm(alarm);
+            if (existing.getStartTs() == alarm.getStartTs()) {
+                log.debug("[{}][{}] New Active Alarm detected");
+                md.put(IS_NEW_ALARM, Boolean.TRUE);
+            } else {
+                log.debug("[{}][{}] Existing Active Alarm detected");
+                md.put(IS_EXISTING_ALARM, Boolean.TRUE);
+            }
+        } else if (isClearedAlarm) {
+            VelocityContext context = VelocityUtils.createContext(ctx.getDeviceMetaData(), msg);
+            String alarmType = VelocityUtils.merge(alarmTypeTemplate, context);
+            Optional<Alarm> alarm = ctx.findLatestAlarm(ctx.getDeviceMetaData().getDeviceId(), alarmType);
+            if (alarm.isPresent()) {
+                ctx.clearAlarm(alarm.get().getId(), System.currentTimeMillis());
+                log.debug("[{}][{}] Existing Active Alarm cleared");
+                md.put(IS_CLEARED_ALARM, Boolean.TRUE);
+                existing = alarm.get();
+            }
+        }
+        //TODO: handle cleared alarms
+
+        if (existing != null) {
+            md.put("alarmId", existing.getId().getId());
+            md.put("alarmType", existing.getType());
+            md.put("alarmSeverity", existing.getSeverity());
+            try {
+                md.put("alarmDetails", mapper.writeValueAsString(existing.getDetails()));
+            } catch (JsonProcessingException e) {
+                throw new RuleException("Failed to serialize alarm details", e);
+            }
+        }
+
+        return md;
+    }
+
+    private Alarm buildAlarm(RuleContext ctx, FromDeviceMsg msg) throws RuleException {
+        VelocityContext context = VelocityUtils.createContext(ctx.getDeviceMetaData(), msg);
+        String alarmType = VelocityUtils.merge(alarmTypeTemplate, context);
+        String alarmDetails = VelocityUtils.merge(alarmDetailsTemplate, context);
+
+        Alarm alarm = new Alarm();
+        alarm.setOriginator(ctx.getDeviceMetaData().getDeviceId());
+        alarm.setType(alarmType);
+
+        alarm.setStatus(status);
+        alarm.setSeverity(severity);
+        alarm.setPropagate(configuration.isAlarmPropagateFlag());
+
+        try {
+            alarm.setDetails(mapper.readTree(alarmDetails));
+        } catch (IOException e) {
+            log.debug("[{}] Failed to parse alarm details {} as json string after evaluation.", ctx.getRuleId(), e);
+            throw new RuleException("Failed to parse alarm details as json string after evaluation!", e);
+        }
+        return alarm;
+    }
+
+    private Bindings buildBindings(RuleContext ctx, FromDeviceMsg msg) {
+        Bindings bindings = NashornJsEvaluator.getAttributeBindings(ctx.getDeviceMetaData().getDeviceAttributes());
+        if (msg != null) {
+            switch (msg.getMsgType()) {
+                case POST_ATTRIBUTES_REQUEST:
+                    bindings = NashornJsEvaluator.updateBindings(bindings, (UpdateAttributesRequest) msg);
+                    break;
+                case POST_TELEMETRY_REQUEST:
+                    TelemetryUploadRequest telemetryMsg = (TelemetryUploadRequest) msg;
+                    for (List<KvEntry> entries : telemetryMsg.getData().values()) {
+                        bindings = NashornJsEvaluator.toBindings(bindings, entries);
+                    }
+            }
+        }
+        return bindings;
+    }
+
+    private void initEvaluators() {
+        newAlarmEvaluator = new NashornJsEvaluator(configuration.getNewAlarmExpression());
+        clearAlarmEvaluator = new NashornJsEvaluator(configuration.getClearAlarmExpression());
+    }
+
+    private void destroyEvaluators() {
+        if (newAlarmEvaluator != null) {
+            newAlarmEvaluator.destroy();
+        }
+        if (clearAlarmEvaluator != null) {
+            clearAlarmEvaluator.destroy();
+        }
+    }
+}
diff --git a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/processor/AlarmProcessorConfiguration.java b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/processor/AlarmProcessorConfiguration.java
new file mode 100644
index 0000000..197cc44
--- /dev/null
+++ b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/processor/AlarmProcessorConfiguration.java
@@ -0,0 +1,38 @@
+/**
+ * Copyright © 2016-2017 The Thingsboard Authors
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.thingsboard.server.extensions.core.processor;
+
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author Andrew Shvayka
+ */
+@Data
+public class AlarmProcessorConfiguration {
+
+    private String newAlarmExpression;
+    private String clearAlarmExpression;
+
+    private String alarmTypeTemplate;
+    private String alarmSeverity;
+    private String alarmStatus;
+    private boolean alarmPropagateFlag;
+
+    private String alarmDetailsTemplate;
+
+}
\ No newline at end of file
diff --git a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/utils/VelocityUtils.java b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/utils/VelocityUtils.java
index 6844234..fbb7612 100644
--- a/extensions-core/src/main/java/org/thingsboard/server/extensions/core/utils/VelocityUtils.java
+++ b/extensions-core/src/main/java/org/thingsboard/server/extensions/core/utils/VelocityUtils.java
@@ -29,7 +29,7 @@ import org.thingsboard.server.common.msg.session.FromDeviceMsg;
 import org.thingsboard.server.extensions.api.device.DeviceAttributes;
 import org.thingsboard.server.extensions.api.device.DeviceMetaData;
 import org.thingsboard.server.extensions.api.rules.RuleProcessingMetaData;
-import org.thingsboard.server.extensions.core.filter.DeviceAttributesFilter;
+import org.thingsboard.server.extensions.core.filter.NashornJsEvaluator;
 
 import java.io.StringReader;
 import java.io.StringWriter;
@@ -70,9 +70,9 @@ public class VelocityUtils {
         context.put("date", new DateTool());
         DeviceAttributes deviceAttributes = deviceMetaData.getDeviceAttributes();
 
-        pushAttributes(context, deviceAttributes.getClientSideAttributes(), DeviceAttributesFilter.CLIENT_SIDE);
-        pushAttributes(context, deviceAttributes.getServerSideAttributes(), DeviceAttributesFilter.SERVER_SIDE);
-        pushAttributes(context, deviceAttributes.getServerSidePublicAttributes(), DeviceAttributesFilter.SHARED);
+        pushAttributes(context, deviceAttributes.getClientSideAttributes(), NashornJsEvaluator.CLIENT_SIDE);
+        pushAttributes(context, deviceAttributes.getServerSideAttributes(), NashornJsEvaluator.SERVER_SIDE);
+        pushAttributes(context, deviceAttributes.getServerSidePublicAttributes(), NashornJsEvaluator.SHARED);
 
         switch (payload.getMsgType()) {
             case POST_TELEMETRY_REQUEST:
diff --git a/extensions-core/src/main/resources/AlarmProcessorDescriptor.json b/extensions-core/src/main/resources/AlarmProcessorDescriptor.json
new file mode 100644
index 0000000..32a4a50
--- /dev/null
+++ b/extensions-core/src/main/resources/AlarmProcessorDescriptor.json
@@ -0,0 +1,113 @@
+{
+  "schema": {
+    "title": "Alarm Configuration",
+    "type": "object",
+    "properties": {
+      "newAlarmExpression": {
+        "title": "Alarm trigger expression",
+        "type": "string",
+        "default": ""
+      },
+      "clearAlarmExpression": {
+        "title": "Alarm clear expression",
+        "type": "string",
+        "default": ""
+      },
+      "alarmTypeTemplate": {
+        "title": "Alarm type",
+        "type": "string"
+      },
+      "alarmSeverity": {
+        "title": "Severity",
+        "type": "string"
+      },
+      "alarmStatus": {
+        "title": "Status",
+        "type": "string"
+      },
+      "alarmPropagateFlag": {
+        "title": "Propagate Alarm",
+        "type": "boolean"
+      },
+      "alarmDetailsTemplate": {
+        "title": "Alarm details",
+        "type": "string"
+      }
+    },
+    "required": [
+      "newAlarmExpression",
+      "clearAlarmExpression",
+      "alarmSeverity",
+      "alarmStatus",
+      "alarmTypeTemplate",
+      "alarmDetailsTemplate"
+    ]
+  },
+  "form": [
+    {
+      "key": "newAlarmExpression",
+      "type": "javascript"
+    },
+    {
+      "key": "clearAlarmExpression",
+      "type": "javascript"
+    },
+    {
+      "key": "alarmSeverity",
+      "type": "rc-select",
+      "multiple": false,
+      "items": [
+        {
+          "value": "CRITICAL",
+          "label": "Critical"
+        },
+        {
+          "value": "MAJOR",
+          "label": "Major"
+        },
+        {
+          "value": "MINOR",
+          "label": "Minor"
+        },
+        {
+          "value": "WARNING",
+          "label": "Warning"
+        },
+        {
+          "value": "INDETERMINATE",
+          "label": "Indeterminate"
+        }
+      ]
+    },
+    {
+      "key": "alarmStatus",
+      "type": "rc-select",
+      "multiple": false,
+      "items": [
+        {
+          "value": "ACTIVE_UNACK",
+          "label": "Active Unacknowledged"
+        },
+        {
+          "value": "ACTIVE_ACK",
+          "label": "Active Acknowledged"
+        },
+        {
+          "value": "CLEARED_UNACK",
+          "label": "Cleared Unacknowledged"
+        },
+        {
+          "value": "CLEARED_ACK",
+          "label": "Cleared Acknowledged"
+        }
+      ]
+    },
+    "alarmTypeTemplate",
+    "alarmPropagateFlag",
+    {
+      "key": "alarmDetailsTemplate",
+      "type": "textarea",
+      "rows": 5
+    }
+  ]
+}
\ No newline at end of file