From e80cb31a150ed47d9193962091e810c785c675b2 Mon Sep 17 00:00:00 2001 From: mp-loki Date: Sat, 13 May 2017 16:36:05 -0400 Subject: [PATCH] JsonNode values saved to postgres as jsonb type --- dao/pom.xml | 5 - .../dao/model/sql/AdminSettingsEntity.java | 25 ++-- .../model/sql/ComponentDescriptorEntity.java | 25 ++-- .../server/dao/model/sql/CustomerEntity.java | 21 +--- .../server/dao/model/sql/DashboardEntity.java | 27 ++--- .../server/dao/model/sql/DeviceEntity.java | 27 ++--- .../server/dao/model/sql/EventEntity.java | 24 ++-- .../dao/model/sql/PluginMetaDataEntity.java | 45 +++---- .../dao/model/sql/RuleMetaDataEntity.java | 78 ++++-------- .../server/dao/model/sql/TenantEntity.java | 25 ++-- .../server/dao/model/sql/UserEntity.java | 24 ++-- .../dao/model/sql/WidgetTypeEntity.java | 34 ++---- .../server/dao/sql/JpaAbstractDao.java | 3 - .../JpaBaseComponentDescriptorDao.java | 5 - .../dao/sql/customer/CustomerRepository.java | 2 - .../dao/sql/customer/JpaCustomerDao.java | 5 - .../dao/sql/dashboard/JpaDashboardDao.java | 5 - .../sql/dashboard/JpaDashboardInfoDao.java | 5 - .../sql/device/JpaDeviceCredentialsDao.java | 7 -- .../server/dao/sql/device/JpaDeviceDao.java | 5 - .../server/dao/sql/event/JpaBaseEventDao.java | 5 - .../dao/sql/plugin/JpaBasePluginDao.java | 5 - .../server/dao/sql/rule/JpaBaseRuleDao.java | 4 - .../dao/sql/settings/JpaAdminSettingsDao.java | 5 - .../server/dao/sql/tenant/JpaTenantDao.java | 5 - .../dao/sql/user/JpaUserCredentialsDao.java | 5 - .../server/dao/sql/user/JpaUserDao.java | 5 - .../dao/sql/widget/JpaWidgetTypeDao.java | 5 - .../dao/sql/widget/JpaWidgetsBundleDao.java | 5 - .../server/dao/util/JacksonUtil.java | 60 +++++++++ .../dao/util/JsonBinarySqlTypeDescriptor.java | 114 ++++++++++++++++++ .../server/dao/util/JsonBinaryType.java | 44 +++++++ .../server/dao/util/JsonTypeDescriptor.java | 95 +++++++++++++++ .../dao/sql/plugin/JpaBasePluginDaoTest.java | 5 +- .../dao/sql/rule/JpaBaseRuleDaoTest.java | 46 +++++-- .../server/dao/sql/user/JpaUserDaoTest.java | 3 +- .../sql/widget/JpaWidgetsBundleDaoTest.java | 4 +- dao/src/test/resources/dbunit/users.xml | 5 - 38 files changed, 478 insertions(+), 339 deletions(-) create mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/JacksonUtil.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/JsonBinarySqlTypeDescriptor.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/JsonBinaryType.java create mode 100644 dao/src/main/java/org/thingsboard/server/dao/util/JsonTypeDescriptor.java diff --git a/dao/pom.xml b/dao/pom.xml index d95521ddd0..ced5c381f4 100644 --- a/dao/pom.xml +++ b/dao/pom.xml @@ -173,11 +173,6 @@ spring-test test - - org.springframework - spring-test - compile - com.h2database h2 diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java index 25393fb971..27f988a780 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/AdminSettingsEntity.java @@ -25,9 +25,12 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.id.AdminSettingsId; import org.thingsboard.server.dao.model.BaseEntity; +import org.thingsboard.server.dao.util.JsonBinaryType; import java.io.IOException; import java.util.UUID; @@ -35,8 +38,8 @@ import java.util.UUID; import static org.thingsboard.server.dao.model.ModelConstants.*; @Data -@Slf4j @Entity +@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ADMIN_SETTINGS_COLUMN_FAMILY_NAME) public final class AdminSettingsEntity implements BaseEntity { @@ -50,8 +53,9 @@ public final class AdminSettingsEntity implements BaseEntity { @Column(name = ADMIN_SETTINGS_KEY_PROPERTY) private String key; - @Column(name = ADMIN_SETTINGS_JSON_VALUE_PROPERTY) - private String jsonValue; + @Type(type = "jsonb") + @Column(name = ADMIN_SETTINGS_JSON_VALUE_PROPERTY, columnDefinition = "jsonb") + private JsonNode jsonValue; public AdminSettingsEntity() { super(); @@ -62,9 +66,7 @@ public final class AdminSettingsEntity implements BaseEntity { this.id = adminSettings.getId().getId(); } this.key = adminSettings.getKey(); - if (jsonValue != null) { - this.jsonValue = adminSettings.getJsonValue().toString(); - } + this.jsonValue = adminSettings.getJsonValue(); } @Override @@ -132,16 +134,7 @@ public final class AdminSettingsEntity implements BaseEntity { AdminSettings adminSettings = new AdminSettings(new AdminSettingsId(id)); adminSettings.setCreatedTime(UUIDs.unixTimestamp(id)); adminSettings.setKey(key); - if (jsonValue != null) { - ObjectMapper mapper = new ObjectMapper(); - JsonNode jsonNode = null; - try { - jsonNode = mapper.readTree(jsonValue); - adminSettings.setJsonValue(jsonNode); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } + adminSettings.setJsonValue(jsonValue); return adminSettings; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java index 37fab4f487..02cad5d8e6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/ComponentDescriptorEntity.java @@ -24,19 +24,22 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.ComponentDescriptorId; import org.thingsboard.server.common.data.plugin.ComponentDescriptor; import org.thingsboard.server.common.data.plugin.ComponentScope; import org.thingsboard.server.common.data.plugin.ComponentType; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; +import org.thingsboard.server.dao.util.JsonBinaryType; import java.io.IOException; import java.util.UUID; @Data -@Slf4j @Entity +@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ModelConstants.COMPONENT_DESCRIPTOR_COLUMN_FAMILY_NAME) public class ComponentDescriptorEntity implements SearchTextEntity { @@ -59,8 +62,9 @@ public class ComponentDescriptorEntity implements SearchTextEntity { @@ -80,8 +80,9 @@ public final class CustomerEntity implements SearchTextEntity { @Column(name = ModelConstants.EMAIL_PROPERTY) private String email; - @Column(name = ModelConstants.CUSTOMER_ADDITIONAL_INFO_PROPERTY) - private String additionalInfo; + @Type(type = "jsonb") + @Column(name = ModelConstants.CUSTOMER_ADDITIONAL_INFO_PROPERTY, columnDefinition = "jsonb") + private JsonNode additionalInfo; public CustomerEntity() { super(); @@ -101,9 +102,7 @@ public final class CustomerEntity implements SearchTextEntity { this.zip = customer.getZip(); this.phone = customer.getPhone(); this.email = customer.getEmail(); - if (additionalInfo != null) { - this.additionalInfo = customer.getAdditionalInfo().toString(); - } + this.additionalInfo = customer.getAdditionalInfo(); } @Override @@ -262,15 +261,7 @@ public final class CustomerEntity implements SearchTextEntity { customer.setZip(zip); customer.setPhone(phone); customer.setEmail(email); - if (additionalInfo != null) { - ObjectMapper mapper = new ObjectMapper(); - try { - JsonNode jsonNode = mapper.readTree(additionalInfo); - customer.setAdditionalInfo(jsonNode); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } + customer.setAdditionalInfo(additionalInfo); return customer; } } \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java index 1ad0f84633..4cc46f466c 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DashboardEntity.java @@ -25,19 +25,22 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.Dashboard; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DashboardId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; +import org.thingsboard.server.dao.util.JsonBinaryType; import java.io.IOException; import java.util.UUID; @Data -@Slf4j @Entity +@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ModelConstants.DASHBOARD_COLUMN_FAMILY_NAME) public final class DashboardEntity implements SearchTextEntity { @@ -59,9 +62,10 @@ public final class DashboardEntity implements SearchTextEntity { @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) private String searchText; - - @Column(name = ModelConstants.DASHBOARD_CONFIGURATION_PROPERTY) - private String configuration; + + @Type(type = "jsonb") + @Column(name = ModelConstants.DASHBOARD_CONFIGURATION_PROPERTY, columnDefinition = "jsonb") + private JsonNode configuration; public DashboardEntity() { super(); @@ -78,9 +82,7 @@ public final class DashboardEntity implements SearchTextEntity { this.customerId = dashboard.getCustomerId().getId(); } this.title = dashboard.getTitle(); - if (configuration != null) { - this.configuration = dashboard.getConfiguration().toString(); - } + this.configuration = dashboard.getConfiguration(); } @Override @@ -191,16 +193,7 @@ public final class DashboardEntity implements SearchTextEntity { dashboard.setCustomerId(new CustomerId(customerId)); } dashboard.setTitle(title); - if (configuration != null) { - ObjectMapper mapper = new ObjectMapper(); - JsonNode jsonNode = null; - try { - jsonNode = mapper.readTree(configuration); - dashboard.setConfiguration(jsonNode); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } + dashboard.setConfiguration(configuration); return dashboard; } } \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java index 0b1ecdf40c..0504ccf903 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/DeviceEntity.java @@ -25,19 +25,22 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.Device; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.DeviceId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; +import org.thingsboard.server.dao.util.JsonBinaryType; import java.io.IOException; import java.util.UUID; @Data -@Slf4j @Entity +@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ModelConstants.DEVICE_COLUMN_FAMILY_NAME) public final class DeviceEntity implements SearchTextEntity { @@ -59,9 +62,10 @@ public final class DeviceEntity implements SearchTextEntity { @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) private String searchText; - - @Column(name = ModelConstants.DEVICE_ADDITIONAL_INFO_PROPERTY) - private String additionalInfo; + + @Type(type = "jsonb") + @Column(name = ModelConstants.DEVICE_ADDITIONAL_INFO_PROPERTY, columnDefinition = "jsonb") + private JsonNode additionalInfo; public DeviceEntity() { super(); @@ -78,9 +82,7 @@ public final class DeviceEntity implements SearchTextEntity { this.customerId = device.getCustomerId().getId(); } this.name = device.getName(); - if (additionalInfo != null) { - this.additionalInfo = device.getAdditionalInfo().toString(); - } + this.additionalInfo = device.getAdditionalInfo(); } @Override @@ -174,16 +176,7 @@ public final class DeviceEntity implements SearchTextEntity { device.setCustomerId(new CustomerId(customerId)); } device.setName(name); - if (additionalInfo != null) { - ObjectMapper mapper = new ObjectMapper(); - JsonNode jsonNode = null; - try { - jsonNode = mapper.readTree(additionalInfo); - device.setAdditionalInfo(jsonNode); - } catch (IOException e) { - log.error(e.getMessage(), e); - } - } + device.setAdditionalInfo(additionalInfo); return device; } } \ No newline at end of file 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 a0cce5ca22..65e51a0879 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 @@ -26,10 +26,13 @@ import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.NoArgsConstructor; import lombok.extern.slf4j.Slf4j; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; 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.util.JsonBinaryType; import static org.thingsboard.server.dao.model.ModelConstants.*; @@ -37,9 +40,9 @@ import java.io.IOException; import java.util.UUID; @Data -@Slf4j @NoArgsConstructor @Entity +@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = EVENT_COLUMN_FAMILY_NAME) public class EventEntity implements BaseEntity { @@ -65,8 +68,9 @@ public class EventEntity implements BaseEntity { @Column(name = EVENT_UID_PROPERTY) private String eventUid; - @Column(name = EVENT_BODY_PROPERTY) - private String body; + @Type(type = "jsonb") + @Column(name = EVENT_BODY_PROPERTY, columnDefinition = "jsonb") + private JsonNode body; public EventEntity(Event event) { if (event.getId() != null) { @@ -81,9 +85,7 @@ public class EventEntity implements BaseEntity { } this.eventType = event.getType(); this.eventUid = event.getUid(); - if (event.getBody() != null) { - this.body = event.getBody().toString(); - } + this.body = event.getBody(); } @Override @@ -118,15 +120,7 @@ public class EventEntity implements BaseEntity { event.setEntityId(new PluginId(entityId)); break; } - 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.setBody(body); event.setType(eventType); event.setUid(eventUid); return event; diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java index 1e5d1b09a1..8d8974dcf8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/PluginMetaDataEntity.java @@ -25,19 +25,23 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.PluginId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; import org.thingsboard.server.common.data.plugin.PluginMetaData; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; +import org.thingsboard.server.dao.util.JsonBinaryType; import java.io.IOException; import java.util.Objects; import java.util.UUID; -@Slf4j + @Data @Entity +@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ModelConstants.PLUGIN_COLUMN_FAMILY_NAME) public class PluginMetaDataEntity implements SearchTextEntity { @@ -65,15 +69,17 @@ public class PluginMetaDataEntity implements SearchTextEntity { @Column(name = ModelConstants.PLUGIN_STATE_PROPERTY) private ComponentLifecycleState state; - @Column(name = ModelConstants.PLUGIN_CONFIGURATION_PROPERTY) - private String configuration; + @Type(type = "jsonb") + @Column(name = ModelConstants.PLUGIN_CONFIGURATION_PROPERTY, columnDefinition = "jsonb") + private JsonNode configuration; + + @Type(type = "jsonb") + @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY, columnDefinition = "jsonb") + private JsonNode additionalInfo; @Column(name = ModelConstants.SEARCH_TEXT_PROPERTY) private String searchText; - @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY) - private String additionalInfo; - public PluginMetaDataEntity() { } @@ -88,12 +94,8 @@ public class PluginMetaDataEntity implements SearchTextEntity { this.publicAccess = pluginMetaData.isPublicAccess(); this.state = pluginMetaData.getState(); this.searchText = pluginMetaData.getName(); - if (pluginMetaData.getConfiguration() != null) { - this.configuration = pluginMetaData.getConfiguration().toString(); - } - if (pluginMetaData.getAdditionalInfo() != null) { - this.additionalInfo = pluginMetaData.getAdditionalInfo().toString(); - } + this.configuration = pluginMetaData.getConfiguration(); + this.additionalInfo = pluginMetaData.getAdditionalInfo(); } @Override @@ -126,23 +128,8 @@ public class PluginMetaDataEntity implements SearchTextEntity { data.setPublicAccess(publicAccess); data.setState(state); data.setApiToken(apiToken); - ObjectMapper mapper = new ObjectMapper(); - if (configuration != null) { - try { - JsonNode jsonNode = mapper.readTree(configuration); - data.setConfiguration(jsonNode); - } catch (IOException e) { - log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", configuration, e.getMessage()), e); - } - } - if (additionalInfo != null) { - try { - JsonNode jsonNode = mapper.readTree(additionalInfo); - data.setAdditionalInfo(jsonNode); - } catch (IOException e) { - log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", additionalInfo, e.getMessage()), e); - } - } + data.setConfiguration(configuration); + data.setAdditionalInfo(additionalInfo); return data; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java index 54359a35aa..193501a981 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/RuleMetaDataEntity.java @@ -27,6 +27,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.RuleId; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.plugin.ComponentLifecycleState; @@ -34,14 +36,15 @@ import org.thingsboard.server.common.data.rule.RuleMetaData; import org.thingsboard.server.dao.DaoUtil; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; +import org.thingsboard.server.dao.util.JsonBinaryType; import java.io.IOException; import java.util.Objects; import java.util.UUID; -@Slf4j @Data @Entity +@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ModelConstants.RULE_COLUMN_FAMILY_NAME) public class RuleMetaDataEntity implements SearchTextEntity { @@ -62,14 +65,18 @@ public class RuleMetaDataEntity implements SearchTextEntity { private String searchText; @Column(name = ModelConstants.RULE_PLUGIN_TOKEN_PROPERTY) private String pluginToken; - @Column(name = ModelConstants.RULE_FILTERS) - private String filters; - @Column(name = ModelConstants.RULE_PROCESSOR) - private String processor; - @Column(name = ModelConstants.RULE_ACTION) - private String action; - @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY) - private String additionalInfo; + @Type(type = "jsonb") + @Column(name = ModelConstants.RULE_FILTERS, columnDefinition = "jsonb") + private JsonNode filters; + @Type(type = "jsonb") + @Column(name = ModelConstants.RULE_PROCESSOR, columnDefinition = "jsonb") + private JsonNode processor; + @Type(type = "jsonb") + @Column(name = ModelConstants.RULE_ACTION, columnDefinition = "jsonb") + private JsonNode action; + @Type(type = "jsonb") + @Column(name = ModelConstants.ADDITIONAL_INFO_PROPERTY, columnDefinition = "jsonb") + private JsonNode additionalInfo; public RuleMetaDataEntity() { } @@ -84,18 +91,10 @@ public class RuleMetaDataEntity implements SearchTextEntity { this.state = rule.getState(); this.weight = rule.getWeight(); this.searchText = rule.getName(); - if (rule.getFilters() != null) { - this.filters = rule.getFilters().toString(); - } - if (rule.getProcessor() != null) { - this.processor = rule.getProcessor().toString(); - } - if (rule.getAction() != null) { - this.action = rule.getAction().toString(); - } - if (rule.getAdditionalInfo() != null) { - this.additionalInfo = rule.getAdditionalInfo().toString(); - } + this.filters = rule.getFilters(); + this.processor = rule.getProcessor(); + this.action = rule.getAction(); + this.additionalInfo = rule.getAdditionalInfo(); } @Override @@ -127,39 +126,10 @@ public class RuleMetaDataEntity implements SearchTextEntity { rule.setWeight(weight); rule.setCreatedTime(UUIDs.unixTimestamp(id)); rule.setPluginToken(pluginToken); - ObjectMapper mapper = new ObjectMapper(); - if (filters != null) { - try { - JsonNode jsonNode = mapper.readTree(filters); - rule.setFilters(jsonNode); - } catch (IOException e) { - log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", filters, e.getMessage()), e); - } - } - if (processor != null) { - try { - JsonNode jsonNode = mapper.readTree(processor); - rule.setProcessor(jsonNode); - } catch (IOException e) { - log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", processor, e.getMessage()), e); - } - } - if (action != null) { - try { - JsonNode jsonNode = mapper.readTree(action); - rule.setAction(jsonNode); - } catch (IOException e) { - log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", action, e.getMessage()), e); - } - } - if (additionalInfo != null) { - try { - JsonNode jsonNode = mapper.readTree(additionalInfo); - rule.setAdditionalInfo(jsonNode); - } catch (IOException e) { - log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", additionalInfo, e.getMessage()), e); - } - } + rule.setFilters(filters); + rule.setProcessor(processor); + rule.setAction(action); + rule.setAdditionalInfo(additionalInfo); return rule; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java index 6a2e8a066b..fcd5b19f63 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/TenantEntity.java @@ -26,18 +26,21 @@ import javax.persistence.Transient; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.Tenant; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; import com.fasterxml.jackson.databind.JsonNode; +import org.thingsboard.server.dao.util.JsonBinaryType; import java.io.IOException; import java.util.UUID; -@Slf4j @Data @Entity +@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ModelConstants.TENANT_COLUMN_FAMILY_NAME) public final class TenantEntity implements SearchTextEntity { @@ -81,8 +84,9 @@ public final class TenantEntity implements SearchTextEntity { @Column(name = ModelConstants.EMAIL_PROPERTY) private String email; - @Column(name = ModelConstants.TENANT_ADDITIONAL_INFO_PROPERTY) - private String additionalInfo; + @Type(type="jsonb") + @Column(name = ModelConstants.TENANT_ADDITIONAL_INFO_PROPERTY, columnDefinition = "jsonb") + private JsonNode additionalInfo; public TenantEntity() { super(); @@ -102,12 +106,9 @@ public final class TenantEntity implements SearchTextEntity { this.zip = tenant.getZip(); this.phone = tenant.getPhone(); this.email = tenant.getEmail(); - if (tenant.getAdditionalInfo() != null) { - this.additionalInfo = tenant.getAdditionalInfo().toString(); - } + this.additionalInfo = tenant.getAdditionalInfo(); } - @Override public String getSearchTextSource() { return title; @@ -258,15 +259,7 @@ public final class TenantEntity implements SearchTextEntity { tenant.setZip(zip); tenant.setPhone(phone); tenant.setEmail(email); - ObjectMapper mapper = new ObjectMapper(); - if (additionalInfo != null) { - try { - JsonNode jsonNode = mapper.readTree(additionalInfo); - tenant.setAdditionalInfo(jsonNode); - } catch (IOException e) { - log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", additionalInfo, e.getMessage()), e); - } - } + tenant.setAdditionalInfo(additionalInfo); return tenant; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java index c85b2aa9d9..6572462df0 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/UserEntity.java @@ -20,6 +20,8 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; import lombok.extern.slf4j.Slf4j; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.User; import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.TenantId; @@ -27,6 +29,7 @@ import org.thingsboard.server.common.data.id.UserId; import org.thingsboard.server.common.data.security.Authority; import org.thingsboard.server.dao.model.ModelConstants; import org.thingsboard.server.dao.model.SearchTextEntity; +import org.thingsboard.server.dao.util.JsonBinaryType; import javax.persistence.*; import java.io.IOException; @@ -35,9 +38,9 @@ import java.util.UUID; /** * Created by Valerii Sosliuk on 4/21/2017. */ -@Slf4j @Data @Entity +@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ModelConstants.USER_PG_HIBERNATE_COLUMN_FAMILY_NAME) public class UserEntity implements SearchTextEntity { @Transient @@ -68,8 +71,9 @@ public class UserEntity implements SearchTextEntity { @Column(name = ModelConstants.USER_LAST_NAME_PROPERTY) private String lastName; - @Column(name = ModelConstants.USER_ADDITIONAL_INFO_PROPERTY) - private String additionalInfo; + @Type(type="jsonb") + @Column(name = ModelConstants.USER_ADDITIONAL_INFO_PROPERTY, columnDefinition = "jsonb") + private JsonNode additionalInfo; public UserEntity() { } @@ -88,9 +92,7 @@ public class UserEntity implements SearchTextEntity { this.email = user.getEmail(); this.firstName = user.getFirstName(); this.lastName = user.getLastName(); - if (user.getAdditionalInfo() != null) { - this.additionalInfo = user.getAdditionalInfo().toString(); - } + this.additionalInfo = user.getAdditionalInfo(); } @Override @@ -150,15 +152,7 @@ public class UserEntity implements SearchTextEntity { user.setEmail(email); user.setFirstName(firstName); user.setLastName(lastName); - ObjectMapper mapper = new ObjectMapper(); - if (additionalInfo != null) { - try { - JsonNode jsonNode = mapper.readTree(additionalInfo); - user.setAdditionalInfo(jsonNode); - } catch (IOException e) { - log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", additionalInfo, e.getMessage()), e); - } - } + user.setAdditionalInfo(additionalInfo); return user; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java index 4f31e70201..28de47ffc6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java +++ b/dao/src/main/java/org/thingsboard/server/dao/model/sql/WidgetTypeEntity.java @@ -16,29 +16,24 @@ package org.thingsboard.server.dao.model.sql; import com.datastax.driver.core.utils.UUIDs; -import javax.persistence.Column; -import javax.persistence.Entity; -import javax.persistence.Id; -import javax.persistence.Table; -import javax.persistence.Transient; - import com.datastax.driver.mapping.annotations.PartitionKey; import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; import lombok.Data; -import lombok.extern.slf4j.Slf4j; +import org.hibernate.annotations.Type; +import org.hibernate.annotations.TypeDef; import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.WidgetTypeId; import org.thingsboard.server.common.data.widget.WidgetType; import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.ModelConstants; +import org.thingsboard.server.dao.util.JsonBinaryType; -import java.io.IOException; +import javax.persistence.*; import java.util.UUID; -@Slf4j @Data @Entity +@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class) @Table(name = ModelConstants.WIDGET_TYPE_COLUMN_FAMILY_NAME) public final class WidgetTypeEntity implements BaseEntity { @@ -63,8 +58,9 @@ public final class WidgetTypeEntity implements BaseEntity { @Column(name = ModelConstants.WIDGET_TYPE_NAME_PROPERTY) private String name; - @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY) - private String descriptor; + @Type(type="jsonb") + @Column(name = ModelConstants.WIDGET_TYPE_DESCRIPTOR_PROPERTY, columnDefinition = "jsonb") + private JsonNode descriptor; public WidgetTypeEntity() { super(); @@ -80,9 +76,7 @@ public final class WidgetTypeEntity implements BaseEntity { this.bundleAlias = widgetType.getBundleAlias(); this.alias = widgetType.getAlias(); this.name = widgetType.getName(); - if (widgetType.getDescriptor() != null) { - this.descriptor = widgetType.getDescriptor().toString(); - } + this.descriptor = widgetType.getDescriptor(); } @Override @@ -144,15 +138,7 @@ public final class WidgetTypeEntity implements BaseEntity { widgetType.setBundleAlias(bundleAlias); widgetType.setAlias(alias); widgetType.setName(name); - ObjectMapper mapper = new ObjectMapper(); - if (descriptor != null) { - try { - JsonNode jsonNode = mapper.readTree(descriptor); - widgetType.setDescriptor(jsonNode); - } catch (IOException e) { - log.warn(String.format("Error parsing JsonNode: %s. Reason: %s ", descriptor, e.getMessage()), e); - } - } + widgetType.setDescriptor(descriptor); return widgetType; } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java index 0d04577221..8d0100d9ad 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/JpaAbstractDao.java @@ -41,8 +41,6 @@ public abstract class JpaAbstractDao, D> implements Dao< protected abstract Class getEntityClass(); - protected abstract String getColumnFamilyName(); - protected abstract CrudRepository getCrudRepository(); protected boolean isSearchTextDao() { @@ -93,7 +91,6 @@ public abstract class JpaAbstractDao, D> implements Dao< @Override public List find() { - log.debug("Get all entities from column family {}", getColumnFamilyName()); List entities = Lists.newArrayList(getCrudRepository().findAll()); return DaoUtil.convertDataList(entities); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java index 440cce02f6..596d142dd9 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/component/JpaBaseComponentDescriptorDao.java @@ -50,11 +50,6 @@ public class JpaBaseComponentDescriptorDao extends JpaAbstractSearchTextDao getCrudRepository() { return componentDescriptorRepository; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java index 5687ebbc99..b26be064f6 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/CustomerRepository.java @@ -40,6 +40,4 @@ public interface CustomerRepository extends CrudRepository "AND ID > ?4 ORDER BY ID LIMIT ?1") List findByTenantIdNextPage(int limit, UUID tenantId, String textSearch, UUID idOffset); - @Query(nativeQuery = true, value = "SELECT * FROM CUSTOMER WHERE TENANT_ID = ?1") - List findByTenantId(UUID tenantId); } diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java index 07d7fc9c1b..3dfaccdec8 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/customer/JpaCustomerDao.java @@ -45,11 +45,6 @@ public class JpaCustomerDao extends JpaAbstractSearchTextDao getCrudRepository() { return customerRepository; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardDao.java index 5d0c7bb86f..5f14110af4 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardDao.java @@ -43,11 +43,6 @@ public class JpaDashboardDao extends JpaAbstractSearchTextDao getCrudRepository() { return dashboardRepository; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java index 698cb31684..81f73092d5 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/dashboard/JpaDashboardInfoDao.java @@ -46,11 +46,6 @@ public class JpaDashboardInfoDao extends JpaAbstractSearchTextDao getCrudRepository() { return deviceCredentialsRepository; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java index 730eb8bd13..c9b9c75d89 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/device/JpaDeviceDao.java @@ -51,11 +51,6 @@ public class JpaDeviceDao extends JpaAbstractSearchTextDao return DeviceEntity.class; } - @Override - protected String getColumnFamilyName() { - return DEVICE_COLUMN_FAMILY_NAME; - } - @Override protected CrudRepository getCrudRepository() { return deviceRepository; 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 index 9dd6070e1c..efe5908f43 100644 --- 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 @@ -66,11 +66,6 @@ public class JpaBaseEventDao extends JpaAbstractSearchTimeDao getCrudRepository() { return eventRepository; 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 44e43d5e03..b4ad114a41 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 @@ -51,11 +51,6 @@ public class JpaBasePluginDao extends JpaAbstractSearchTextDao getCrudRepository() { return pluginMetaDataRepository; 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 b368b3bf9c..b5e6bf556d 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 @@ -50,10 +50,6 @@ public class JpaBaseRuleDao extends JpaAbstractSearchTextDao getEntityClass() { return RuleMetaDataEntity.class; } - @Override - protected String getColumnFamilyName() { - return ModelConstants.RULE_COLUMN_FAMILY_NAME; - } @Override protected CrudRepository getCrudRepository() { diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/settings/JpaAdminSettingsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/settings/JpaAdminSettingsDao.java index 7373cd8140..b1e2326f41 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/settings/JpaAdminSettingsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/settings/JpaAdminSettingsDao.java @@ -40,11 +40,6 @@ public class JpaAdminSettingsDao extends JpaAbstractDao getCrudRepository() { return adminSettingsRepository; 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 cbe173831d..f2feef25f5 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 @@ -47,11 +47,6 @@ public class JpaTenantDao extends JpaAbstractSearchTextDao return TenantEntity.class; } - @Override - protected String getColumnFamilyName() { - return TENANT_COLUMN_FAMILY_NAME; - } - @Override protected CrudRepository getCrudRepository() { return tenantRepository; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDao.java index fa119b679f..828909cca2 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserCredentialsDao.java @@ -44,11 +44,6 @@ public class JpaUserCredentialsDao extends JpaAbstractDao getCrudRepository() { return userCredentialsRepository; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java index 3008f59016..1a3c6eaf2d 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/user/JpaUserDao.java @@ -45,11 +45,6 @@ public class JpaUserDao extends JpaAbstractDao implements User return UserEntity.class; } - @Override - protected String getColumnFamilyName() { - return ModelConstants.USER_COLUMN_FAMILY_NAME; - } - @Override protected CrudRepository getCrudRepository() { return userRepository; diff --git a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java index 2146a8ff11..58f9346239 100644 --- a/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java +++ b/dao/src/main/java/org/thingsboard/server/dao/sql/widget/JpaWidgetTypeDao.java @@ -45,11 +45,6 @@ public class JpaWidgetTypeDao extends JpaAbstractDao getCrudRepository() { return widgetTypeRepository; 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 4288e5ab74..b2f0de6b1f 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 @@ -47,11 +47,6 @@ public class JpaWidgetsBundleDao extends JpaAbstractSearchTextDao getCrudRepository() { return widgetsBundleRepository; diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/JacksonUtil.java b/dao/src/main/java/org/thingsboard/server/dao/util/JacksonUtil.java new file mode 100644 index 0000000000..5b1f5455ce --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/util/JacksonUtil.java @@ -0,0 +1,60 @@ +/** + * 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.dao.util; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; + +/** + * Created by Valerii Sosliuk on 5/12/2017. + */ +public class JacksonUtil { + + public static final ObjectMapper OBJECT_MAPPER = new ObjectMapper(); + + public static T fromString(String string, Class clazz) { + try { + return OBJECT_MAPPER.readValue(string, clazz); + } catch (IOException e) { + throw new IllegalArgumentException("The given string value: " + + string + " cannot be transformed to Json object"); + } + } + + public static String toString(Object value) { + try { + return OBJECT_MAPPER.writeValueAsString(value); + } catch (JsonProcessingException e) { + throw new IllegalArgumentException("The given Json object value: " + + value + " cannot be transformed to a String"); + } + } + + public static JsonNode toJsonNode(String value) { + try { + return OBJECT_MAPPER.readTree(value); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + + public static T clone(T value) { + return fromString(toString(value), (Class) value.getClass()); + } +} \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/JsonBinarySqlTypeDescriptor.java b/dao/src/main/java/org/thingsboard/server/dao/util/JsonBinarySqlTypeDescriptor.java new file mode 100644 index 0000000000..77c768712e --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/util/JsonBinarySqlTypeDescriptor.java @@ -0,0 +1,114 @@ +/** + * 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.dao.util; + +import com.fasterxml.jackson.databind.JsonNode; +import org.hibernate.type.descriptor.ValueBinder; +import org.hibernate.type.descriptor.ValueExtractor; +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.JavaTypeDescriptor; +import org.hibernate.type.descriptor.sql.BasicBinder; +import org.hibernate.type.descriptor.sql.BasicExtractor; +import org.hibernate.type.descriptor.sql.SqlTypeDescriptor; + +import java.sql.*; + +/** + * Created by Valerii Sosliuk on 5/12/2017. + */ +public class JsonBinarySqlTypeDescriptor + implements SqlTypeDescriptor { + + public static final JsonBinarySqlTypeDescriptor INSTANCE = + new JsonBinarySqlTypeDescriptor(); + + @Override + public int getSqlType() { + return Types.OTHER; + } + + @Override + public boolean canBeRemapped() { + return true; + } + + @Override + public ValueExtractor getExtractor( + final JavaTypeDescriptor javaTypeDescriptor) { + return new BasicExtractor(javaTypeDescriptor, this) { + @Override + protected X doExtract( + ResultSet rs, + String name, + WrapperOptions options) throws SQLException { + return javaTypeDescriptor.wrap( + rs.getObject(name), options + ); + } + + @Override + protected X doExtract( + CallableStatement statement, + int index, + WrapperOptions options) throws SQLException { + return javaTypeDescriptor.wrap( + statement.getObject(index), options + ); + } + + @Override + protected X doExtract( + CallableStatement statement, + String name, + WrapperOptions options) throws SQLException { + return javaTypeDescriptor.wrap( + statement.getObject(name), options + ); + } + }; + } + + @Override + public ValueBinder getBinder( + final JavaTypeDescriptor javaTypeDescriptor) { + return new BasicBinder(javaTypeDescriptor, this) { + @Override + protected void doBind( + PreparedStatement st, + X value, + int index, + WrapperOptions options) throws SQLException { + st.setObject(index, + javaTypeDescriptor.unwrap( + value, JsonNode.class, options), getSqlType() + ); + } + + @Override + protected void doBind( + CallableStatement st, + X value, + String name, + WrapperOptions options) + throws SQLException { + st.setObject(name, + javaTypeDescriptor.unwrap( + value, JsonNode.class, options), getSqlType() + ); + } + }; + } +} \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/JsonBinaryType.java b/dao/src/main/java/org/thingsboard/server/dao/util/JsonBinaryType.java new file mode 100644 index 0000000000..96a49c9a39 --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/util/JsonBinaryType.java @@ -0,0 +1,44 @@ +/** + * 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.dao.util; + +import org.hibernate.type.AbstractSingleColumnStandardBasicType; +import org.hibernate.usertype.DynamicParameterizedType; + +import java.util.Properties; + +/** + * Created by Valerii Sosliuk on 5/12/2017. + */ +public class JsonBinaryType extends AbstractSingleColumnStandardBasicType + implements DynamicParameterizedType { + + public JsonBinaryType() { + super( + JsonBinarySqlTypeDescriptor.INSTANCE, + new JsonTypeDescriptor() + ); + } + + public String getName() { + return "jsonb"; + } + + @Override + public void setParameterValues(Properties parameters) { + ((JsonTypeDescriptor) getJavaTypeDescriptor()) + .setParameterValues(parameters); + }} \ No newline at end of file diff --git a/dao/src/main/java/org/thingsboard/server/dao/util/JsonTypeDescriptor.java b/dao/src/main/java/org/thingsboard/server/dao/util/JsonTypeDescriptor.java new file mode 100644 index 0000000000..aeca9297ad --- /dev/null +++ b/dao/src/main/java/org/thingsboard/server/dao/util/JsonTypeDescriptor.java @@ -0,0 +1,95 @@ +/** + * 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.dao.util; + +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.AbstractTypeDescriptor; +import org.hibernate.type.descriptor.java.MutableMutabilityPlan; +import org.hibernate.usertype.DynamicParameterizedType; + +import java.util.Properties; + +/** + * Created by Valerii Sosliuk on 5/12/2017. + */ +public class JsonTypeDescriptor + extends AbstractTypeDescriptor + implements DynamicParameterizedType { + + private Class jsonObjectClass; + + @Override + public void setParameterValues(Properties parameters) { + jsonObjectClass = ( (ParameterType) parameters.get( PARAMETER_TYPE ) ) + .getReturnedClass(); + + } + + public JsonTypeDescriptor() { + super( Object.class, new MutableMutabilityPlan() { + @Override + protected Object deepCopyNotNull(Object value) { + return JacksonUtil.clone(value); + } + }); + } + + @Override + public boolean areEqual(Object one, Object another) { + if ( one == another ) { + return true; + } + if ( one == null || another == null ) { + return false; + } + return JacksonUtil.toJsonNode(JacksonUtil.toString(one)).equals( + JacksonUtil.toJsonNode(JacksonUtil.toString(another))); + } + + @Override + public String toString(Object value) { + return JacksonUtil.toString(value); + } + + @Override + public Object fromString(String string) { + return JacksonUtil.fromString(string, jsonObjectClass); + } + + @SuppressWarnings({ "unchecked" }) + @Override + public X unwrap(Object value, Class type, WrapperOptions options) { + if ( value == null ) { + return null; + } + if ( String.class.isAssignableFrom( type ) ) { + return (X) toString(value); + } + if ( Object.class.isAssignableFrom( type ) ) { + return (X) JacksonUtil.toJsonNode(toString(value)); + } + throw unknownUnwrap( type ); + } + + @Override + public Object wrap(X value, WrapperOptions options) { + if ( value == null ) { + return null; + } + return fromString(value.toString()); + } + +} \ No newline at end of file diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java index 31a6c58376..542f26fa16 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/plugin/JpaBasePluginDaoTest.java @@ -16,7 +16,9 @@ package org.thingsboard.server.dao.sql.plugin; import com.datastax.driver.core.utils.UUIDs; +import com.github.springtestdbunit.annotation.DatabaseOperation; import com.github.springtestdbunit.annotation.DatabaseSetup; +import com.github.springtestdbunit.annotation.DatabaseTearDown; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; import org.thingsboard.server.common.data.id.PluginId; @@ -45,7 +47,6 @@ public class JpaBasePluginDaoTest extends AbstractJpaDaoTest { UUID tenantId1 = UUIDs.timeBased(); UUID tenantId2 = UUIDs.timeBased(); createPluginsTwoTenants(tenantId1, tenantId2, "plugin_"); - assertEquals(60, pluginDao.find().size()); List rules1 = pluginDao.findByTenantIdAndPageLink( new TenantId(tenantId1), new TextPageLink(20, "plugin_")); assertEquals(20, rules1.size()); @@ -60,7 +61,7 @@ public class JpaBasePluginDaoTest extends AbstractJpaDaoTest { } @Test - @DatabaseSetup("classpath:dbunit/empty_dataset.xml") + @DatabaseSetup(value = "classpath:dbunit/empty_dataset.xml") public void testFindAllTenantRulesByTenantId() { UUID tenantId1 = UUIDs.timeBased(); UUID tenantId2 = UUIDs.timeBased(); diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDaoTest.java index 9e2141db8e..7779652492 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/rule/JpaBaseRuleDaoTest.java @@ -16,6 +16,7 @@ package org.thingsboard.server.dao.sql.rule; import com.datastax.driver.core.utils.UUIDs; +import com.fasterxml.jackson.databind.ObjectMapper; import com.github.springtestdbunit.annotation.DatabaseSetup; import org.junit.Test; import org.springframework.beans.factory.annotation.Autowired; @@ -26,6 +27,7 @@ import org.thingsboard.server.common.data.rule.RuleMetaData; import org.thingsboard.server.dao.AbstractJpaDaoTest; import org.thingsboard.server.dao.rule.RuleDao; +import java.io.IOException; import java.util.List; import java.util.UUID; @@ -38,12 +40,38 @@ import static org.junit.Assert.assertNotNull; public class JpaBaseRuleDaoTest extends AbstractJpaDaoTest { @Autowired - private RuleDao jpaBaseRuleDao; + private RuleDao ruleDao; + + @Test + @DatabaseSetup("classpath:dbunit/empty_dataset.xml") + public void testSave() throws IOException { + UUID id = UUIDs.timeBased(); + RuleMetaData ruleMetaData = new RuleMetaData(); + ruleMetaData.setId(new RuleId(id)); + ruleMetaData.setTenantId(new TenantId(UUIDs.timeBased())); + ruleMetaData.setName("test"); + String filters = "{\"filters\":\"value-1\"}"; + String processor = "{\"processor\":\"value-2\"}"; + String action = "{\"action\":\"value-3\"}"; + String additionalInfo = "{\"additionalInfo\":\"value-4\"}"; + ObjectMapper mapper = new ObjectMapper(); + ruleMetaData.setFilters(mapper.readTree(filters)); + ruleMetaData.setProcessor(mapper.readTree(processor)); + ruleMetaData.setAction(mapper.readTree(action)); + ruleMetaData.setAdditionalInfo(mapper.readTree(additionalInfo)); + ruleDao.save(ruleMetaData); + RuleMetaData savedRule = ruleDao.findById(id); + assertNotNull(savedRule); + assertEquals(filters, savedRule.getFilters().toString()); + assertEquals(processor, savedRule.getProcessor().toString()); + assertEquals(action, savedRule.getAction().toString()); + assertEquals(additionalInfo, savedRule.getAdditionalInfo().toString()); + } @Test @DatabaseSetup("classpath:dbunit/rule.xml") public void testFindRulesByPlugin() { - assertEquals(3, jpaBaseRuleDao.findRulesByPlugin("token_1").size()); + assertEquals(3, ruleDao.findRulesByPlugin("token_1").size()); } @Test @@ -52,15 +80,15 @@ public class JpaBaseRuleDaoTest extends AbstractJpaDaoTest { UUID tenantId1 = UUIDs.timeBased(); UUID tenantId2 = UUIDs.timeBased(); createRulesTwoTenants(tenantId1, tenantId2, "name_", "token"); - List rules1 = jpaBaseRuleDao.findByTenantIdAndPageLink( + List rules1 = ruleDao.findByTenantIdAndPageLink( new TenantId(tenantId1), new TextPageLink(20, "name_")); assertEquals(20, rules1.size()); - List rules2 = jpaBaseRuleDao.findByTenantIdAndPageLink(new TenantId(tenantId1), + List rules2 = ruleDao.findByTenantIdAndPageLink(new TenantId(tenantId1), new TextPageLink(20, "name_", rules1.get(19).getId().getId(), null)); assertEquals(10, rules2.size()); - List rules3 = jpaBaseRuleDao.findByTenantIdAndPageLink(new TenantId(tenantId1), + List rules3 = ruleDao.findByTenantIdAndPageLink(new TenantId(tenantId1), new TextPageLink(20, "name_", rules2.get(9).getId().getId(), null)); assertEquals(0, rules3.size()); } @@ -71,15 +99,15 @@ public class JpaBaseRuleDaoTest extends AbstractJpaDaoTest { UUID tenantId1 = UUIDs.timeBased(); UUID tenantId2 = UUIDs.timeBased(); createTenantsAndSystemRules(tenantId1, tenantId2, "name_", "token"); - List rules1 = jpaBaseRuleDao.findAllTenantRulesByTenantId( + List rules1 = ruleDao.findAllTenantRulesByTenantId( tenantId1, new TextPageLink(40, "name_")); assertEquals(40, rules1.size()); - List rules2 = jpaBaseRuleDao.findAllTenantRulesByTenantId(tenantId1, + List rules2 = ruleDao.findAllTenantRulesByTenantId(tenantId1, new TextPageLink(40, "name_", rules1.get(39).getId().getId(), null)); assertEquals(20, rules2.size()); - List rules3 = jpaBaseRuleDao.findAllTenantRulesByTenantId(tenantId1, + List rules3 = ruleDao.findAllTenantRulesByTenantId(tenantId1, new TextPageLink(40, "name_", rules2.get(19).getId().getId(), null)); assertEquals(0, rules3.size()); } @@ -105,6 +133,6 @@ public class JpaBaseRuleDaoTest extends AbstractJpaDaoTest { ruleMetaData.setTenantId(new TenantId(tenantId)); ruleMetaData.setName(namePrefix + i); ruleMetaData.setPluginToken(pluginToken); - jpaBaseRuleDao.save(ruleMetaData); + ruleDao.save(ruleMetaData); } } diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java index 9d719ba4bd..17463baf28 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/user/JpaUserDaoTest.java @@ -62,7 +62,6 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest { assertEquals(Authority.SYS_ADMIN, user.getAuthority()); assertEquals("John", user.getFirstName()); assertEquals("Doe", user.getLastName()); - assertEquals("{\"key\":\"value-0\"}", user.getAdditionalInfo().toString()); } @Test @@ -114,7 +113,9 @@ public class JpaUserDaoTest extends AbstractJpaDaoTest { userDao.save(user); assertEquals(6, userDao.find().size()); User savedUser = userDao.findByEmail("user@thingsboard.org"); + //User savedUser = userDao.findById(UUID.fromString("cd481534-27cc-11e7-93ae-92361f002671")); assertNotNull(savedUser); + assertEquals(additionalInfo, savedUser.getAdditionalInfo().toString()); } private void create30Adminsand60Users(UUID tenantId, UUID customerId) { diff --git a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDaoTest.java b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDaoTest.java index 7c1df06203..9733d4bb7f 100644 --- a/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDaoTest.java +++ b/dao/src/test/java/org/thingsboard/server/dao/sql/widget/JpaWidgetsBundleDaoTest.java @@ -137,12 +137,12 @@ public class JpaWidgetsBundleDaoTest extends AbstractJpaDaoTest { @Test @DatabaseSetup("classpath:dbunit/empty_dataset.xml") @DatabaseTearDown(value = "classpath:dbunit/empty_dataset.xml", type= DatabaseOperation.DELETE_ALL) - public void testNonSearchTextNotFound() { + public void testSearchTextNotFound() { UUID tenantId = UUIDs.timeBased(); createWidgetBundles(5, tenantId, "ABC_"); createSystemWidgetBundles(5, "SYS_"); - TextPageLink textPageLink = new TextPageLink(30, "WB"); + TextPageLink textPageLink = new TextPageLink(30, "TEXT_NOT_FOUND"); List widgetsBundles4 = widgetsBundleDao.findAllTenantWidgetsBundlesByTenantId(tenantId, textPageLink); assertEquals(0, widgetsBundles4.size()); } diff --git a/dao/src/test/resources/dbunit/users.xml b/dao/src/test/resources/dbunit/users.xml index 9576b5c3be..4b704a0a2e 100644 --- a/dao/src/test/resources/dbunit/users.xml +++ b/dao/src/test/resources/dbunit/users.xml @@ -7,7 +7,6 @@ search_text="SYSADM SEARCH TEXT" first_name="John" last_name="Doe" - additional_info="{"key":"value-0"}" /> \ No newline at end of file