Commit fed0fe8b000a094d37a0a61da770c5485041e32a

Authored by Andrew Shvayka
1 parent 7b0b5e72

Redis cache as an option and adding Serializable.

Showing 25 changed files with 486 additions and 180 deletions
... ... @@ -429,12 +429,12 @@ public final class PluginProcessingContext implements PluginContext {
429 429
430 430 @Override
431 431 public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType) {
432   - return this.pluginCtx.relationService.findByFromAndType(from, relationType, RelationTypeGroup.COMMON);
  432 + return this.pluginCtx.relationService.findByFromAndTypeAsync(from, relationType, RelationTypeGroup.COMMON);
433 433 }
434 434
435 435 @Override
436 436 public ListenableFuture<List<EntityRelation>> findByToAndType(EntityId from, String relationType) {
437   - return this.pluginCtx.relationService.findByToAndType(from, relationType, RelationTypeGroup.COMMON);
  437 + return this.pluginCtx.relationService.findByToAndTypeAsync(from, relationType, RelationTypeGroup.COMMON);
438 438 }
439 439
440 440 @Override
... ...
... ... @@ -117,6 +117,10 @@ public abstract class BaseController {
117 117 @Autowired
118 118 protected RelationService relationService;
119 119
  120 + @ExceptionHandler(Exception.class)
  121 + public void handleException(Exception ex, HttpServletResponse response) {
  122 + errorResponseHandler.handle(ex, response);
  123 + }
120 124
121 125 @ExceptionHandler(ThingsboardException.class)
122 126 public void handleThingsboardException(ThingsboardException ex, HttpServletResponse response) {
... ...
... ... @@ -120,7 +120,7 @@ public class EntityRelationController extends BaseController {
120 120 checkEntityId(fromId);
121 121 checkEntityId(toId);
122 122 RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
123   - return checkNotNull(relationService.getRelation(fromId, toId, strRelationType, typeGroup).get());
  123 + return checkNotNull(relationService.getRelation(fromId, toId, strRelationType, typeGroup));
124 124 } catch (Exception e) {
125 125 throw handleException(e);
126 126 }
... ... @@ -138,7 +138,7 @@ public class EntityRelationController extends BaseController {
138 138 checkEntityId(entityId);
139 139 RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
140 140 try {
141   - return checkNotNull(relationService.findByFrom(entityId, typeGroup).get());
  141 + return checkNotNull(relationService.findByFrom(entityId, typeGroup));
142 142 } catch (Exception e) {
143 143 throw handleException(e);
144 144 }
... ... @@ -176,7 +176,7 @@ public class EntityRelationController extends BaseController {
176 176 checkEntityId(entityId);
177 177 RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
178 178 try {
179   - return checkNotNull(relationService.findByFromAndType(entityId, strRelationType, typeGroup).get());
  179 + return checkNotNull(relationService.findByFromAndType(entityId, strRelationType, typeGroup));
180 180 } catch (Exception e) {
181 181 throw handleException(e);
182 182 }
... ... @@ -194,7 +194,7 @@ public class EntityRelationController extends BaseController {
194 194 checkEntityId(entityId);
195 195 RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
196 196 try {
197   - return checkNotNull(relationService.findByTo(entityId, typeGroup).get());
  197 + return checkNotNull(relationService.findByTo(entityId, typeGroup));
198 198 } catch (Exception e) {
199 199 throw handleException(e);
200 200 }
... ... @@ -232,7 +232,7 @@ public class EntityRelationController extends BaseController {
232 232 checkEntityId(entityId);
233 233 RelationTypeGroup typeGroup = parseRelationTypeGroup(strRelationTypeGroup, RelationTypeGroup.COMMON);
234 234 try {
235   - return checkNotNull(relationService.findByToAndType(entityId, strRelationType, typeGroup).get());
  235 + return checkNotNull(relationService.findByToAndType(entityId, strRelationType, typeGroup));
236 236 } catch (Exception e) {
237 237 throw handleException(e);
238 238 }
... ...
... ... @@ -214,26 +214,11 @@ actors:
214 214 enabled: "${ACTORS_STATISTICS_ENABLED:true}"
215 215 persist_frequency: "${ACTORS_STATISTICS_PERSIST_FREQUENCY:3600000}"
216 216
217   -# Cache parameters
218 217 cache:
219   - # Enable/disable cache functionality.
220   - enabled: "${CACHE_ENABLED:false}"
221   - device_credentials:
222   - # Default time to store device credentials in cache, in seconds
223   - time_to_live: "${CACHE_DEVICE_CREDENTIAL_TTL:3600}"
224   - # Maximum size of the map. When maximum size is reached, the map is evicted based on the policy defined.
225   - max_size:
226   - # Max size policy options:
227   - # PER_NODE: Maximum number of map entries in each JVM.
228   - # PER_PARTITION: Maximum number of map entries within each partition.
229   - # USED_HEAP_SIZE: Maximum used heap size in megabytes for each JVM.
230   - # USED_HEAP_PERCENTAGE: Maximum used heap size percentage for each JVM.
231   - # FREE_HEAP_SIZE: Minimum free heap size in megabytes for each JVM.
232   - # FREE_HEAP_PERCENTAGE: Minimum free heap size percentage for each JVM.
233   - policy: "${CACHE_DEVICE_CREDENTIAL_MAX_SIZE_POLICY:PER_NODE}"
234   - size: "${CACHE_DEVICE_CREDENTIAL_MAX_SIZE_SIZE:1000000}"
  218 + # caffeine or redis
  219 + type: "${CACHE_TYPE:caffeine}"
235 220
236   -caching:
  221 +caffeine:
237 222 specs:
238 223 relations:
239 224 timeToLiveInMinutes: 1440
... ... @@ -245,6 +230,15 @@ caching:
245 230 timeToLiveInMinutes: 1440
246 231 maxSize: 100000
247 232
  233 +redis:
  234 + # standalone or cluster
  235 + connection:
  236 + type: standalone
  237 + host: "${REDIS_HOST:localhost}"
  238 + port: "${REDIS_PORT:6379}"
  239 + db: "${REDIS_DB:0}"
  240 + password: "${REDIS_PASSWORD:}"
  241 +
248 242 # Check new version updates parameters
249 243 updates:
250 244 # Enable/disable updates checking.
... ...
... ... @@ -19,7 +19,7 @@ import lombok.EqualsAndHashCode;
19 19 import org.thingsboard.server.common.data.id.UUIDBased;
20 20
21 21 @EqualsAndHashCode(callSuper = true)
22   -public abstract class ContactBased<I extends UUIDBased> extends SearchTextBased<I> {
  22 +public abstract class ContactBased<I extends UUIDBased> extends SearchTextBasedWithAdditionalInfo<I> {
23 23
24 24 private static final long serialVersionUID = 5047448057830660988L;
25 25
... ...
... ... @@ -29,8 +29,7 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
29 29
30 30 private String title;
31 31 private TenantId tenantId;
32   - private transient JsonNode additionalInfo;
33   -
  32 +
34 33 public Customer() {
35 34 super();
36 35 }
... ... @@ -43,7 +42,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
43 42 super(customer);
44 43 this.tenantId = customer.getTenantId();
45 44 this.title = customer.getTitle();
46   - this.additionalInfo = customer.getAdditionalInfo();
47 45 }
48 46
49 47 public TenantId getTenantId() {
... ... @@ -65,7 +63,7 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
65 63 @JsonIgnore
66 64 public boolean isPublic() {
67 65 if (getAdditionalInfo() != null && getAdditionalInfo().has("isPublic")) {
68   - return additionalInfo.get("isPublic").asBoolean();
  66 + return getAdditionalInfo().get("isPublic").asBoolean();
69 67 }
70 68
71 69 return false;
... ... @@ -77,14 +75,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
77 75 return title;
78 76 }
79 77
80   - public JsonNode getAdditionalInfo() {
81   - return additionalInfo;
82   - }
83   -
84   - public void setAdditionalInfo(JsonNode additionalInfo) {
85   - this.additionalInfo = additionalInfo;
86   - }
87   -
88 78 @Override
89 79 public String getSearchText() {
90 80 return getTitle();
... ... @@ -94,7 +84,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
94 84 public int hashCode() {
95 85 final int prime = 31;
96 86 int result = super.hashCode();
97   - result = prime * result + ((additionalInfo == null) ? 0 : additionalInfo.hashCode());
98 87 result = prime * result + ((tenantId == null) ? 0 : tenantId.hashCode());
99 88 result = prime * result + ((title == null) ? 0 : title.hashCode());
100 89 return result;
... ... @@ -109,11 +98,6 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
109 98 if (getClass() != obj.getClass())
110 99 return false;
111 100 Customer other = (Customer) obj;
112   - if (additionalInfo == null) {
113   - if (other.additionalInfo != null)
114   - return false;
115   - } else if (!additionalInfo.equals(other.additionalInfo))
116   - return false;
117 101 if (tenantId == null) {
118 102 if (other.tenantId != null)
119 103 return false;
... ... @@ -135,7 +119,7 @@ public class Customer extends ContactBased<CustomerId> implements HasName {
135 119 builder.append(", tenantId=");
136 120 builder.append(tenantId);
137 121 builder.append(", additionalInfo=");
138   - builder.append(additionalInfo);
  122 + builder.append(getAdditionalInfo());
139 123 builder.append(", country=");
140 124 builder.append(country);
141 125 builder.append(", state=");
... ...
... ... @@ -23,7 +23,7 @@ import org.thingsboard.server.common.data.id.TenantId;
23 23 import com.fasterxml.jackson.databind.JsonNode;
24 24
25 25 @EqualsAndHashCode(callSuper = true)
26   -public class Device extends SearchTextBased<DeviceId> implements HasName {
  26 +public class Device extends SearchTextBasedWithAdditionalInfo<DeviceId> implements HasName {
27 27
28 28 private static final long serialVersionUID = 2807343040519543363L;
29 29
... ... @@ -31,7 +31,6 @@ public class Device extends SearchTextBased<DeviceId> implements HasName {
31 31 private CustomerId customerId;
32 32 private String name;
33 33 private String type;
34   - private transient JsonNode additionalInfo;
35 34
36 35 public Device() {
37 36 super();
... ... @@ -47,7 +46,6 @@ public class Device extends SearchTextBased<DeviceId> implements HasName {
47 46 this.customerId = device.getCustomerId();
48 47 this.name = device.getName();
49 48 this.type = device.getType();
50   - this.additionalInfo = device.getAdditionalInfo();
51 49 }
52 50
53 51 public TenantId getTenantId() {
... ... @@ -83,14 +81,6 @@ public class Device extends SearchTextBased<DeviceId> implements HasName {
83 81 this.type = type;
84 82 }
85 83
86   - public JsonNode getAdditionalInfo() {
87   - return additionalInfo;
88   - }
89   -
90   - public void setAdditionalInfo(JsonNode additionalInfo) {
91   - this.additionalInfo = additionalInfo;
92   - }
93   -
94 84 @Override
95 85 public String getSearchText() {
96 86 return getName();
... ... @@ -108,7 +98,7 @@ public class Device extends SearchTextBased<DeviceId> implements HasName {
108 98 builder.append(", type=");
109 99 builder.append(type);
110 100 builder.append(", additionalInfo=");
111   - builder.append(additionalInfo);
  101 + builder.append(getAdditionalInfo());
112 102 builder.append(", createdTime=");
113 103 builder.append(createdTime);
114 104 builder.append(", id=");
... ...
  1 +/**
  2 + * Copyright © 2016-2017 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data;
  17 +
  18 +import com.fasterxml.jackson.databind.JsonNode;
  19 +
  20 +public interface HasAdditionalInfo {
  21 +
  22 + JsonNode getAdditionalInfo();
  23 +
  24 +}
... ...
  1 +/**
  2 + * Copyright © 2016-2017 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.common.data;
  17 +
  18 +import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import com.fasterxml.jackson.core.JsonProcessingException;
  20 +import com.fasterxml.jackson.databind.JsonNode;
  21 +import com.fasterxml.jackson.databind.ObjectMapper;
  22 +import lombok.extern.slf4j.Slf4j;
  23 +import org.thingsboard.server.common.data.id.UUIDBased;
  24 +
  25 +import java.io.ByteArrayInputStream;
  26 +import java.io.IOException;
  27 +import java.util.Arrays;
  28 +import java.util.Objects;
  29 +import java.util.function.Supplier;
  30 +import java.util.function.Consumer;
  31 +
  32 +/**
  33 + * Created by ashvayka on 19.02.18.
  34 + */
  35 +@Slf4j
  36 +public abstract class SearchTextBasedWithAdditionalInfo<I extends UUIDBased> extends SearchTextBased<I> implements HasAdditionalInfo {
  37 +
  38 + private transient JsonNode additionalInfo;
  39 + @JsonIgnore
  40 + private byte[] additionalInfoBytes;
  41 +
  42 + public SearchTextBasedWithAdditionalInfo() {
  43 + super();
  44 + }
  45 +
  46 + public SearchTextBasedWithAdditionalInfo(I id) {
  47 + super(id);
  48 + }
  49 +
  50 + public SearchTextBasedWithAdditionalInfo(SearchTextBasedWithAdditionalInfo<I> searchTextBased) {
  51 + super(searchTextBased);
  52 + setAdditionalInfo(searchTextBased.getAdditionalInfo());
  53 + }
  54 +
  55 + @Override
  56 + public JsonNode getAdditionalInfo() {
  57 + return getJson(() -> additionalInfo, () -> additionalInfoBytes);
  58 + }
  59 +
  60 + public void setAdditionalInfo(JsonNode addInfo) {
  61 + setJson(addInfo, json -> this.additionalInfo = json, bytes -> this.additionalInfoBytes = bytes);
  62 + }
  63 +
  64 + @Override
  65 + public boolean equals(Object o) {
  66 + if (this == o) return true;
  67 + if (o == null || getClass() != o.getClass()) return false;
  68 + if (!super.equals(o)) return false;
  69 + SearchTextBasedWithAdditionalInfo<?> that = (SearchTextBasedWithAdditionalInfo<?>) o;
  70 + return Arrays.equals(additionalInfoBytes, that.additionalInfoBytes);
  71 + }
  72 +
  73 + @Override
  74 + public int hashCode() {
  75 + return Objects.hash(super.hashCode(), additionalInfoBytes);
  76 + }
  77 +
  78 + public static JsonNode getJson(Supplier<JsonNode> jsonData, Supplier<byte[]> binaryData) {
  79 + JsonNode json = jsonData.get();
  80 + if (json != null) {
  81 + return json;
  82 + } else {
  83 + byte[] data = binaryData.get();
  84 + if (data != null) {
  85 + try {
  86 + return new ObjectMapper().readTree(new ByteArrayInputStream(data));
  87 + } catch (IOException e) {
  88 + log.warn("Can't deserialize json data: ", e);
  89 + return null;
  90 + }
  91 + } else {
  92 + return null;
  93 + }
  94 + }
  95 + }
  96 +
  97 + public static void setJson(JsonNode json, Consumer<JsonNode> jsonConsumer, Consumer<byte[]> bytesConsumer) {
  98 + jsonConsumer.accept(json);
  99 + try {
  100 + bytesConsumer.accept(new ObjectMapper().writeValueAsBytes(json));
  101 + } catch (JsonProcessingException e) {
  102 + log.warn("Can't serialize json data: ", e);
  103 + }
  104 + }
  105 +}
... ...
... ... @@ -28,8 +28,7 @@ public class Tenant extends ContactBased<TenantId> implements HasName {
28 28
29 29 private String title;
30 30 private String region;
31   - private transient JsonNode additionalInfo;
32   -
  31 +
33 32 public Tenant() {
34 33 super();
35 34 }
... ... @@ -42,7 +41,6 @@ public class Tenant extends ContactBased<TenantId> implements HasName {
42 41 super(tenant);
43 42 this.title = tenant.getTitle();
44 43 this.region = tenant.getRegion();
45   - this.additionalInfo = tenant.getAdditionalInfo();
46 44 }
47 45
48 46 public String getTitle() {
... ... @@ -67,14 +65,6 @@ public class Tenant extends ContactBased<TenantId> implements HasName {
67 65 this.region = region;
68 66 }
69 67
70   - public JsonNode getAdditionalInfo() {
71   - return additionalInfo;
72   - }
73   -
74   - public void setAdditionalInfo(JsonNode additionalInfo) {
75   - this.additionalInfo = additionalInfo;
76   - }
77   -
78 68 @Override
79 69 public String getSearchText() {
80 70 return getTitle();
... ... @@ -88,7 +78,7 @@ public class Tenant extends ContactBased<TenantId> implements HasName {
88 78 builder.append(", region=");
89 79 builder.append(region);
90 80 builder.append(", additionalInfo=");
91   - builder.append(additionalInfo);
  81 + builder.append(getAdditionalInfo());
92 82 builder.append(", country=");
93 83 builder.append(country);
94 84 builder.append(", state=");
... ...
... ... @@ -25,7 +25,7 @@ import org.thingsboard.server.common.data.security.Authority;
25 25 import com.fasterxml.jackson.databind.JsonNode;
26 26
27 27 @EqualsAndHashCode(callSuper = true)
28   -public class User extends SearchTextBased<UserId> implements HasName {
  28 +public class User extends SearchTextBasedWithAdditionalInfo<UserId> implements HasName {
29 29
30 30 private static final long serialVersionUID = 8250339805336035966L;
31 31
... ... @@ -35,7 +35,6 @@ public class User extends SearchTextBased<UserId> implements HasName {
35 35 private Authority authority;
36 36 private String firstName;
37 37 private String lastName;
38   - private transient JsonNode additionalInfo;
39 38
40 39 public User() {
41 40 super();
... ... @@ -53,7 +52,6 @@ public class User extends SearchTextBased<UserId> implements HasName {
53 52 this.authority = user.getAuthority();
54 53 this.firstName = user.getFirstName();
55 54 this.lastName = user.getLastName();
56   - this.additionalInfo = user.getAdditionalInfo();
57 55 }
58 56
59 57 public TenantId getTenantId() {
... ... @@ -110,14 +108,6 @@ public class User extends SearchTextBased<UserId> implements HasName {
110 108 this.lastName = lastName;
111 109 }
112 110
113   - public JsonNode getAdditionalInfo() {
114   - return additionalInfo;
115   - }
116   -
117   - public void setAdditionalInfo(JsonNode additionalInfo) {
118   - this.additionalInfo = additionalInfo;
119   - }
120   -
121 111 @Override
122 112 public String getSearchText() {
123 113 return getEmail();
... ... @@ -139,7 +129,7 @@ public class User extends SearchTextBased<UserId> implements HasName {
139 129 builder.append(", lastName=");
140 130 builder.append(lastName);
141 131 builder.append(", additionalInfo=");
142   - builder.append(additionalInfo);
  132 + builder.append(getAdditionalInfo());
143 133 builder.append(", createdTime=");
144 134 builder.append(createdTime);
145 135 builder.append(", id=");
... ...
... ... @@ -17,14 +17,16 @@ package org.thingsboard.server.common.data.asset;
17 17
18 18 import com.fasterxml.jackson.databind.JsonNode;
19 19 import lombok.EqualsAndHashCode;
  20 +import org.thingsboard.server.common.data.HasAdditionalInfo;
20 21 import org.thingsboard.server.common.data.HasName;
21 22 import org.thingsboard.server.common.data.SearchTextBased;
  23 +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
22 24 import org.thingsboard.server.common.data.id.AssetId;
23 25 import org.thingsboard.server.common.data.id.CustomerId;
24 26 import org.thingsboard.server.common.data.id.TenantId;
25 27
26 28 @EqualsAndHashCode(callSuper = true)
27   -public class Asset extends SearchTextBased<AssetId> implements HasName {
  29 +public class Asset extends SearchTextBasedWithAdditionalInfo<AssetId> implements HasName {
28 30
29 31 private static final long serialVersionUID = 2807343040519543363L;
30 32
... ... @@ -32,7 +34,6 @@ public class Asset extends SearchTextBased<AssetId> implements HasName {
32 34 private CustomerId customerId;
33 35 private String name;
34 36 private String type;
35   - private transient JsonNode additionalInfo;
36 37
37 38 public Asset() {
38 39 super();
... ... @@ -48,7 +49,6 @@ public class Asset extends SearchTextBased<AssetId> implements HasName {
48 49 this.customerId = asset.getCustomerId();
49 50 this.name = asset.getName();
50 51 this.type = asset.getType();
51   - this.additionalInfo = asset.getAdditionalInfo();
52 52 }
53 53
54 54 public TenantId getTenantId() {
... ... @@ -84,14 +84,6 @@ public class Asset extends SearchTextBased<AssetId> implements HasName {
84 84 this.type = type;
85 85 }
86 86
87   - public JsonNode getAdditionalInfo() {
88   - return additionalInfo;
89   - }
90   -
91   - public void setAdditionalInfo(JsonNode additionalInfo) {
92   - this.additionalInfo = additionalInfo;
93   - }
94   -
95 87 @Override
96 88 public String getSearchText() {
97 89 return getName();
... ... @@ -109,7 +101,7 @@ public class Asset extends SearchTextBased<AssetId> implements HasName {
109 101 builder.append(", type=");
110 102 builder.append(type);
111 103 builder.append(", additionalInfo=");
112   - builder.append(additionalInfo);
  104 + builder.append(getAdditionalInfo());
113 105 builder.append(", createdTime=");
114 106 builder.append(createdTime);
115 107 builder.append(", id=");
... ...
... ... @@ -15,16 +15,24 @@
15 15 */
16 16 package org.thingsboard.server.common.data.plugin;
17 17
  18 +import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import com.fasterxml.jackson.core.JsonProcessingException;
  20 +import com.fasterxml.jackson.databind.ObjectMapper;
18 21 import lombok.EqualsAndHashCode;
  22 +import lombok.extern.slf4j.Slf4j;
19 23 import org.thingsboard.server.common.data.HasName;
20   -import org.thingsboard.server.common.data.SearchTextBased;
  24 +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
21 25 import org.thingsboard.server.common.data.id.PluginId;
22 26 import org.thingsboard.server.common.data.id.TenantId;
23 27
24 28 import com.fasterxml.jackson.databind.JsonNode;
25 29
  30 +import java.io.ByteArrayInputStream;
  31 +import java.io.IOException;
  32 +
26 33 @EqualsAndHashCode(callSuper = true)
27   -public class PluginMetaData extends SearchTextBased<PluginId> implements HasName {
  34 +@Slf4j
  35 +public class PluginMetaData extends SearchTextBasedWithAdditionalInfo<PluginId> implements HasName {
28 36
29 37 private static final long serialVersionUID = 1L;
30 38
... ... @@ -35,7 +43,9 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName
35 43 private boolean publicAccess;
36 44 private ComponentLifecycleState state;
37 45 private transient JsonNode configuration;
38   - private transient JsonNode additionalInfo;
  46 + @JsonIgnore
  47 + private byte[] configurationBytes;
  48 +
39 49
40 50 public PluginMetaData() {
41 51 super();
... ... @@ -54,7 +64,6 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName
54 64 this.publicAccess = plugin.isPublicAccess();
55 65 this.state = plugin.getState();
56 66 this.configuration = plugin.getConfiguration();
57   - this.additionalInfo = plugin.getAdditionalInfo();
58 67 }
59 68
60 69 @Override
... ... @@ -96,11 +105,11 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName
96 105 }
97 106
98 107 public JsonNode getConfiguration() {
99   - return configuration;
  108 + return getJson(() -> configuration, () -> configurationBytes);
100 109 }
101 110
102   - public void setConfiguration(JsonNode configuration) {
103   - this.configuration = configuration;
  111 + public void setConfiguration(JsonNode data) {
  112 + setJson(data, json -> this.configuration = json, bytes -> this.configurationBytes = bytes);
104 113 }
105 114
106 115 public boolean isPublicAccess() {
... ... @@ -119,14 +128,6 @@ public class PluginMetaData extends SearchTextBased<PluginId> implements HasName
119 128 return state;
120 129 }
121 130
122   - public JsonNode getAdditionalInfo() {
123   - return additionalInfo;
124   - }
125   -
126   - public void setAdditionalInfo(JsonNode additionalInfo) {
127   - this.additionalInfo = additionalInfo;
128   - }
129   -
130 131 @Override
131 132 public String toString() {
132 133 return "PluginMetaData [apiToken=" + apiToken + ", tenantId=" + tenantId + ", name=" + name + ", clazz=" + clazz + ", publicAccess=" + publicAccess
... ...
... ... @@ -15,10 +15,20 @@
15 15 */
16 16 package org.thingsboard.server.common.data.relation;
17 17
  18 +import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import com.fasterxml.jackson.core.JsonProcessingException;
18 20 import com.fasterxml.jackson.databind.JsonNode;
  21 +import com.fasterxml.jackson.databind.ObjectMapper;
  22 +import lombok.extern.slf4j.Slf4j;
  23 +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
19 24 import org.thingsboard.server.common.data.id.EntityId;
20 25
21   -public class EntityRelation {
  26 +import java.io.ByteArrayInputStream;
  27 +import java.io.IOException;
  28 +import java.io.Serializable;
  29 +
  30 +@Slf4j
  31 +public class EntityRelation implements Serializable {
22 32
23 33 private static final long serialVersionUID = 2807343040519543363L;
24 34
... ... @@ -29,7 +39,9 @@ public class EntityRelation {
29 39 private EntityId to;
30 40 private String type;
31 41 private RelationTypeGroup typeGroup;
32   - private JsonNode additionalInfo;
  42 + private transient JsonNode additionalInfo;
  43 + @JsonIgnore
  44 + private byte[] additionalInfoBytes;
33 45
34 46 public EntityRelation() {
35 47 super();
... ... @@ -92,11 +104,11 @@ public class EntityRelation {
92 104 }
93 105
94 106 public JsonNode getAdditionalInfo() {
95   - return additionalInfo;
  107 + return SearchTextBasedWithAdditionalInfo.getJson(() -> additionalInfo, () -> additionalInfoBytes);
96 108 }
97 109
98   - public void setAdditionalInfo(JsonNode additionalInfo) {
99   - this.additionalInfo = additionalInfo;
  110 + public void setAdditionalInfo(JsonNode addInfo) {
  111 + SearchTextBasedWithAdditionalInfo.setJson(addInfo, json -> this.additionalInfo = json, bytes -> this.additionalInfoBytes = bytes);
100 112 }
101 113
102 114 @Override
... ...
... ... @@ -15,18 +15,23 @@
15 15 */
16 16 package org.thingsboard.server.common.data.rule;
17 17
  18 +import com.fasterxml.jackson.annotation.JsonIgnore;
  19 +import com.fasterxml.jackson.core.JsonProcessingException;
18 20 import com.fasterxml.jackson.databind.JsonNode;
  21 +import com.fasterxml.jackson.databind.ObjectMapper;
19 22 import lombok.Data;
20 23 import lombok.EqualsAndHashCode;
  24 +import lombok.extern.slf4j.Slf4j;
21 25 import org.thingsboard.server.common.data.HasName;
22   -import org.thingsboard.server.common.data.SearchTextBased;
  26 +import org.thingsboard.server.common.data.SearchTextBasedWithAdditionalInfo;
23 27 import org.thingsboard.server.common.data.id.RuleId;
24 28 import org.thingsboard.server.common.data.id.TenantId;
25 29 import org.thingsboard.server.common.data.plugin.ComponentLifecycleState;
26 30
27 31 @Data
28 32 @EqualsAndHashCode(callSuper = true)
29   -public class RuleMetaData extends SearchTextBased<RuleId> implements HasName {
  33 +@Slf4j
  34 +public class RuleMetaData extends SearchTextBasedWithAdditionalInfo<RuleId> implements HasName {
30 35
31 36 private static final long serialVersionUID = -5656679015122935465L;
32 37
... ... @@ -38,7 +43,13 @@ public class RuleMetaData extends SearchTextBased<RuleId> implements HasName {
38 43 private transient JsonNode filters;
39 44 private transient JsonNode processor;
40 45 private transient JsonNode action;
41   - private transient JsonNode additionalInfo;
  46 + @JsonIgnore
  47 + private byte[] filtersBytes;
  48 + @JsonIgnore
  49 + private byte[] processorBytes;
  50 + @JsonIgnore
  51 + private byte[] actionBytes;
  52 +
42 53
43 54 public RuleMetaData() {
44 55 super();
... ... @@ -55,10 +66,9 @@ public class RuleMetaData extends SearchTextBased<RuleId> implements HasName {
55 66 this.state = rule.getState();
56 67 this.weight = rule.getWeight();
57 68 this.pluginToken = rule.getPluginToken();
58   - this.filters = rule.getFilters();
59   - this.processor = rule.getProcessor();
60   - this.action = rule.getAction();
61   - this.additionalInfo = rule.getAdditionalInfo();
  69 + this.setFilters(rule.getFilters());
  70 + this.setProcessor(rule.getProcessor());
  71 + this.setAction(rule.getAction());
62 72 }
63 73
64 74 @Override
... ... @@ -71,4 +81,29 @@ public class RuleMetaData extends SearchTextBased<RuleId> implements HasName {
71 81 return name;
72 82 }
73 83
  84 + public JsonNode getFilters() {
  85 + return SearchTextBasedWithAdditionalInfo.getJson(() -> filters, () -> filtersBytes);
  86 + }
  87 +
  88 + public JsonNode getProcessor() {
  89 + return SearchTextBasedWithAdditionalInfo.getJson(() -> processor, () -> processorBytes);
  90 + }
  91 +
  92 + public JsonNode getAction() {
  93 + return SearchTextBasedWithAdditionalInfo.getJson(() -> action, () -> actionBytes);
  94 + }
  95 +
  96 + public void setFilters(JsonNode data) {
  97 + setJson(data, json -> this.filters = json, bytes -> this.filtersBytes = bytes);
  98 + }
  99 +
  100 + public void setProcessor(JsonNode data) {
  101 + setJson(data, json -> this.processor = json, bytes -> this.processorBytes = bytes);
  102 + }
  103 +
  104 + public void setAction(JsonNode data) {
  105 + setJson(data, json -> this.action = json, bytes -> this.actionBytes = bytes);
  106 + }
  107 +
  108 +
74 109 }
... ...
... ... @@ -182,6 +182,14 @@
182 182 <groupId>org.springframework</groupId>
183 183 <artifactId>spring-context-support</artifactId>
184 184 </dependency>
  185 + <dependency>
  186 + <groupId>org.springframework.data</groupId>
  187 + <artifactId>spring-data-redis</artifactId>
  188 + </dependency>
  189 + <dependency>
  190 + <groupId>redis.clients</groupId>
  191 + <artifactId>jedis</artifactId>
  192 + </dependency>
185 193 </dependencies>
186 194 <build>
187 195 <plugins>
... ...
... ... @@ -337,7 +337,7 @@ public class BaseAlarmService extends AbstractEntityService implements AlarmServ
337 337
338 338 private void updateRelations(Alarm alarm, AlarmStatus oldStatus, AlarmStatus newStatus) {
339 339 try {
340   - List<EntityRelation> relations = relationService.findByTo(alarm.getId(), RelationTypeGroup.ALARM).get();
  340 + List<EntityRelation> relations = relationService.findByToAsync(alarm.getId(), RelationTypeGroup.ALARM).get();
341 341 Set<EntityId> parents = relations.stream().map(EntityRelation::getFrom).collect(Collectors.toSet());
342 342 for (EntityId parentId : parents) {
343 343 updateAlarmRelation(parentId, alarm.getId(), oldStatus, newStatus);
... ...
dao/src/main/java/org/thingsboard/server/dao/cache/CaffeineCacheConfiguration.java renamed from dao/src/main/java/org/thingsboard/server/dao/cache/ServiceCacheConfiguration.java
... ... @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.cache;
18 18 import com.github.benmanes.caffeine.cache.Caffeine;
19 19 import com.github.benmanes.caffeine.cache.Ticker;
20 20 import lombok.Data;
  21 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
21 22 import org.springframework.boot.context.properties.ConfigurationProperties;
22 23 import org.springframework.cache.CacheManager;
23 24 import org.springframework.cache.annotation.EnableCaching;
... ... @@ -33,10 +34,11 @@ import java.util.concurrent.TimeUnit;
33 34 import java.util.stream.Collectors;
34 35
35 36 @Configuration
36   -@ConfigurationProperties(prefix = "caching")
  37 +@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "caffeine", matchIfMissing = true)
  38 +@ConfigurationProperties(prefix = "caffeine")
37 39 @EnableCaching
38 40 @Data
39   -public class ServiceCacheConfiguration {
  41 +public class CaffeineCacheConfiguration {
40 42
41 43 private Map<String, CacheSpecs> specs;
42 44
... ...
  1 +/**
  2 + * Copyright © 2016-2017 The Thingsboard Authors
  3 + *
  4 + * Licensed under the Apache License, Version 2.0 (the "License");
  5 + * you may not use this file except in compliance with the License.
  6 + * You may obtain a copy of the License at
  7 + *
  8 + * http://www.apache.org/licenses/LICENSE-2.0
  9 + *
  10 + * Unless required by applicable law or agreed to in writing, software
  11 + * distributed under the License is distributed on an "AS IS" BASIS,
  12 + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 + * See the License for the specific language governing permissions and
  14 + * limitations under the License.
  15 + */
  16 +package org.thingsboard.server.dao.cache;
  17 +
  18 +import lombok.Data;
  19 +import org.springframework.beans.factory.annotation.Value;
  20 +import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
  21 +import org.springframework.boot.context.properties.ConfigurationProperties;
  22 +import org.springframework.cache.CacheManager;
  23 +import org.springframework.cache.annotation.EnableCaching;
  24 +import org.springframework.cache.interceptor.KeyGenerator;
  25 +import org.springframework.context.annotation.Bean;
  26 +import org.springframework.context.annotation.Configuration;
  27 +import org.springframework.data.redis.cache.RedisCacheManager;
  28 +import org.springframework.data.redis.connection.RedisConnectionFactory;
  29 +import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
  30 +import org.springframework.data.redis.core.RedisTemplate;
  31 +
  32 +@Configuration
  33 +@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis", matchIfMissing = false)
  34 +@EnableCaching
  35 +@Data
  36 +public class TBRedisCacheConfiguration {
  37 +
  38 + @Value("${redis.connection.host}")
  39 + private String host;
  40 +
  41 + @Value("${redis.connection.port}")
  42 + private Integer port;
  43 +
  44 + @Value("${redis.connection.db}")
  45 + private Integer db;
  46 +
  47 + @Value("${redis.connection.password}")
  48 + private String password;
  49 +
  50 + @Bean
  51 + public RedisConnectionFactory redisConnectionFactory() {
  52 + JedisConnectionFactory factory = new JedisConnectionFactory();
  53 + factory.setHostName(host);
  54 + factory.setPort(port);
  55 + factory.setDatabase(db);
  56 + factory.setPassword(password);
  57 + return factory;
  58 + }
  59 +
  60 + @Bean
  61 + public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) {
  62 + RedisTemplate<String, String> redisTemplate = new RedisTemplate<>();
  63 + redisTemplate.setConnectionFactory(cf);
  64 + return redisTemplate;
  65 + }
  66 +
  67 + @Bean
  68 + public CacheManager cacheManager(RedisTemplate redisTemplate) {
  69 + return new RedisCacheManager(redisTemplate);
  70 + }
  71 +
  72 + @Bean
  73 + public KeyGenerator previousDeviceCredentialsId() {
  74 + return new PreviousDeviceCredentialsIdKeyGenerator();
  75 + }
  76 +
  77 +
  78 +}
... ...
... ... @@ -64,19 +64,28 @@ public class BaseRelationService implements RelationService {
64 64 return relationDao.checkRelation(from, to, relationType, typeGroup);
65 65 }
66 66
67   - @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #to, #relationType}")
  67 + @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #to, #relationType, #typeGroup}")
68 68 @Override
69   - public ListenableFuture<EntityRelation> getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  69 + public EntityRelation getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
  70 + try {
  71 + return getRelationAsync(from, to, relationType, typeGroup).get();
  72 + } catch (InterruptedException | ExecutionException e) {
  73 + throw new RuntimeException(e);
  74 + }
  75 + }
  76 +
  77 + @Override
  78 + public ListenableFuture<EntityRelation> getRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
70 79 log.trace("Executing EntityRelation [{}][{}][{}][{}]", from, to, relationType, typeGroup);
71 80 validate(from, to, relationType, typeGroup);
72 81 return relationDao.getRelation(from, to, relationType, typeGroup);
73 82 }
74 83
75 84 @Caching(evict = {
76   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.from"),
77   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"),
78   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"),
79   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}")
  85 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.typeGroup}"),
  86 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type, #relation.typeGroup}"),
  87 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.typeGroup}"),
  88 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup}")
80 89 })
81 90 @Override
82 91 public boolean saveRelation(EntityRelation relation) {
... ... @@ -86,10 +95,10 @@ public class BaseRelationService implements RelationService {
86 95 }
87 96
88 97 @Caching(evict = {
89   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.from"),
90   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"),
91   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"),
92   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}")
  98 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.typeGroup}"),
  99 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type, #relation.typeGroup}"),
  100 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.typeGroup}"),
  101 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup}")
93 102 })
94 103 @Override
95 104 public ListenableFuture<Boolean> saveRelationAsync(EntityRelation relation) {
... ... @@ -99,11 +108,11 @@ public class BaseRelationService implements RelationService {
99 108 }
100 109
101 110 @Caching(evict = {
102   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.from"),
103   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"),
104   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"),
105   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}"),
106   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type}")
  111 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.typeGroup}"),
  112 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type, #relation.typeGroup}"),
  113 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.typeGroup}"),
  114 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type, #relation.typeGroup}"),
  115 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type, #relation.typeGroup}")
107 116 })
108 117 @Override
109 118 public boolean deleteRelation(EntityRelation relation) {
... ... @@ -117,7 +126,7 @@ public class BaseRelationService implements RelationService {
117 126 @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.type}"),
118 127 @CacheEvict(cacheNames = RELATIONS_CACHE, key = "#relation.to"),
119 128 @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.to, #relation.type}"),
120   - @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type}")
  129 + @CacheEvict(cacheNames = RELATIONS_CACHE, key = "{#relation.from, #relation.to, #relation.type, #relation.typeGroup}")
121 130 })
122 131 @Override
123 132 public ListenableFuture<Boolean> deleteRelationAsync(EntityRelation relation) {
... ... @@ -218,9 +227,9 @@ public class BaseRelationService implements RelationService {
218 227 ListenableFuture<List<List<EntityRelation>>> inboundRelationsTo = Futures.allAsList(inboundRelationsListTo);
219 228 ListenableFuture<List<Boolean>> inboundDeletions = Futures.transform(inboundRelationsTo,
220 229 (AsyncFunction<List<List<EntityRelation>>, List<Boolean>>) relations -> {
221   - List<ListenableFuture<Boolean>> results = getListenableFutures(relations, cache, true);
222   - return Futures.allAsList(results);
223   - });
  230 + List<ListenableFuture<Boolean>> results = getListenableFutures(relations, cache, true);
  231 + return Futures.allAsList(results);
  232 + });
224 233
225 234 ListenableFuture<Boolean> inboundFuture = Futures.transform(inboundDeletions, getListToBooleanFunction());
226 235
... ... @@ -272,9 +281,18 @@ public class BaseRelationService implements RelationService {
272 281 cache.evict(fromToAndType);
273 282 }
274 283
275   - @Cacheable(cacheNames = RELATIONS_CACHE, key = "#from")
  284 + @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #typeGroup}")
  285 + @Override
  286 + public List<EntityRelation> findByFrom(EntityId from, RelationTypeGroup typeGroup) {
  287 + try {
  288 + return findByFromAsync(from, typeGroup).get();
  289 + } catch (InterruptedException | ExecutionException e) {
  290 + throw new RuntimeException(e);
  291 + }
  292 + }
  293 +
276 294 @Override
277   - public ListenableFuture<List<EntityRelation>> findByFrom(EntityId from, RelationTypeGroup typeGroup) {
  295 + public ListenableFuture<List<EntityRelation>> findByFromAsync(EntityId from, RelationTypeGroup typeGroup) {
278 296 log.trace("Executing findByFrom [{}][{}]", from, typeGroup);
279 297 validate(from);
280 298 validateTypeGroup(typeGroup);
... ... @@ -300,9 +318,18 @@ public class BaseRelationService implements RelationService {
300 318 return relationsInfo;
301 319 }
302 320
303   - @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #relationType}")
  321 + @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#from, #relationType, #typeGroup}")
  322 + @Override
  323 + public List<EntityRelation> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) {
  324 + try {
  325 + return findByFromAndTypeAsync(from, relationType, typeGroup).get();
  326 + } catch (InterruptedException | ExecutionException e) {
  327 + throw new RuntimeException(e);
  328 + }
  329 + }
  330 +
304 331 @Override
305   - public ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup) {
  332 + public ListenableFuture<List<EntityRelation>> findByFromAndTypeAsync(EntityId from, String relationType, RelationTypeGroup typeGroup) {
306 333 log.trace("Executing findByFromAndType [{}][{}][{}]", from, relationType, typeGroup);
307 334 validate(from);
308 335 validateType(relationType);
... ... @@ -310,9 +337,18 @@ public class BaseRelationService implements RelationService {
310 337 return relationDao.findAllByFromAndType(from, relationType, typeGroup);
311 338 }
312 339
313   - @Cacheable(cacheNames = RELATIONS_CACHE, key = "#to")
  340 + @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #typeGroup}")
  341 + @Override
  342 + public List<EntityRelation> findByTo(EntityId to, RelationTypeGroup typeGroup) {
  343 + try {
  344 + return findByToAsync(to, typeGroup).get();
  345 + } catch (InterruptedException | ExecutionException e) {
  346 + throw new RuntimeException(e);
  347 + }
  348 + }
  349 +
314 350 @Override
315   - public ListenableFuture<List<EntityRelation>> findByTo(EntityId to, RelationTypeGroup typeGroup) {
  351 + public ListenableFuture<List<EntityRelation>> findByToAsync(EntityId to, RelationTypeGroup typeGroup) {
316 352 log.trace("Executing findByTo [{}][{}]", to, typeGroup);
317 353 validate(to);
318 354 validateTypeGroup(typeGroup);
... ... @@ -351,9 +387,18 @@ public class BaseRelationService implements RelationService {
351 387 return entityRelationInfo;
352 388 }
353 389
354   - @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #relationType}")
  390 + @Cacheable(cacheNames = RELATIONS_CACHE, key = "{#to, #relationType, #typeGroup}")
  391 + @Override
  392 + public List<EntityRelation> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) {
  393 + try {
  394 + return findByToAndTypeAsync(to, relationType, typeGroup).get();
  395 + } catch (InterruptedException | ExecutionException e) {
  396 + throw new RuntimeException(e);
  397 + }
  398 + }
  399 +
355 400 @Override
356   - public ListenableFuture<List<EntityRelation>> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup) {
  401 + public ListenableFuture<List<EntityRelation>> findByToAndTypeAsync(EntityId to, String relationType, RelationTypeGroup typeGroup) {
357 402 log.trace("Executing findByToAndType [{}][{}][{}]", to, relationType, typeGroup);
358 403 validate(to);
359 404 validateType(relationType);
... ... @@ -527,9 +572,9 @@ public class BaseRelationService implements RelationService {
527 572 private ListenableFuture<List<EntityRelation>> findRelations(final EntityId rootId, final EntitySearchDirection direction) {
528 573 ListenableFuture<List<EntityRelation>> relations;
529 574 if (direction == EntitySearchDirection.FROM) {
530   - relations = findByFrom(rootId, RelationTypeGroup.COMMON);
  575 + relations = findByFromAsync(rootId, RelationTypeGroup.COMMON);
531 576 } else {
532   - relations = findByTo(rootId, RelationTypeGroup.COMMON);
  577 + relations = findByToAsync(rootId, RelationTypeGroup.COMMON);
533 578 }
534 579 return relations;
535 580 }
... ...
... ... @@ -31,7 +31,9 @@ public interface RelationService {
31 31
32 32 ListenableFuture<Boolean> checkRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
33 33
34   - ListenableFuture<EntityRelation> getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  34 + EntityRelation getRelation(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
  35 +
  36 + ListenableFuture<EntityRelation> getRelationAsync(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup);
35 37
36 38 boolean saveRelation(EntityRelation relation);
37 39
... ... @@ -49,17 +51,25 @@ public interface RelationService {
49 51
50 52 ListenableFuture<Boolean> deleteEntityRelationsAsync(EntityId entity);
51 53
52   - ListenableFuture<List<EntityRelation>> findByFrom(EntityId from, RelationTypeGroup typeGroup);
  54 + List<EntityRelation> findByFrom(EntityId from, RelationTypeGroup typeGroup);
  55 +
  56 + ListenableFuture<List<EntityRelation>> findByFromAsync(EntityId from, RelationTypeGroup typeGroup);
53 57
54 58 ListenableFuture<List<EntityRelationInfo>> findInfoByFrom(EntityId from, RelationTypeGroup typeGroup);
55 59
56   - ListenableFuture<List<EntityRelation>> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup);
  60 + List<EntityRelation> findByFromAndType(EntityId from, String relationType, RelationTypeGroup typeGroup);
  61 +
  62 + ListenableFuture<List<EntityRelation>> findByFromAndTypeAsync(EntityId from, String relationType, RelationTypeGroup typeGroup);
57 63
58   - ListenableFuture<List<EntityRelation>> findByTo(EntityId to, RelationTypeGroup typeGroup);
  64 + List<EntityRelation> findByTo(EntityId to, RelationTypeGroup typeGroup);
  65 +
  66 + ListenableFuture<List<EntityRelation>> findByToAsync(EntityId to, RelationTypeGroup typeGroup);
59 67
60 68 ListenableFuture<List<EntityRelationInfo>> findInfoByTo(EntityId to, RelationTypeGroup typeGroup);
61 69
62   - ListenableFuture<List<EntityRelation>> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup);
  70 + List<EntityRelation> findByToAndType(EntityId to, String relationType, RelationTypeGroup typeGroup);
  71 +
  72 + ListenableFuture<List<EntityRelation>> findByToAndTypeAsync(EntityId to, String relationType, RelationTypeGroup typeGroup);
63 73
64 74 ListenableFuture<List<EntityRelation>> findByQuery(EntityRelationsQuery query);
65 75
... ...
... ... @@ -122,7 +122,7 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
122 122 saveRelation(relationB1);
123 123 saveRelation(relationB2);
124 124
125   - List<EntityRelation> relations = relationService.findByFrom(parentA, RelationTypeGroup.COMMON).get();
  125 + List<EntityRelation> relations = relationService.findByFrom(parentA, RelationTypeGroup.COMMON);
126 126 Assert.assertEquals(2, relations.size());
127 127 for (EntityRelation relation : relations) {
128 128 Assert.assertEquals(EntityRelation.CONTAINS_TYPE, relation.getType());
... ... @@ -130,13 +130,13 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
130 130 Assert.assertTrue(childA.equals(relation.getTo()) || childB.equals(relation.getTo()));
131 131 }
132 132
133   - relations = relationService.findByFromAndType(parentA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get();
  133 + relations = relationService.findByFromAndType(parentA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON);
134 134 Assert.assertEquals(2, relations.size());
135 135
136   - relations = relationService.findByFromAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get();
  136 + relations = relationService.findByFromAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON);
137 137 Assert.assertEquals(0, relations.size());
138 138
139   - relations = relationService.findByFrom(parentB, RelationTypeGroup.COMMON).get();
  139 + relations = relationService.findByFrom(parentB, RelationTypeGroup.COMMON);
140 140 Assert.assertEquals(2, relations.size());
141 141 for (EntityRelation relation : relations) {
142 142 Assert.assertEquals(EntityRelation.MANAGES_TYPE, relation.getType());
... ... @@ -144,10 +144,10 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
144 144 Assert.assertTrue(childA.equals(relation.getTo()) || childB.equals(relation.getTo()));
145 145 }
146 146
147   - relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get();
  147 + relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON);
148 148 Assert.assertEquals(0, relations.size());
149 149
150   - relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get();
  150 + relations = relationService.findByFromAndType(parentB, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON);
151 151 Assert.assertEquals(0, relations.size());
152 152 }
153 153
... ... @@ -177,26 +177,26 @@ public abstract class BaseRelationServiceTest extends AbstractServiceTest {
177 177 // Data propagation to views is async
178 178 Thread.sleep(3000);
179 179
180   - List<EntityRelation> relations = relationService.findByTo(childA, RelationTypeGroup.COMMON).get();
  180 + List<EntityRelation> relations = relationService.findByTo(childA, RelationTypeGroup.COMMON);
181 181 Assert.assertEquals(2, relations.size());
182 182 for (EntityRelation relation : relations) {
183 183 Assert.assertEquals(childA, relation.getTo());
184 184 Assert.assertTrue(parentA.equals(relation.getFrom()) || parentB.equals(relation.getFrom()));
185 185 }
186 186
187   - relations = relationService.findByToAndType(childA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON).get();
  187 + relations = relationService.findByToAndType(childA, EntityRelation.CONTAINS_TYPE, RelationTypeGroup.COMMON);
188 188 Assert.assertEquals(1, relations.size());
189 189
190   - relations = relationService.findByToAndType(childB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get();
  190 + relations = relationService.findByToAndType(childB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON);
191 191 Assert.assertEquals(1, relations.size());
192 192
193   - relations = relationService.findByToAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get();
  193 + relations = relationService.findByToAndType(parentA, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON);
194 194 Assert.assertEquals(0, relations.size());
195 195
196   - relations = relationService.findByToAndType(parentB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON).get();
  196 + relations = relationService.findByToAndType(parentB, EntityRelation.MANAGES_TYPE, RelationTypeGroup.COMMON);
197 197 Assert.assertEquals(0, relations.size());
198 198
199   - relations = relationService.findByTo(childB, RelationTypeGroup.COMMON).get();
  199 + relations = relationService.findByTo(childB, RelationTypeGroup.COMMON);
200 200 Assert.assertEquals(2, relations.size());
201 201 for (EntityRelation relation : relations) {
202 202 Assert.assertEquals(childB, relation.getTo());
... ...
1   -cache.enabled=false
2   -cache.device_credentials.time_to_live=3600
3   -cache.device_credentials.max_size.size=1000000
4   -cache.device_credentials.max_size.policy=PER_NODE
5   -
6 1 zk.enabled=false
7 2 zk.url=localhost:2181
8 3 zk.zk_dir=/thingsboard
9 4
10 5 updates.enabled=false
11 6
12   -caching.specs.relations.timeToLiveInMinutes=1440
13   -caching.specs.relations.maxSize=100000
  7 +cache.type=caffeine
  8 +#cache.type=redis
  9 +
  10 +caffeine.specs.relations.timeToLiveInMinutes=1440
  11 +caffeine.specs.relations.maxSize=100000
  12 +
  13 +caffeine.specs.deviceCredentials.timeToLiveInMinutes=1440
  14 +caffeine.specs.deviceCredentials.maxSize=100000
14 15
15   -caching.specs.deviceCredentials.timeToLiveInMinutes=1440
16   -caching.specs.deviceCredentials.maxSize=100000
  16 +caffeine.specs.devices.timeToLiveInMinutes=1440
  17 +caffeine.specs.devices.maxSize=100000
17 18
18   -caching.specs.devices.timeToLiveInMinutes=1440
19   -caching.specs.devices.maxSize=100000
\ No newline at end of file
  19 +redis.connection.host=localhost
  20 +redis.connection.port=6379
  21 +redis.connection.db=0
  22 +redis.connection.password=
\ No newline at end of file
... ...
  1 +#
  2 +# Copyright © 2016-2017 The Thingsboard Authors
  3 +#
  4 +# Licensed under the Apache License, Version 2.0 (the "License");
  5 +# you may not use this file except in compliance with the License.
  6 +# You may obtain a copy of the License at
  7 +#
  8 +# http://www.apache.org/licenses/LICENSE-2.0
  9 +#
  10 +# Unless required by applicable law or agreed to in writing, software
  11 +# distributed under the License is distributed on an "AS IS" BASIS,
  12 +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13 +# See the License for the specific language governing permissions and
  14 +# limitations under the License.
  15 +#
  16 +
  17 +version: '3.3'
  18 +services:
  19 + redis:
  20 + image: redis:4.0
  21 + networks:
  22 + - core
  23 + ports:
  24 + - "6379:6379"
  25 +
  26 +networks:
  27 + core:
... ...
... ... @@ -32,6 +32,8 @@
32 32 <spring-boot.version>1.4.3.RELEASE</spring-boot.version>
33 33 <spring.version>4.3.4.RELEASE</spring.version>
34 34 <spring-security.version>4.2.0.RELEASE</spring-security.version>
  35 + <spring-data-redis.version>1.8.10.RELEASE</spring-data-redis.version>
  36 + <jedis.version>2.9.0</jedis.version>
35 37 <jjwt.version>0.7.0</jjwt.version>
36 38 <json-path.version>2.2.0</json-path.version>
37 39 <junit.version>4.12</junit.version>
... ... @@ -784,6 +786,16 @@
784 786 <scope>test</scope>
785 787 </dependency>
786 788 <dependency>
  789 + <groupId>org.springframework.data</groupId>
  790 + <artifactId>spring-data-redis</artifactId>
  791 + <version>${spring-data-redis.version}</version>
  792 + </dependency>
  793 + <dependency>
  794 + <groupId>redis.clients</groupId>
  795 + <artifactId>jedis</artifactId>
  796 + <version>${jedis.version}</version>
  797 + </dependency>
  798 + <dependency>
787 799 <groupId>com.sun.winsw</groupId>
788 800 <artifactId>winsw</artifactId>
789 801 <version>${winsw.version}</version>
... ...