Browse Source

Redis cache as an option and adding Serializable.

pull/600/head
Andrew Shvayka 9 years ago
parent
commit
fed0fe8b00
  1. 4
      application/src/main/java/org/thingsboard/server/actors/plugin/PluginProcessingContext.java
  2. 4
      application/src/main/java/org/thingsboard/server/controller/BaseController.java
  3. 10
      application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java
  4. 30
      application/src/main/resources/thingsboard.yml
  5. 2
      common/data/src/main/java/org/thingsboard/server/common/data/ContactBased.java
  6. 22
      common/data/src/main/java/org/thingsboard/server/common/data/Customer.java
  7. 14
      common/data/src/main/java/org/thingsboard/server/common/data/Device.java
  8. 24
      common/data/src/main/java/org/thingsboard/server/common/data/HasAdditionalInfo.java
  9. 105
      common/data/src/main/java/org/thingsboard/server/common/data/SearchTextBasedWithAdditionalInfo.java
  10. 14
      common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java
  11. 14
      common/data/src/main/java/org/thingsboard/server/common/data/User.java
  12. 16
      common/data/src/main/java/org/thingsboard/server/common/data/asset/Asset.java
  13. 31
      common/data/src/main/java/org/thingsboard/server/common/data/plugin/PluginMetaData.java
  14. 22
      common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java
  15. 49
      common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleMetaData.java
  16. 8
      dao/pom.xml
  17. 2
      dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java
  18. 6
      dao/src/main/java/org/thingsboard/server/dao/cache/CaffeineCacheConfiguration.java
  19. 78
      dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisCacheConfiguration.java
  20. 103
      dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java
  21. 20
      dao/src/main/java/org/thingsboard/server/dao/relation/RelationService.java
  22. 24
      dao/src/test/java/org/thingsboard/server/dao/service/BaseRelationServiceTest.java
  23. 25
      dao/src/test/resources/application-test.properties
  24. 27
      docker/docker-compose-tests.yml
  25. 12
      pom.xml

4
application/src/main/java/org/thingsboard/server/actors/plugin/PluginProcessingContext.java

@ -429,12 +429,12 @@ public final class PluginProcessingContext implements PluginContext {
@Override
public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType) {
return this.pluginCtx.relationService.findByFromAndType(from, relationType, RelationTypeGroup.COMMON);
return this.pluginCtx.relationService.findByFromAndTypeAsync(from, relationType, RelationTypeGroup.COMMON);
}
@Override
public ListenableFuture<List<EntityRelation>> findByToAndType(EntityId from, String relationType) {
return this.pluginCtx.relationService.findByToAndType(from, relationType, RelationTypeGroup.COMMON);
return this.pluginCtx.relationService.findByToAndTypeAsync(from, relationType, RelationTypeGroup.COMMON);
}
@Override

4
application/src/main/java/org/thingsboard/server/controller/BaseController.java

