thingsboard-memoizeit
Changes
dao/src/test/resources/dbunit/events.xml 18(+18 -0)
Details
diff --git a/dao/src/main/java/org/thingsboard/server/dao/event/CassandraBaseEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/event/CassandraBaseEventDao.java
index 3598d2a..5d4b91c 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/event/CassandraBaseEventDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/event/CassandraBaseEventDao.java
@@ -142,7 +142,7 @@ public class CassandraBaseEventDao extends CassandraAbstractSearchTimeDao<EventE
.value(ModelConstants.EVENT_ENTITY_TYPE_PROPERTY, entity.getEntityType())
.value(ModelConstants.EVENT_ENTITY_ID_PROPERTY, entity.getEntityId())
.value(ModelConstants.EVENT_TYPE_PROPERTY, entity.getEventType())
- .value(ModelConstants.EVENT_UID_PROPERTY, entity.getEventUId())
+ .value(ModelConstants.EVENT_UID_PROPERTY, entity.getEventUid())
.value(ModelConstants.EVENT_BODY_PROPERTY, entity.getBody());
if (ifNotExists) {
insert = insert.ifNotExists();
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EventEntity.java
index a2987b1..acd5b8d 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EventEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/nosql/EventEntity.java
@@ -36,7 +36,7 @@ import java.util.UUID;
*/
@Data
@NoArgsConstructor
-@Table(name = DEVICE_COLUMN_FAMILY_NAME)
+@Table(name = EVENT_COLUMN_FAMILY_NAME)
public class EventEntity implements BaseEntity<Event> {
@Transient
@@ -63,7 +63,7 @@ public class EventEntity implements BaseEntity<Event> {
@ClusteringColumn(value = 1)
@Column(name = EVENT_UID_PROPERTY)
- private String eventUId;
+ private String eventUid;
@Column(name = EVENT_BODY_PROPERTY, codec = JsonCodec.class)
private JsonNode body;
@@ -80,7 +80,7 @@ public class EventEntity implements BaseEntity<Event> {
this.entityId = event.getEntityId().getId();
}
this.eventType = event.getType();
- this.eventUId = event.getUid();
+ this.eventUid = event.getUid();
this.body = event.getBody();
}
@@ -118,7 +118,7 @@ public class EventEntity implements BaseEntity<Event> {
}
event.setBody(body);
event.setType(eventType);
- event.setUid(eventUId);
+ event.setUid(eventUid);
return event;
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java
index 92808ba..9bfa663 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/EventEntity.java
@@ -22,46 +22,51 @@ import javax.persistence.Id;
import javax.persistence.Table;
import javax.persistence.Transient;
import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.NoArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.Event;
import org.thingsboard.server.common.data.id.*;
import org.thingsboard.server.dao.model.BaseEntity;
-import org.thingsboard.server.dao.model.ModelConstants;
+import static org.thingsboard.server.dao.model.ModelConstants.*;
+
+import java.io.IOException;
import java.util.UUID;
@Data
+@Slf4j
@NoArgsConstructor
-//@Entity
-@Table(name = ModelConstants.DEVICE_COLUMN_FAMILY_NAME)
+@Entity
+@Table(name = EVENT_COLUMN_FAMILY_NAME)
public class EventEntity implements BaseEntity<Event> {
@Transient
private static final long serialVersionUID = -5717830061727466727L;
- @Column(name = ModelConstants.ID_PROPERTY)
+ @Id
+ @Column(name = ID_PROPERTY, columnDefinition = "BINARY(16)")
private UUID id;
- @Id
- @Column(name = ModelConstants.EVENT_TENANT_ID_PROPERTY)
+ @Column(name = EVENT_TENANT_ID_PROPERTY, columnDefinition = "BINARY(16)")
private UUID tenantId;
- @Column(name = ModelConstants.EVENT_ENTITY_TYPE_PROPERTY)
+ @Column(name = EVENT_ENTITY_TYPE_PROPERTY)
private EntityType entityType;
- @Column(name = ModelConstants.EVENT_ENTITY_ID_PROPERTY)
+ @Column(name = EVENT_ENTITY_ID_PROPERTY, columnDefinition = "BINARY(16)")
private UUID entityId;
- @Column(name = ModelConstants.EVENT_TYPE_PROPERTY)
+ @Column(name = EVENT_TYPE_PROPERTY)
private String eventType;
- @Column(name = ModelConstants.EVENT_UID_PROPERTY)
- private String eventUId;
+ @Column(name = EVENT_UID_PROPERTY)
+ private String eventUid;
- @Column(name = ModelConstants.EVENT_BODY_PROPERTY)
- private JsonNode body;
+ @Column(name = EVENT_BODY_PROPERTY)
+ private String body;
public EventEntity(Event event) {
if (event.getId() != null) {
@@ -75,8 +80,10 @@ public class EventEntity implements BaseEntity<Event> {
this.entityId = event.getEntityId().getId();
}
this.eventType = event.getType();
- this.eventUId = event.getUid();
- this.body = event.getBody();
+ this.eventUid = event.getUid();
+ if (event.getBody() != null) {
+ this.body = event.getBody().toString();
+ }
}
@Override
@@ -111,9 +118,17 @@ public class EventEntity implements BaseEntity<Event> {
event.setEntityId(new PluginId(entityId));
break;
}
- event.setBody(body);
+ ObjectMapper mapper = new ObjectMapper();
+ if (body != null) {
+ try {
+ JsonNode jsonNode = mapper.readTree(body);
+ event.setBody(jsonNode);
+ } catch (IOException e) {
+ log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", body, e.getMessage()), e);
+ }
+ }
event.setType(eventType);
- event.setUid(eventUId);
+ event.setUid(eventUid);
return event;
}
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventRepository.java
new file mode 100644
index 0000000..32a5b3b
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/EventRepository.java
@@ -0,0 +1,24 @@
+package org.thingsboard.server.dao.sql.event;
+
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.data.repository.query.Param;
+import org.thingsboard.server.common.data.EntityType;
+import org.thingsboard.server.common.data.Event;
+import org.thingsboard.server.dao.model.sql.EventEntity;
+
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 5/3/2017.
+ */
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public interface EventRepository extends CrudRepository<EventEntity, UUID>, JpaSpecificationExecutor<EventEntity> {
+
+ EventEntity findByTenantIdAndEntityTypeAndEntityIdAndEventTypeAndEventUid(
+ UUID tenantId, EntityType entityType, UUID id, String eventType, String eventUid);
+
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java
new file mode 100644
index 0000000..3972c8e
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDao.java
@@ -0,0 +1,137 @@
+package org.thingsboard.server.dao.sql.event;
+
+import com.datastax.driver.core.utils.UUIDs;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
+import org.springframework.data.domain.PageRequest;
+import org.springframework.data.domain.Pageable;
+import org.springframework.data.domain.Sort;
+import org.springframework.data.jpa.domain.Specification;
+import org.springframework.data.repository.CrudRepository;
+import org.springframework.stereotype.Component;
+import org.thingsboard.server.common.data.Event;
+import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.page.TimePageLink;
+import org.thingsboard.server.dao.DaoUtil;
+import org.thingsboard.server.dao.event.EventDao;
+import org.thingsboard.server.dao.model.sql.EventEntity;
+import org.thingsboard.server.dao.sql.JpaAbstractSearchTimeDao;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.springframework.data.jpa.domain.Specifications.where;
+import static org.thingsboard.server.dao.model.ModelConstants.EVENT_COLUMN_FAMILY_NAME;
+import static org.thingsboard.server.dao.model.ModelConstants.ID_PROPERTY;
+import static org.thingsboard.server.dao.model.ModelConstants.NULL_UUID;
+
+/**
+ * Created by Valerii Sosliuk on 5/3/2017.
+ */
+@Slf4j
+@Component
+@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
+public class JpaBaseEventDao extends JpaAbstractSearchTimeDao<EventEntity, Event> implements EventDao {
+
+ private final UUID systemTenantId = NULL_UUID;
+
+ @Autowired
+ private EventRepository eventRepository;
+
+ @Override
+ protected Class<EventEntity> getEntityClass() {
+ return EventEntity.class;
+ }
+
+ @Override
+ protected String getColumnFamilyName() {
+ return EVENT_COLUMN_FAMILY_NAME;
+ }
+
+ @Override
+ protected CrudRepository<EventEntity, UUID> getCrudRepository() {
+ return eventRepository;
+ }
+
+ @Override
+ public Event save(Event event) {
+ if (StringUtils.isEmpty(event.getUid())) {
+ event.setUid(event.getId().toString());
+ }
+ return save(new EventEntity(event), false).orElse(null);
+ }
+
+ @Override
+ public Optional<Event> saveIfNotExists(Event event) {
+ return save(new EventEntity(event), true);
+ }
+
+ @Override
+ public Event findEvent(UUID tenantId, EntityId entityId, String eventType, String eventUid) {
+ return DaoUtil.getData(eventRepository.findByTenantIdAndEntityTypeAndEntityIdAndEventTypeAndEventUid(
+ tenantId, entityId.getEntityType(), entityId.getId(), eventType, eventUid));
+ }
+
+ @Override
+ public List<Event> findEvents(UUID tenantId, EntityId entityId, TimePageLink pageLink) {
+ return findEvents(tenantId, entityId, null, pageLink);
+ }
+ @Override
+ public List<Event> findEvents(UUID tenantId, EntityId entityId, String eventType, TimePageLink pageLink) {
+ Specification<EventEntity> timeSearchSpec = getTimeSearchPageSpec(pageLink);
+ Specification<EventEntity> fieldsSpec = getEntityFieldsSpec(tenantId, entityId, eventType);
+ Sort.Direction sortDirection = pageLink.isAscOrder() ? Sort.Direction.ASC : Sort.Direction.DESC;
+ Pageable pageable = new PageRequest(0, pageLink.getLimit(), sortDirection, ID_PROPERTY);
+ return DaoUtil.convertDataList(eventRepository.findAll(where(timeSearchSpec).and(fieldsSpec), pageable).getContent());
+ }
+
+ public Optional<Event> save(EventEntity entity, boolean ifNotExists) {
+ log.debug("Save event [{}] ", entity);
+ if (entity.getTenantId() == null) {
+ log.trace("Save system event with predefined id {}", systemTenantId);
+ entity.setTenantId(systemTenantId);
+ }
+ if (entity.getId() == null) {
+ entity.setId(UUIDs.timeBased());
+ }
+ if (StringUtils.isEmpty(entity.getEventUid())) {
+ entity.setEventUid(entity.getId().toString());
+ }
+ if (ifNotExists && findById(entity.getId()) != null) {
+ return Optional.empty();
+ }
+ return Optional.of(DaoUtil.getData(eventRepository.save(entity)));
+ }
+
+ private Specification<EventEntity> getEntityFieldsSpec(UUID tenantId, EntityId entityId, String eventType) {
+ return new Specification<EventEntity>() {
+ @Override
+ public Predicate toPredicate(Root<EventEntity> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
+ List<Predicate> predicates = new ArrayList<Predicate>();
+ if (tenantId != null) {
+ Predicate tenantIdPredicate = criteriaBuilder.equal(root.get("tenantId"), tenantId);
+ predicates.add(tenantIdPredicate);
+ }
+ if (entityId != null) {
+ Predicate entityTypePredicate = criteriaBuilder.equal(root.get("entityType"), entityId.getEntityType());
+ Predicate entityIdPredicate = criteriaBuilder.equal(root.get("entityId"), entityId.getId());
+ predicates.add(entityTypePredicate);
+ predicates.add(entityIdPredicate);
+ }
+ if (eventType != null) {
+ Predicate eventTypePredicate = criteriaBuilder.equal(root.get("eventType"), eventType);
+ predicates.add(eventTypePredicate);
+ }
+ return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+ }
+ };
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTextDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTextDao.java
new file mode 100644
index 0000000..02d0e07
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTextDao.java
@@ -0,0 +1,14 @@
+package org.thingsboard.server.dao.sql;
+
+import org.thingsboard.server.dao.model.BaseEntity;
+
+/**
+ * Created by Valerii Sosliuk on 5/6/2017.
+ */
+public abstract class JpaAbstractSearchTextDao <E extends BaseEntity<D>, D> extends JpaAbstractDao<E, D> {
+
+ @Override
+ protected boolean isSearchTextDao() {
+ return true;
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTimeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTimeDao.java
new file mode 100644
index 0000000..f0e5cb2
--- /dev/null
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractSearchTimeDao.java
@@ -0,0 +1,62 @@
+package org.thingsboard.server.dao.sql;
+
+import com.datastax.driver.core.utils.UUIDs;
+import org.springframework.data.jpa.domain.Specification;
+import org.thingsboard.server.common.data.page.TimePageLink;
+import org.thingsboard.server.dao.model.BaseEntity;
+import static org.thingsboard.server.dao.model.ModelConstants.*;
+
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Predicate;
+import javax.persistence.criteria.Root;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Created by Valerii Sosliuk on 5/4/2017.
+ */
+public abstract class JpaAbstractSearchTimeDao<E extends BaseEntity<D>, D> extends JpaAbstractDao<E, D> {
+
+ protected Specification<E> getTimeSearchPageSpec(TimePageLink pageLink) {
+ return new Specification<E>() {
+ @Override
+ public Predicate toPredicate(Root<E> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
+ Predicate lowerBound = null;
+ Predicate upperBound = null;
+ List<Predicate> predicates = new ArrayList<>();
+ if (pageLink.isAscOrder()) {
+ if (pageLink.getIdOffset() != null) {
+ lowerBound = criteriaBuilder.greaterThan(root.get(ID_PROPERTY), pageLink.getIdOffset());
+ predicates.add(lowerBound);
+ } else if (pageLink.getStartTime() != null) {
+ UUID startOf = UUIDs.startOf(pageLink.getStartTime());
+ lowerBound = criteriaBuilder.greaterThanOrEqualTo(root.get(ID_PROPERTY), startOf);
+ predicates.add(lowerBound);
+ }
+ if (pageLink.getEndTime() != null) {
+ UUID endOf = UUIDs.endOf(pageLink.getEndTime());
+ upperBound = criteriaBuilder.lessThanOrEqualTo(root.get(ID_PROPERTY), endOf);
+ predicates.add(upperBound);
+ }
+ } else {
+ if (pageLink.getIdOffset() != null) {
+ lowerBound = criteriaBuilder.lessThan(root.get(ID_PROPERTY), pageLink.getIdOffset());
+ predicates.add(lowerBound);
+ } else if (pageLink.getEndTime() != null) {
+ UUID endOf = UUIDs.endOf(pageLink.getEndTime());
+ lowerBound = criteriaBuilder.lessThanOrEqualTo(root.get(ID_PROPERTY), endOf);
+ predicates.add(lowerBound);
+ }
+ if (pageLink.getStartTime() != null) {
+ UUID startOf = UUIDs.startOf(pageLink.getStartTime());
+ upperBound = criteriaBuilder.greaterThanOrEqualTo(root.get(ID_PROPERTY), startOf);
+ predicates.add(upperBound);
+ }
+ }
+ return criteriaBuilder.and(predicates.toArray(new Predicate[0]));
+ }
+ };
+ }
+}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java
index 5134ae6..44e43d5 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDao.java
@@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.model.sql.PluginMetaDataEntity;
import org.thingsboard.server.dao.plugin.PluginDao;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
+import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import java.util.Arrays;
import java.util.List;
@@ -40,7 +41,7 @@ import java.util.UUID;
@Slf4j
@Component
@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
-public class JpaBasePluginDao extends JpaAbstractDao<PluginMetaDataEntity, PluginMetaData> implements PluginDao {
+public class JpaBasePluginDao extends JpaAbstractSearchTextDao<PluginMetaDataEntity, PluginMetaData> implements PluginDao {
@Autowired
private PluginMetaDataRepository pluginMetaDataRepository;
@@ -61,11 +62,6 @@ public class JpaBasePluginDao extends JpaAbstractDao<PluginMetaDataEntity, Plugi
}
@Override
- protected boolean isSearchTextDao() {
- return true;
- }
-
- @Override
public PluginMetaData findById(PluginId pluginId) {
log.debug("Search plugin meta-data entity by id [{}]", pluginId);
PluginMetaData pluginMetaData = super.findById(pluginId.getId());
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDao.java
index b2a5d12..b368b3b 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDao.java
@@ -29,6 +29,7 @@ import org.thingsboard.server.dao.model.ModelConstants;
import org.thingsboard.server.dao.model.sql.RuleMetaDataEntity;
import org.thingsboard.server.dao.rule.RuleDao;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
+import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import java.util.Arrays;
import java.util.List;
@@ -40,7 +41,7 @@ import java.util.UUID;
@Slf4j
@Component
@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
-public class JpaBaseRuleDao extends JpaAbstractDao<RuleMetaDataEntity, RuleMetaData> implements RuleDao {
+public class JpaBaseRuleDao extends JpaAbstractSearchTextDao<RuleMetaDataEntity, RuleMetaData> implements RuleDao {
@Autowired
private RuleMetaDataRepository ruleMetaDataRepository;
@@ -60,11 +61,6 @@ public class JpaBaseRuleDao extends JpaAbstractDao<RuleMetaDataEntity, RuleMetaD
}
@Override
- protected boolean isSearchTextDao() {
- return true;
- }
-
- @Override
public RuleMetaData findById(RuleId ruleId) {
return findById(ruleId.getId());
}
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java
index 0f34109..cbe1738 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/tenant/JpaTenantDao.java
@@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.page.TextPageLink;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.TenantEntity;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
+import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import org.thingsboard.server.dao.tenant.TenantDao;
import java.util.List;
@@ -36,7 +37,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.TENANT_COLUMN_FAMI
*/
@Component
@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
-public class JpaTenantDao extends JpaAbstractDao<TenantEntity, Tenant> implements TenantDao {
+public class JpaTenantDao extends JpaAbstractSearchTextDao<TenantEntity, Tenant> implements TenantDao {
@Autowired
private TenantRepository tenantRepository;
@@ -57,11 +58,6 @@ public class JpaTenantDao extends JpaAbstractDao<TenantEntity, Tenant> implement
}
@Override
- protected boolean isSearchTextDao() {
- return true;
- }
-
- @Override
public List<Tenant> findTenantsByRegion(String region, TextPageLink pageLink) {
if (pageLink.getIdOffset() == null) {
return DaoUtil.convertDataList(tenantRepository.findByRegionFirstPage(pageLink.getLimit(), region, pageLink.getTextSearch()));
diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java
index ff40dd2..4288e5a 100644
--- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java
+++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDao.java
@@ -24,6 +24,7 @@ import org.thingsboard.server.common.data.widget.WidgetsBundle;
import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.sql.WidgetsBundleEntity;
import org.thingsboard.server.dao.sql.JpaAbstractDao;
+import org.thingsboard.server.dao.sql.JpaAbstractSearchTextDao;
import org.thingsboard.server.dao.widget.WidgetsBundleDao;
import java.util.List;
@@ -36,7 +37,7 @@ import static org.thingsboard.server.dao.model.ModelConstants.WIDGETS_BUNDLE_COL
*/
@Component
@ConditionalOnProperty(prefix = "sql", value = "enabled", havingValue = "true", matchIfMissing = false)
-public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, WidgetsBundle> implements WidgetsBundleDao {
+public class JpaWidgetsBundleDao extends JpaAbstractSearchTextDao<WidgetsBundleEntity, WidgetsBundle> implements WidgetsBundleDao {
@Autowired
private WidgetsBundleRepository widgetsBundleRepository;
@@ -61,10 +62,6 @@ public class JpaWidgetsBundleDao extends JpaAbstractDao<WidgetsBundleEntity, Wid
return DaoUtil.getData(widgetsBundleRepository.findWidgetsBundleByTenantIdAndAlias(tenantId, alias));
}
- @Override
- protected boolean isSearchTextDao() {
- return true;
- }
@Override
public List<WidgetsBundle> findSystemWidgetsBundles(TextPageLink pageLink) {
diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java
new file mode 100644
index 0000000..cdebadd
--- /dev/null
+++ b/dao/src/test/java/org/thingsboard/server/dao/sql/event/JpaBaseEventDaoTest.java
@@ -0,0 +1,145 @@
+package org.thingsboard.server.dao.sql.event;
+
+import ch.qos.logback.core.net.SyslogOutputStream;
+import com.datastax.driver.core.utils.UUIDs;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.github.springtestdbunit.annotation.DatabaseSetup;
+import lombok.extern.slf4j.Slf4j;
+import org.junit.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.thingsboard.server.common.data.Event;
+import org.thingsboard.server.common.data.id.DeviceId;
+import org.thingsboard.server.common.data.id.EntityId;
+import org.thingsboard.server.common.data.id.EventId;
+import org.thingsboard.server.common.data.id.TenantId;
+import org.thingsboard.server.common.data.page.TimePageLink;
+import org.thingsboard.server.dao.AbstractJpaDaoTest;
+import org.thingsboard.server.dao.event.EventDao;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Optional;
+import java.util.UUID;
+
+import static org.junit.Assert.*;
+import static org.thingsboard.server.common.data.DataConstants.STATS;
+
+/**
+ * Created by Valerii Sosliuk on 5/5/2017.
+ */
+@Slf4j
+public class JpaBaseEventDaoTest extends AbstractJpaDaoTest {
+
+ public static final long HOUR_MILLISECONDS = (long) 3.6e+6;
+ @Autowired
+ private EventDao eventDao;
+
+ @Test
+ @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+ public void testSaveIfNotExists() {
+ UUID eventId = UUIDs.timeBased();
+ UUID tenantId = UUIDs.timeBased();
+ UUID entityId = UUIDs.timeBased();
+ Event event = getEvent(eventId, tenantId, entityId);
+ Optional<Event> optEvent1 = eventDao.saveIfNotExists(event);
+ assertTrue("Optional is expected to be non-empty", optEvent1.isPresent());
+ assertEquals(optEvent1.get(), event);
+ Optional<Event> optEvent2 = eventDao.saveIfNotExists(event);
+ assertFalse("Optional is expected to be empty", optEvent2.isPresent());
+ }
+
+ @Test
+ @DatabaseSetup("classpath:dbunit/events.xml")
+ public void findEvent() {
+ UUID tenantId = UUID.fromString("be41c7a0-31f5-11e7-9cfd-2786e6aa2046");
+ UUID entityId = UUID.fromString("be41c7a1-31f5-11e7-9cfd-2786e6aa2046");
+ String eventType = STATS;
+ String eventUid = "be41c7a3-31f5-11e7-9cfd-2786e6aa2046";
+ Event event = eventDao.findEvent(tenantId, new DeviceId(entityId), eventType, eventUid);
+ assertNotNull("Event expected to be not null", event);
+ assertEquals("be41c7a2-31f5-11e7-9cfd-2786e6aa2046", event.getId().getId().toString());
+ }
+
+ @Test
+ @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+ public void findEventsByEntityIdAndPageLink() {
+ UUID tenantId = UUIDs.timeBased();
+ UUID entityId1 = UUIDs.timeBased();
+ UUID entityId2 = UUIDs.timeBased();
+ long startTime = System.currentTimeMillis();
+ long endTime = createEventsTwoEntities(tenantId, entityId1, entityId2, startTime, 20);
+ List<Event> allEvents = eventDao.find();
+
+ assertEquals(20, allEvents.size());
+
+ TimePageLink pageLink1 = new TimePageLink(30, null, null, true);
+ List<Event> events1 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink1);
+ assertEquals(10, events1.size());
+
+ TimePageLink pageLink2 = new TimePageLink(30, startTime, null, true);
+ List<Event> events2 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink2);
+ assertEquals(10, events2.size());
+
+ TimePageLink pageLink3 = new TimePageLink(30, startTime, endTime, true);
+ List<Event> events3 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink3);
+ assertEquals(10, events3.size());
+
+ TimePageLink pageLink4 = new TimePageLink(5, startTime, endTime, true);
+ List<Event> events4 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink4);
+ assertEquals(5, events4.size());
+
+ UUID idOffset = events4.get(4).getId().getId();
+ TimePageLink pageLink5 = new TimePageLink(10, startTime, endTime, true, idOffset);
+ List<Event> events5 = eventDao.findEvents(tenantId, new DeviceId(entityId1), pageLink5);
+ assertEquals(5, events5.size());
+
+ }
+
+ private long createEventsTwoEntities(UUID tenantId, UUID entityId1, UUID entityId2, long startTime, int count) {
+ // Generate #count events for two entities with timestamps from an hour ago till now
+
+ // Distribute events uniformly
+ long step = HOUR_MILLISECONDS / count;
+ long timestamp = startTime;
+ for (int i = 0; i < count / 2; i++) {
+ //UUID eventId1 = UUIDs.startOf(timestamp);
+ UUID eventId1 = UUIDs.timeBased();
+ Event event1 = getEvent(eventId1, tenantId, entityId1);
+ eventDao.save(event1);
+ timestamp += step;
+ //UUID eventId2 = UUIDs.startOf(timestamp);
+ UUID eventId2 = UUIDs.timeBased();
+ Event event2 = getEvent(eventId2, tenantId, entityId2);
+ eventDao.save(event2);
+ timestamp += step;
+ }
+ return System.currentTimeMillis();
+ }
+
+ @Test
+ @DatabaseSetup("classpath:dbunit/empty_dataset.xml")
+ public void findEventsByEntityIdAndEventTypeAndPageLink() {
+
+ }
+
+ private Event getEvent(UUID eventId, UUID tenantId, UUID entityId) {
+ Event event = new Event();
+ event.setId(new EventId(eventId));
+ event.setTenantId(new TenantId(tenantId));
+ EntityId deviceId = new DeviceId(entityId);
+ event.setEntityId(deviceId);
+ event.setUid(entityId.toString());
+ event.setType(STATS);
+ ObjectMapper mapper = new ObjectMapper();
+ try {
+ JsonNode jsonNode = mapper.readTree("{\"key\":\"value\"}");
+ event.setBody(jsonNode);
+ } catch (IOException e) {
+ log.error(e.getMessage(), e);
+ }
+ return event;
+ }
+}
dao/src/test/resources/dbunit/events.xml 18(+18 -0)
diff --git a/dao/src/test/resources/dbunit/events.xml b/dao/src/test/resources/dbunit/events.xml
new file mode 100644
index 0000000..8f88758
--- /dev/null
+++ b/dao/src/test/resources/dbunit/events.xml
@@ -0,0 +1,18 @@
+<dataset>
+ <event
+ id="uuid'be41c7a2-31f5-11e7-9cfd-2786e6aa2046'"
+ tenant_id="uuid'be41c7a0-31f5-11e7-9cfd-2786e6aa2046'"
+ entity_id="uuid'be41c7a1-31f5-11e7-9cfd-2786e6aa2046'"
+ entity_type="1"
+ event_type="STATS"
+ event_uid="be41c7a3-31f5-11e7-9cfd-2786e6aa2046"
+ />
+ <event
+ id="uuid'be41c7a4-31f5-11e7-9cfd-2786e6aa2046'"
+ tenant_id="uuid'be41c7a0-31f5-11e7-9cfd-2786e6aa2046'"
+ entity_id="uuid'be41c7a1-31f5-11e7-9cfd-2786e6aa2046'"
+ entity_type="1"
+ event_type="STATS"
+ event_uid="be41c7a5-31f5-11e7-9cfd-2786e6aa2046"
+ />
+</dataset>
\ No newline at end of file