@ -117,6 +117,10 @@ public abstract class BaseController {
@Autowired
protected RelationService relationService;
@ExceptionHandler(Exception.class)
public void handleException(Exception ex, HttpServletResponse response) {
errorResponseHandler.handle(ex, response);
}
@ExceptionHandler(ThingsboardException.class)
public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) {

10
application/src/main/java/org/thingsboard/server/controller/EntityRelationController.java

@ -120,7 +120,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(fromId);
checkEntityId(toId);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
return checkNotNull(relationService.getRelation(fromId, toId, strRelationType, typeGroup).get());
return checkNotNull(relationService.getRelation(fromId, toId, strRelationType, typeGroup));
} catch (Exception e) {
throw handleException(e);
}
@ -138,7 +138,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByFrom(entityId, typeGroup).get());
return checkNotNull(relationService.findByFrom(entityId, typeGroup));
} catch (Exception e) {
throw handleException(e);
}
@ -176,7 +176,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByFromAndType(entityId, strRelationType, typeGroup).get());
return checkNotNull(relationService.findByFromAndType(entityId, strRelationType, typeGroup));
} catch (Exception e) {
throw handleException(e);
}
@ -194,7 +194,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByTo(entityId, typeGroup).get());
return checkNotNull(relationService.findByTo(entityId, typeGroup));
} catch (Exception e) {
throw handleException(e);
}
@ -232,7 +232,7 @@ public class EntityRelationController extends BaseController {
checkEntityId(entityId);
RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
try {
return checkNotNull(relationService.findByToAndType(entityId, strRelationType, typeGroup).get());
return checkNotNull(relationService.findByToAndType(entityId, strRelationType, typeGroup));
} catch (Exception e) {
throw handleException(e);
}

30
application/src/main/resources/thingsboard.yml

@ -214,26 +214,11 @@ actors:
enabled: "${ACTORS_STATISTICS_ENABLED:true}"
persist_frequency: "${ACTORS_STATISTICS_PERSIST_FREQUENCY:3600000}"
# Cache parameters
cache:
# Enable/disable cache functionality.
enabled: "${CACHE_ENABLED:false}"
device_credentials:
# Default time to store device credentials in cache, in seconds
time_to_live: "${CACHE_DEVICE_CREDENTIAL_TTL:3600}"
# Maximum size of the map. When maximum size is reached, the map is evicted based on the policy defined.
max_size:
# Max size policy options:
# PER_NODE: Maximum number of map entries in each JVM.
# PER_PARTITION: Maximum number of map entries within each partition.
# USED_HEAP_SIZE: Maximum used heap size in megabytes for each JVM.
# USED_HEAP_PERCENTAGE: Maximum used heap size percentage for each JVM.
# FREE_HEAP_SIZE: Minimum free heap size in megabytes for each JVM.
# FREE_HEAP_PERCENTAGE: Minimum free heap size percentage for each JVM.
policy: "${CACHE_DEVICE_CREDENTIAL_MAX_SIZE_POLICY:PER_NODE}"
size: "${CACHE_DEVICE_CREDENTIAL_MAX_SIZE_SIZE:1000000}"
# caffeine or redis
type: "${CACHE_TYPE:caffeine}"
caching:
caffeine:
specs:
relations:
timeToLiveInMinutes: 1440
@ -245,6 +230,15 @@ caching:
timeToLiveInMinutes: 1440
maxSize: 100000
redis:
# standalone or cluster
connection:
type: standalone
host: "${REDIS_HOST:localhost}"
port: "${REDIS_PORT:6379}"
db: "${REDIS_DB:0}"
password: "${REDIS_PASSWORD:}"
# Check new version updates parameters
updates:
# Enable/disable updates checking.

2
common/data/src/main/java/org/thingsboard/server/common/data/ContactBased.java

@ -19,7 +19,7 @@ import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.id.UUIDBased;
@EqualsAndHashCode(callSuper = true)
public abstract class ContactBased<I extends UUIDBased> extends SearchTextBased<I> {
public abstract class ContactBased<I extends UUIDBased> extends SearchTextBasedWithAdditionalInfo<I> {
private static final long serialVersionUID = 5047448057830660988L;

22
common/data/src/main/java/org/thingsboard/server/common/data/Customer.java

@ -29,8 +29,7 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
private String title;
private TenantId tenantId;
private transient JsonNode additionalInfo;
public Customer() {
super();
}
@ -43,7 +42,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
super(customer);
this.tenantId = customer.getTenantId();
this.title = customer.getTitle();
this.additionalInfo = customer.getAdditionalInfo();
}
public TenantId getTenantId() {
@ -65,7 +63,7 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
@JsonIgnore
public boolean isPublic() {
if (getAdditionalInfo() != null && getAdditionalInfo().has("isPublic")) {
return additionalInfo.get("isPublic").asBoolean();
return getAdditionalInfo().get("isPublic").asBoolean();
}
return false;
@ -77,14 +75,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
return title;
}
public JsonNode getAdditionalInfo() {
return additionalInfo;
}
public void setAdditionalInfo(JsonNode additionalInfo) {
this.additionalInfo = additionalInfo;
}
@Override
public String getSearchText() {
return getTitle();
@ -94,7 +84,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((additionalInfo == null) ? 0 : additionalInfo.hashCode());
result = prime * result + ((tenantId == null) ? 0 : tenantId.hashCode());
result = prime * result + ((title == null) ? 0 : title.hashCode());
return result;
@ -109,11 +98,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
if (getClass() != obj.getClass())
return false;
Customer other = (Customer) obj;
if (additionalInfo == null) {
if (other.additionalInfo != null)
return false;
} else if (!additionalInfo.equals(other.additionalInfo))
return false;
if (tenantId == null) {
if (other.tenantId != null)
return false;
@ -135,7 +119,7 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
builder.append(", tenantId=");
builder.append(tenantId);
builder.append(", additionalInfo=");
builder.append(additionalInfo);
builder.append(getAdditionalInfo());
builder.append(", country=");
builder.append(country);
builder.append(", state=");

14
common/data/src/main/java/org/thingsboard/server/common/data/Device.java

@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId;
import com.fasterxml.jackson.databind.JsonNode;
@EqualsAndHashCode(callSuper = true)
public class Device extends SearchTextBased<DeviceId> implements HasName {
public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implements HasName {
private static final long serialVersionUID = 2807343040519543363L;
@ -31,7 +31,6 @@ public class Device extends SearchTextBased<DeviceId> implements HasName {
private CustomerId customerId;
private String name;
private String type;
private transient JsonNode additionalInfo;
public Device() {
super();
@ -47,7 +46,6 @@ public class Device extends SearchTextBased<DeviceId> implements HasName {
this.customerId = device.getCustomerId();
this.name = device.getName();
this.type = device.getType();
this.additionalInfo = device.getAdditionalInfo();
}
public TenantId getTenantId() {
@ -83,14 +81,6 @@ public class Device extends SearchTextBased<DeviceId> implements HasName {
this.type = type;
}
public JsonNode getAdditionalInfo() {
return additionalInfo;
}
public void setAdditionalInfo(JsonNode additionalInfo) {
this.additionalInfo = additionalInfo;
}
@Override
public String getSearchText() {
return getName();
@ -108,7 +98,7 @@ public class Device extends SearchTextBased<DeviceId> implements HasName {
builder.append(", type=");
builder.append(type);
builder.append(", additionalInfo=");
builder.append(additionalInfo);
builder.append(getAdditionalInfo());
builder.append(", createdTime=");
builder.append(createdTime);
builder.append(", id=");

24
common/data/src/main/java/org/thingsboard/server/common/data/HasAdditionalInfo.java

@ -0,0 +1,24 @@
/**
* 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.common.data;
import com.fasterxml.jackson.databind.JsonNode;
public interface HasAdditionalInfo {
JsonNode getAdditionalInfo();
}

105
common/data/src/main/java/org/thingsboard/server/common/data/SearchTextBasedWithAdditionalInfo.java

@ -0,0 +1,105 @@
/**
* 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.common.data;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.id.UUIDBased;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.Objects;
import java.util.function.Supplier;
import java.util.function.Consumer;
/**
* Created by ashvayka on 19.02.18.
*/
@Slf4j
public abstract class SearchTextBasedWithAdditionalInfo<I extends UUIDBased> extends SearchTextBased<I> implements HasAdditionalInfo {
private transient JsonNode additionalInfo;
@JsonIgnore
private byte[] additionalInfoBytes;
public SearchTextBasedWithAdditionalInfo() {
super();
}
public SearchTextBasedWithAdditionalInfo(I id) {
super(id);
}
public SearchTextBasedWithAdditionalInfo(SearchTextBasedWithAdditionalInfo<I> searchTextBased) {
super(searchTextBased);
setAdditionalInfo(searchTextBased.getAdditionalInfo());
}
@Override
public JsonNode getAdditionalInfo() {
return getJson(() -> additionalInfo, () -> additionalInfoBytes);
}
public void setAdditionalInfo(JsonNode addInfo) {
setJson(addInfo, json -> this.additionalInfo = json, bytes -> this.additionalInfoBytes = bytes);
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
SearchTextBasedWithAdditionalInfo<?> that = (SearchTextBasedWithAdditionalInfo<?>) o;
return Arrays.equals(additionalInfoBytes, that.additionalInfoBytes);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), additionalInfoBytes);
}
public static JsonNode getJson(Supplier<JsonNode> jsonData, Supplier<byte[]> binaryData) {
JsonNode json = jsonData.get();
if (json != null) {
return json;
} else {
byte[] data = binaryData.get();
if (data != null) {
try {
return new ObjectMapper().readTree(new ByteArrayInputStream(data));
} catch (IOException e) {
log.warn("Can't deserialize json data: ", e);
return null;
}
} else {
return null;
}
}
}
public static void setJson(JsonNode json, Consumer<JsonNode> jsonConsumer, Consumer<byte[]> bytesConsumer) {
jsonConsumer.accept(json);
try {
bytesConsumer.accept(new ObjectMapper().writeValueAsBytes(json));
} catch (JsonProcessingException e) {
log.warn("Can't serialize json data: ", e);
}
}
}

14
common/data/src/main/java/org/thingsboard/server/common/data/Tenant.java

@ -28,8 +28,7 @@ public class Tenant extends ContactBased<TenantId> implements HasName {
private String title;
private String region;
private transient JsonNode additionalInfo;
public Tenant() {
super();
}
@ -42,7 +41,6 @@ public class Tenant extends ContactBased<TenantId> implements HasName {
super(tenant);
this.title = tenant.getTitle();
this.region = tenant.getRegion();
this.additionalInfo = tenant.getAdditionalInfo();
}
public String getTitle() {
@ -67,14 +65,6 @@ public class Tenant extends ContactBased<TenantId> implements HasName {
this.region = region;
}
public JsonNode getAdditionalInfo() {
return additionalInfo;
}
public void setAdditionalInfo(JsonNode additionalInfo) {
this.additionalInfo = additionalInfo;
}
@Override
public String getSearchText() {
return getTitle();
@ -88,7 +78,7 @@ public class Tenant extends ContactBased<TenantId> implements HasName {
builder.append(", region=");
builder.append(region);
builder.append(", additionalInfo=");
builder.append(additionalInfo);
builder.append(getAdditionalInfo());
builder.append(", country=");
builder.append(country);
builder.append(", state=");

14
common/data/src/main/java/org/thingsboard/server/common/data/User.java

@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.security.Authority;
import com.fasterxml.jackson.databind.JsonNode;
@EqualsAndHashCode(callSuper = true)
public class User extends SearchTextBased<UserId> implements HasName {
public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements HasName {
private static final long serialVersionUID = 8250339805336035966L;
@ -35,7 +35,6 @@ public class User extends SearchTextBased<UserId> implements HasName {
private Authority authority;
private String firstName;
private String lastName;
private transient JsonNode additionalInfo;
public User() {
super();
@ -53,7 +52,6 @@ public class User extends SearchTextBased<UserId> implements HasName {
this.authority = user.getAuthority();
this.firstName = user.getFirstName();
this.lastName = user.getLastName();
this.additionalInfo = user.getAdditionalInfo();
}
public TenantId getTenantId() {
@ -110,14 +108,6 @@ public class User extends SearchTextBased<UserId> implements HasName {
this.lastName = lastName;
}
public JsonNode getAdditionalInfo() {
return additionalInfo;
}
public void setAdditionalInfo(JsonNode additionalInfo) {
this.additionalInfo = additionalInfo;
}
@Override
public String getSearchText() {
return getEmail();
@ -139,7 +129,7 @@ public class User extends SearchTextBased<UserId> implements HasName {
builder.append(", lastName=");
builder.append(lastName);
builder.append(", additionalInfo=");
builder.append(additionalInfo);
builder.append(getAdditionalInfo());
builder.append(", createdTime=");
builder.append(createdTime);
builder.append(", id=");

16
common/data/src/main/java/org/thingsboard/server/common/data/asset/Asset.java

@ -17,14 +17,16 @@ package org.thingsboard.server.common.data.asset;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.EqualsAndHashCode;
import org.thingsboard.server.common.data.HasAdditionalInfo;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.SearchTextBased;
import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
import org.thingsboard.server.common.data.id.AssetId;
import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.TenantId;
@EqualsAndHashCode(callSuper = true)
public class Asset extends SearchTextBased<AssetId> implements HasName {
public class Asset extends SearchTextBasedWithAdditionalInfo<AssetId> implements HasName {
private static final long serialVersionUID = 2807343040519543363L;
@ -32,7 +34,6 @@ public class Asset extends SearchTextBased<AssetId> implements HasName {
private CustomerId customerId;
private String name;
private String type;
private transient JsonNode additionalInfo;
public Asset() {
super();
@ -48,7 +49,6 @@ public class Asset extends SearchTextBased<AssetId> implements HasName {
this.customerId = asset.getCustomerId();
this.name = asset.getName();
this.type = asset.getType();
this.additionalInfo = asset.getAdditionalInfo();
}
public TenantId getTenantId() {
@ -84,14 +84,6 @@ public class Asset extends SearchTextBased<AssetId> implements HasName {
this.type = type;
}
public JsonNode getAdditionalInfo() {
return additionalInfo;
}
public void setAdditionalInfo(JsonNode additionalInfo) {
this.additionalInfo = additionalInfo;
}
@Override
public String getSearchText() {
return getName();
@ -109,7 +101,7 @@ public class Asset extends SearchTextBased<AssetId> implements HasName {
builder.append(", type=");
builder.append(type);
builder.append(", additionalInfo=");
builder.append(additionalInfo);
builder.append(getAdditionalInfo());
builder.append(", createdTime=");
builder.append(createdTime);
builder.append(", id=");

31
common/data/src/main/java/org/thingsboard/server/common/data/plugin/PluginMetaData.java

@ -15,16 +15,24 @@
*/
package org.thingsboard.server.common.data.plugin;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.SearchTextBased;
import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
import org.thingsboard.server.common.data.id.PluginId;
import org.thingsboard.server.common.data.id.TenantId;
import com.fasterxml.jackson.databind.JsonNode;
import java.io.ByteArrayInputStream;
import java.io.IOException;
@EqualsAndHashCode(callSuper = true)
public class PluginMetaData extends SearchTextBased<PluginId> implements HasName {
@Slf4j
public class PluginMetaData extends SearchTextBasedWithAdditionalInfo<PluginId> implements HasName {
private static final long serialVersionUID = 1L;
@ -35,7 +43,9 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName
private boolean publicAccess;
private ComponentLifecycleState state;
private transient JsonNode configuration;
private transient JsonNode additionalInfo;
@JsonIgnore
private byte[] configurationBytes;
public PluginMetaData() {
super();
@ -54,7 +64,6 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName
this.publicAccess = plugin.isPublicAccess();
this.state = plugin.getState();
this.configuration = plugin.getConfiguration();
this.additionalInfo = plugin.getAdditionalInfo();
}
@Override
@ -96,11 +105,11 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName
}
public JsonNode getConfiguration() {
return configuration;
return getJson(() -> configuration, () -> configurationBytes);
}
public void setConfiguration(JsonNode configuration) {
this.configuration = configuration;
public void setConfiguration(JsonNode data) {
setJson(data, json -> this.configuration = json, bytes -> this.configurationBytes = bytes);
}
public boolean isPublicAccess() {
@ -119,14 +128,6 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName
return state;
}
public JsonNode getAdditionalInfo() {
return additionalInfo;
}
public void setAdditionalInfo(JsonNode additionalInfo) {
this.additionalInfo = additionalInfo;
}
@Override
public String toString() {
return "PluginMetaData [apiToken=" + apiToken + ", tenantId=" + tenantId + ", name=" + name + ", clazz=" + clazz + ", publicAccess=" + publicAccess

22
common/data/src/main/java/org/thingsboard/server/common/data/relation/EntityRelation.java

@ -15,10 +15,20 @@
*/
package org.thingsboard.server.common.data.relation;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
import org.thingsboard.server.common.data.id.EntityId;
public class EntityRelation {
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.Serializable;
@Slf4j
public class EntityRelation implements Serializable {
private static final long serialVersionUID = 2807343040519543363L;
@ -29,7 +39,9 @@ public class EntityRelation {
private EntityId to;
private String type;
private RelationTypeGroup typeGroup;
private JsonNode additionalInfo;
private transient JsonNode additionalInfo;
@JsonIgnore
private byte[] additionalInfoBytes;
public EntityRelation() {
super();
@ -92,11 +104,11 @@ public class EntityRelation {
}
public JsonNode getAdditionalInfo() {
return additionalInfo;
return SearchTextBasedWithAdditionalInfo.getJson(() -> additionalInfo, () -> additionalInfoBytes);
}
public void setAdditionalInfo(JsonNode additionalInfo) {
this.additionalInfo = additionalInfo;
public void setAdditionalInfo(JsonNode addInfo) {
SearchTextBasedWithAdditionalInfo.setJson(addInfo, json -> this.additionalInfo = json, bytes -> this.additionalInfoBytes = bytes);
}
@Override

49
common/data/src/main/java/org/thingsboard/server/common/data/rule/RuleMetaData.java

@ -15,18 +15,23 @@
*/
package org.thingsboard.server.common.data.rule;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.extern.slf4j.Slf4j;
import org.thingsboard.server.common.data.HasName;
import org.thingsboard.server.common.data.SearchTextBased;
import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
import org.thingsboard.server.common.data.id.RuleId;
import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.common.data.plugin.ComponentLifecycleState;
@Data
@EqualsAndHashCode(callSuper = true)
public class RuleMetaData extends SearchTextBased<RuleId> implements HasName {
@Slf4j
public class RuleMetaData extends SearchTextBasedWithAdditionalInfo<RuleId> implements HasName {
private static final long serialVersionUID = -5656679015122935465L;
@ -38,7 +43,13 @@ public class RuleMetaData extends SearchTextBased<RuleId> implements HasName {
private transient JsonNode filters;
private transient JsonNode processor;
private transient JsonNode action;
private transient JsonNode additionalInfo;
@JsonIgnore
private byte[] filtersBytes;
@JsonIgnore
private byte[] processorBytes;
@JsonIgnore
private byte[] actionBytes;
public RuleMetaData() {
super();
@ -55,10 +66,9 @@ public class RuleMetaData extends SearchTextBased<RuleId> implements HasName {
this.state = rule.getState();
this.weight = rule.getWeight();
this.pluginToken = rule.getPluginToken();
this.filters = rule.getFilters();
this.processor = rule.getProcessor();
this.action = rule.getAction();
this.additionalInfo = rule.getAdditionalInfo();
this.setFilters(rule.getFilters());
this.setProcessor(rule.getProcessor());
this.setAction(rule.getAction());
}
@Override
@ -71,4 +81,29 @@ public class RuleMetaData extends SearchTextBased<RuleId> implements HasName {
return name;
}
public JsonNode getFilters() {
return SearchTextBasedWithAdditionalInfo.getJson(() -> filters, () -> filtersBytes);
}
public JsonNode getProcessor() {
return SearchTextBasedWithAdditionalInfo.getJson(() -> processor, () -> processorBytes);
}
public JsonNode getAction() {
return SearchTextBasedWithAdditionalInfo.getJson(() -> action, () -> actionBytes);
}
public void setFilters(JsonNode data) {
setJson(data, json -> this.filters = json, bytes -> this.filtersBytes = bytes);
}
public void setProcessor(JsonNode data) {
setJson(data, json -> this.processor = json, bytes -> this.processorBytes = bytes);
}
public void setAction(JsonNode data) {
setJson(data, json -> this.action = json, bytes -> this.actionBytes = bytes);
}
}

8
dao/pom.xml

@ -182,6 +182,14 @@
<groupId>org.springframework</groupId>
<artifactId>spring-context-support</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
</dependency>
</dependencies>
<build>
<plugins>

2
dao/src/main/java/org/thingsboard/server/dao/alarm/BaseAlarmService.java

@ -337,7 +337,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
private void updateRelations(Alarm alarm, AlarmStatus oldStatus, AlarmStatus newStatus) {
try {
List<EntityRelation> relations = relationService.findByTo(alarm.getId(), RelationTypeGroup.ALARM).get();
List<EntityRelation> relations = relationService.findByToAsync(alarm.getId(), RelationTypeGroup.ALARM).get();
Set<EntityId> parents = relations.stream().map(EntityRelation::getFrom).collect(Collectors.toSet());
for (EntityId parentId : parents) {
updateAlarmRelation(parentId, alarm.getId(), oldStatus, newStatus);

6
dao/src/main/java/org/thingsboard/server/dao/cache/ServiceCacheConfiguration.java → dao/src/main/java/org/thingsboard/server/dao/cache/CaffeineCacheConfiguration.java

@ -18,6 +18,7 @@ package org.thingsboard.server.dao.cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.Ticker;
import lombok.Data;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
@ -33,10 +34,11 @@ import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@Configuration
@ConfigurationProperties(prefix = "caching")
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
@ConfigurationProperties(prefix = "caffeine")
@EnableCaching
@Data
public class ServiceCacheConfiguration {
public class CaffeineCacheConfiguration {
private Map<String, CacheSpecs> specs;

78
dao/src/main/java/org/thingsboard/server/dao/cache/TBRedisCacheConfiguration.java

@ -0,0 +1,78 @@
/**
* 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.cache;
import lombok.Data;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.cache.CacheManager;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
@Configuration
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis", matchIfMissing = false)
@EnableCaching
@Data
public class TBRedisCacheConfiguration {
@Value("${redis.connection.host}")
private String host;
@Value("${redis.connection.port}")
private Integer port;
@Value("${redis.connection.db}")
private Integer db;
@Value("${redis.connection.password}")
private String password;
@Bean
public RedisConnectionFactory redisConnectionFactory() {
JedisConnectionFactory factory = new JedisConnectionFactory();
factory.setHostName(host);
factory.setPort(port);
factory.setDatabase(db);
factory.setPassword(password);
return factory;
}
@Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
redisTemplate.setConnectionFactory(cf);
return redisTemplate;
}
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
return new RedisCacheManager(redisTemplate);
}
@Bean
public KeyGenerator previousDeviceCredentialsId() {
return new PreviousDeviceCredentialsIdKeyGenerator();
}
}

103
dao/src/main/java/org/thingsboard/server/dao/relation/BaseRelationService.java

@ -64,19 +64,28 @@ public class BaseRelationService implements RelationService {
return relationDao.checkRelation(from, to, relationType, typeGroup);
}
@Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #to, #relationType}")
@Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #to, #relationType, #typeGroup}")
@Override
public ListenableFuture<EntityRelation> getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
public EntityRelation getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
try {
return getRelationAsync(from, to, relationType, typeGroup).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
public ListenableFuture<EntityRelation> getRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
log.trace("Executing EntityRelation [{}][{}][{}][{}]", from, to, relationType, typeGroup);
validate(from, to, relationType, typeGroup);
return relationDao.getRelation(from, to, relationType, typeGroup);
}
@Caching(evict = {
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.from"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}")
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.typeGroup}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type, #relation.typeGroup}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.typeGroup}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup}")
})
@Override
public boolean saveRelation(EntityRelation relation) {
@ -86,10 +95,10 @@ public class BaseRelationService implements RelationService {
}
@Caching(evict = {
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.from"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}")
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.typeGroup}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type, #relation.typeGroup}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.typeGroup}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup}")
})
@Override
public ListenableFuture<Boolean> saveRelationAsync(EntityRelation relation) {
@ -99,11 +108,11 @@ public class BaseRelationService implements RelationService {
}
@Caching(evict = {
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.from"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type}")
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.typeGroup}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type, #relation.typeGroup}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.typeGroup}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type, #relation.typeGroup}")
})
@Override
public boolean deleteRelation(EntityRelation relation) {
@ -117,7 +126,7 @@ public class BaseRelationService implements RelationService {
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}"),
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type}")
@CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type, #relation.typeGroup}")
})
@Override
public ListenableFuture<Boolean> deleteRelationAsync(EntityRelation relation) {
@ -218,9 +227,9 @@ public class BaseRelationService implements RelationService {
ListenableFuture<List<List<EntityRelation>>> inboundRelationsTo = Futures.allAsList(inboundRelationsListTo);
ListenableFuture<List<Boolean>> inboundDeletions = Futures.transform(inboundRelationsTo,
(AsyncFunction<List<List<EntityRelation>>, List<Boolean>>) relations -> {
List<ListenableFuture<Boolean>> results = getListenableFutures(relations, cache, true);
return Futures.allAsList(results);
});
List<ListenableFuture<Boolean>> results = getListenableFutures(relations, cache, true);
return Futures.allAsList(results);
});
ListenableFuture<Boolean> inboundFuture = Futures.transform(inboundDeletions, getListToBooleanFunction());
@ -272,9 +281,18 @@ public class BaseRelationService implements RelationService {
cache.evict(fromToAndType);
}
@Cacheable(cacheNames = RELATIONS_CACHE, key = "#from")
@Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #typeGroup}")
@Override
public List<EntityRelation> findByFrom(EntityId from, RelationTypeGroup typeGroup) {
try {
return findByFromAsync(from, typeGroup).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
public ListenableFuture<List<EntityRelation>> findByFrom(EntityId from, RelationTypeGroup typeGroup) {
public ListenableFuture<List<EntityRelation>> findByFromAsync(EntityId from, RelationTypeGroup typeGroup) {
log.trace("Executing findByFrom [{}][{}]", from, typeGroup);
validate(from);
validateTypeGroup(typeGroup);
@ -300,9 +318,18 @@ public class BaseRelationService implements RelationService {
return relationsInfo;
}
@Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #relationType}")
@Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #relationType, #typeGroup}")
@Override
public List<EntityRelation> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) {
try {
return findByFromAndTypeAsync(from, relationType, typeGroup).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) {
public ListenableFuture<List<EntityRelation>> findByFromAndTypeAsync(EntityId from, String relationType, RelationTypeGroup typeGroup) {
log.trace("Executing findByFromAndType [{}][{}][{}]", from, relationType, typeGroup);
validate(from);
validateType(relationType);
@ -310,9 +337,18 @@ public class BaseRelationService implements RelationService {
return relationDao.findAllByFromAndType(from, relationType, typeGroup);
}
@Cacheable(cacheNames = RELATIONS_CACHE, key = "#to")
@Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #typeGroup}")
@Override
public List<EntityRelation> findByTo(EntityId to, RelationTypeGroup typeGroup) {
try {
return findByToAsync(to, typeGroup).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
public ListenableFuture<List<EntityRelation>> findByTo(EntityId to, RelationTypeGroup typeGroup) {
public ListenableFuture<List<EntityRelation>> findByToAsync(EntityId to, RelationTypeGroup typeGroup) {
log.trace("Executing findByTo [{}][{}]", to, typeGroup);
validate(to);
validateTypeGroup(typeGroup);
@ -351,9 +387,18 @@ public class BaseRelationService implements RelationService {
return entityRelationInfo;
}
@Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #relationType}")
@Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #relationType, #typeGroup}")
@Override
public List<EntityRelation> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) {
try {
return findByToAndTypeAsync(to, relationType, typeGroup).get();
} catch (InterruptedException | ExecutionException e) {
throw new RuntimeException(e);
}
}
@Override
public ListenableFuture<List<EntityRelation>> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) {
public ListenableFuture<List<EntityRelation>> findByToAndTypeAsync(EntityId to, String relationType, RelationTypeGroup typeGroup) {
log.trace("Executing findByToAndType [{}][{}][{}]", to, relationType, typeGroup);
validate(to);
validateType(relationType);
@ -527,9 +572,9 @@ public class BaseRelationService implements RelationService {
private ListenableFuture<List<EntityRelation>> findRelations(final EntityId rootId, final EntitySearchDirection direction) {
ListenableFuture<List<EntityRelation>> relations;
if (direction == EntitySearchDirection.FROM) {
relations = findByFrom(rootId, RelationTypeGroup.COMMON);
relations = findByFromAsync(rootId, RelationTypeGroup.COMMON);
} else {
relations = findByTo(rootId, RelationTypeGroup.COMMON);
relations = findByToAsync(rootId, RelationTypeGroup.COMMON);
}
return relations;
}

20
dao/src/main/java/org/thingsboard/server/dao/relation/RelationService.java

@ -31,7 +31,9 @@ public interface RelationService {
ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
ListenableFuture<EntityRelation> getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
EntityRelation getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
ListenableFuture<EntityRelation> getRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
boolean saveRelation(EntityRelation relation);
@ -49,17 +51,25 @@ public interface RelationService {
ListenableFuture<Boolean> deleteEntityRelationsAsync(EntityId entity);
ListenableFuture<List<EntityRelation>> findByFrom(EntityId from, RelationTypeGroup typeGroup);
List<EntityRelation> findByFrom(EntityId from, RelationTypeGroup typeGroup);
ListenableFuture<List<EntityRelation>> findByFromAsync(EntityId from, RelationTypeGroup typeGroup);
ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(EntityId from, RelationTypeGroup typeGroup);
ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup);
List<EntityRelation> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup);
ListenableFuture<List<EntityRelation>> findByFromAndTypeAsync(EntityId from, String relationType, RelationTypeGroup typeGroup);
ListenableFuture<List<EntityRelation>> findByTo(EntityId to, RelationTypeGroup typeGroup);
List<EntityRelation> findByTo(EntityId to, RelationTypeGroup typeGroup);
ListenableFuture<List<EntityRelation>> findByToAsync(EntityId to, RelationTypeGroup typeGroup);
ListenableFuture<List<EntityRelationInfo>> findInfoByTo(EntityId to, RelationTypeGroup typeGroup);
ListenableFuture<List<EntityRelation>> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup);
List<EntityRelation> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup);
ListenableFuture<List<EntityRelation>> findByToAndTypeAsync(EntityId to, String relationType, RelationTypeGroup typeGroup);
ListenableFuture<List<EntityRelation>> findByQuery(EntityRelationsQuery query);

24
dao/src/test/java/org/thingsboard/server/dao/service/BaseRelationServiceTest.java

@ -122,7 +122,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
saveRelation(relationB1);
saveRelation(relationB2);
List<EntityRelation> relations = relationService.findByFrom(parentA, RelationTypeGroup.COMMON).get();
List<EntityRelation> relations = relationService.findByFrom(parentA, RelationTypeGroup.COMMON);
Assert.assertEquals(2, relations.size());
for (EntityRelation relation : relations) {
Assert.assertEquals(EntityRelation.CONTAINS_TYPE, relation.getType());
@ -130,13 +130,13 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
Assert.assertTrue(childA.equals(relation.getTo()) || childB.equals(relation.getTo()));
}
relations = relationService.findByFromAndType(parentA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get();
relations = relationService.findByFromAndType(parentA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON);
Assert.assertEquals(2, relations.size());
relations = relationService.findByFromAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get();
relations = relationService.findByFromAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON);
Assert.assertEquals(0, relations.size());
relations = relationService.findByFrom(parentB, RelationTypeGroup.COMMON).get();
relations = relationService.findByFrom(parentB, RelationTypeGroup.COMMON);
Assert.assertEquals(2, relations.size());
for (EntityRelation relation : relations) {
Assert.assertEquals(EntityRelation.MANAGES_TYPE, relation.getType());
@ -144,10 +144,10 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
Assert.assertTrue(childA.equals(relation.getTo()) || childB.equals(relation.getTo()));
}
relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get();
relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON);
Assert.assertEquals(0, relations.size());
relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get();
relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON);
Assert.assertEquals(0, relations.size());
}
@ -177,26 +177,26 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
// Data propagation to views is async
Thread.sleep(3000);
List<EntityRelation> relations = relationService.findByTo(childA, RelationTypeGroup.COMMON).get();
List<EntityRelation> relations = relationService.findByTo(childA, RelationTypeGroup.COMMON);
Assert.assertEquals(2, relations.size());
for (EntityRelation relation : relations) {
Assert.assertEquals(childA, relation.getTo());
Assert.assertTrue(parentA.equals(relation.getFrom()) || parentB.equals(relation.getFrom()));
}
relations = relationService.findByToAndType(childA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get();
relations = relationService.findByToAndType(childA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON);
Assert.assertEquals(1, relations.size());
relations = relationService.findByToAndType(childB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get();
relations = relationService.findByToAndType(childB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON);
Assert.assertEquals(1, relations.size());
relations = relationService.findByToAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get();
relations = relationService.findByToAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON);
Assert.assertEquals(0, relations.size());
relations = relationService.findByToAndType(parentB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get();
relations = relationService.findByToAndType(parentB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON);
Assert.assertEquals(0, relations.size());
relations = relationService.findByTo(childB, RelationTypeGroup.COMMON).get();
relations = relationService.findByTo(childB, RelationTypeGroup.COMMON);
Assert.assertEquals(2, relations.size());
for (EntityRelation relation : relations) {
Assert.assertEquals(childB, relation.getTo());

25
dao/src/test/resources/application-test.properties

@ -1,19 +1,22 @@
cache.enabled=false
cache.device_credentials.time_to_live=3600
cache.device_credentials.max_size.size=1000000
cache.device_credentials.max_size.policy=PER_NODE
zk.enabled=false
zk.url=localhost:2181
zk.zk_dir=/thingsboard
updates.enabled=false
caching.specs.relations.timeToLiveInMinutes=1440
caching.specs.relations.maxSize=100000
cache.type=caffeine
#cache.type=redis
caffeine.specs.relations.timeToLiveInMinutes=1440
caffeine.specs.relations.maxSize=100000
caffeine.specs.deviceCredentials.timeToLiveInMinutes=1440
caffeine.specs.deviceCredentials.maxSize=100000
caching.specs.deviceCredentials.timeToLiveInMinutes=1440
caching.specs.deviceCredentials.maxSize=100000
caffeine.specs.devices.timeToLiveInMinutes=1440
caffeine.specs.devices.maxSize=100000
caching.specs.devices.timeToLiveInMinutes=1440
caching.specs.devices.maxSize=100000
redis.connection.host=localhost
redis.connection.port=6379
redis.connection.db=0
redis.connection.password=

27
docker/docker-compose-tests.yml

@ -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.
#
version: '3.3'
services:
redis:
image: redis:4.0
networks:
- core
ports:
- "6379:6379"
networks:
core:

12
pom.xml

@ -32,6 +32,8 @@
<spring-boot.version>1.4.3.RELEASE</spring-boot.version>
<spring.version>4.3.4.RELEASE</spring.version>
<spring-security.version>4.2.0.RELEASE</spring-security.version>
<spring-data-redis.version>1.8.10.RELEASE</spring-data-redis.version>
<jedis.version>2.9.0</jedis.version>
<jjwt.version>0.7.0</jjwt.version>
<json-path.version>2.2.0</json-path.version>
<junit.version>4.12</junit.version>
@ -783,6 +785,16 @@
<version>2.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.data</groupId>
<artifactId>spring-data-redis</artifactId>
<version>${spring-data-redis.version}</version>
</dependency>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>${jedis.version}</version>
</dependency>
<dependency>
<groupId>com.sun.winsw</groupId>
<artifactId>winsw</artifactId>

Loading…
Cancel
Save