Commit c4cd601dcbbbec90a83dfe8508766f7dd94e5d53

Authored by Andrew Shvayka
1 parent 7d72a467

Improvements to Tenant rules and plugins startup sequence

Showing 18 changed files with 114 additions and 97 deletions
@@ -136,6 +136,9 @@ public class ActorSystemContext { @@ -136,6 +136,9 @@ public class ActorSystemContext {
136 @Value("${actors.statistics.persist_frequency}") 136 @Value("${actors.statistics.persist_frequency}")
137 @Getter private long statisticsPersistFrequency; 137 @Getter private long statisticsPersistFrequency;
138 138
  139 + @Value("${actors.tenant.create_components_on_init}")
  140 + @Getter private boolean tenantComponentsInitEnabled;
  141 +
139 @Getter @Setter private ActorSystem actorSystem; 142 @Getter @Setter private ActorSystem actorSystem;
140 143
141 @Getter @Setter private ActorRef appActor; 144 @Getter @Setter private ActorRef appActor;
@@ -174,7 +174,7 @@ public class AppActor extends ContextAwareActor { @@ -174,7 +174,7 @@ public class AppActor extends ContextAwareActor {
174 TenantId tenantId = toDeviceActorMsg.getTenantId(); 174 TenantId tenantId = toDeviceActorMsg.getTenantId();
175 ActorRef tenantActor = getOrCreateTenantActor(tenantId); 175 ActorRef tenantActor = getOrCreateTenantActor(tenantId);
176 if (toDeviceActorMsg.getPayload().getMsgType().requiresRulesProcessing()) { 176 if (toDeviceActorMsg.getPayload().getMsgType().requiresRulesProcessing()) {
177 - tenantActor.tell(new RuleChainDeviceMsg(toDeviceActorMsg, ruleManager.getRuleChain()), context().self()); 177 + tenantActor.tell(new RuleChainDeviceMsg(toDeviceActorMsg, ruleManager.getRuleChain(this.context())), context().self());
178 } else { 178 } else {
179 tenantActor.tell(toDeviceActorMsg, context().self()); 179 tenantActor.tell(toDeviceActorMsg, context().self());
180 } 180 }
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.actors.shared.plugin; 16 package org.thingsboard.server.actors.shared.plugin;
17 17
  18 +import akka.actor.ActorContext;
18 import org.thingsboard.server.actors.ActorSystemContext; 19 import org.thingsboard.server.actors.ActorSystemContext;
19 import org.thingsboard.server.actors.service.DefaultActorService; 20 import org.thingsboard.server.actors.service.DefaultActorService;
20 import org.thingsboard.server.common.data.id.TenantId; 21 import org.thingsboard.server.common.data.id.TenantId;
@@ -30,6 +31,12 @@ public class TenantPluginManager extends PluginManager { @@ -30,6 +31,12 @@ public class TenantPluginManager extends PluginManager {
30 this.tenantId = tenantId; 31 this.tenantId = tenantId;
31 } 32 }
32 33
  34 + public void init(ActorContext context) {
  35 + if (systemContext.isTenantComponentsInitEnabled()) {
  36 + super.init(context);
  37 + }
  38 + }
  39 +
33 @Override 40 @Override
34 FetchFunction<PluginMetaData> getFetchPluginsFunction() { 41 FetchFunction<PluginMetaData> getFetchPluginsFunction() {
35 return link -> pluginService.findTenantPlugins(tenantId, link); 42 return link -> pluginService.findTenantPlugins(tenantId, link);
@@ -25,7 +25,6 @@ import org.thingsboard.server.actors.rule.RuleActorChain; @@ -25,7 +25,6 @@ import org.thingsboard.server.actors.rule.RuleActorChain;
25 import org.thingsboard.server.actors.rule.RuleActorMetaData; 25 import org.thingsboard.server.actors.rule.RuleActorMetaData;
26 import org.thingsboard.server.actors.rule.SimpleRuleActorChain; 26 import org.thingsboard.server.actors.rule.SimpleRuleActorChain;
27 import org.thingsboard.server.actors.service.ContextAwareActor; 27 import org.thingsboard.server.actors.service.ContextAwareActor;
28 -import org.thingsboard.server.actors.service.DefaultActorService;  
29 import org.thingsboard.server.common.data.id.RuleId; 28 import org.thingsboard.server.common.data.id.RuleId;
30 import org.thingsboard.server.common.data.id.TenantId; 29 import org.thingsboard.server.common.data.id.TenantId;
31 import org.thingsboard.server.common.data.page.PageDataIterable; 30 import org.thingsboard.server.common.data.page.PageDataIterable;
@@ -72,6 +71,9 @@ public abstract class RuleManager { @@ -72,6 +71,9 @@ public abstract class RuleManager {
72 } 71 }
73 72
74 public Optional<ActorRef> update(ActorContext context, RuleId ruleId, ComponentLifecycleEvent event) { 73 public Optional<ActorRef> update(ActorContext context, RuleId ruleId, ComponentLifecycleEvent event) {
  74 + if (ruleMap == null) {
  75 + init(context);
  76 + }
75 RuleMetaData rule; 77 RuleMetaData rule;
76 if (event != ComponentLifecycleEvent.DELETED) { 78 if (event != ComponentLifecycleEvent.DELETED) {
77 rule = systemContext.getRuleService().findRuleById(ruleId); 79 rule = systemContext.getRuleService().findRuleById(ruleId);
@@ -111,11 +113,13 @@ public abstract class RuleManager { @@ -111,11 +113,13 @@ public abstract class RuleManager {
111 .withDispatcher(getDispatcherName()), rId.toString())); 113 .withDispatcher(getDispatcherName()), rId.toString()));
112 } 114 }
113 115
114 - public RuleActorChain getRuleChain() { 116 + public RuleActorChain getRuleChain(ActorContext context) {
  117 + if (ruleMap == null) {
  118 + init(context);
  119 + }
115 return ruleChain; 120 return ruleChain;
116 } 121 }
117 122
118 -  
119 private void refreshRuleChain() { 123 private void refreshRuleChain() {
120 Set<RuleActorMetaData> activeRuleSet = new HashSet<>(); 124 Set<RuleActorMetaData> activeRuleSet = new HashSet<>();
121 for (Map.Entry<RuleMetaData, RuleActorMetaData> rule : ruleMap.entrySet()) { 125 for (Map.Entry<RuleMetaData, RuleActorMetaData> rule : ruleMap.entrySet()) {
@@ -15,6 +15,7 @@ @@ -15,6 +15,7 @@
15 */ 15 */
16 package org.thingsboard.server.actors.shared.rule; 16 package org.thingsboard.server.actors.shared.rule;
17 17
  18 +import akka.actor.ActorContext;
18 import org.thingsboard.server.actors.ActorSystemContext; 19 import org.thingsboard.server.actors.ActorSystemContext;
19 import org.thingsboard.server.actors.service.DefaultActorService; 20 import org.thingsboard.server.actors.service.DefaultActorService;
20 import org.thingsboard.server.common.data.id.TenantId; 21 import org.thingsboard.server.common.data.id.TenantId;
@@ -27,6 +28,12 @@ public class TenantRuleManager extends RuleManager { @@ -27,6 +28,12 @@ public class TenantRuleManager extends RuleManager {
27 super(systemContext, tenantId); 28 super(systemContext, tenantId);
28 } 29 }
29 30
  31 + public void init(ActorContext context) {
  32 + if (systemContext.isTenantComponentsInitEnabled()) {
  33 + super.init(context);
  34 + }
  35 + }
  36 +
30 @Override 37 @Override
31 FetchFunction<RuleMetaData> getFetchRulesFunction() { 38 FetchFunction<RuleMetaData> getFetchRulesFunction() {
32 return link -> ruleService.findTenantRules(tenantId, link); 39 return link -> ruleService.findTenantRules(tenantId, link);
@@ -151,18 +151,13 @@ public class TenantActor extends ContextAwareActor { @@ -151,18 +151,13 @@ public class TenantActor extends ContextAwareActor {
151 private void process(RuleChainDeviceMsg msg) { 151 private void process(RuleChainDeviceMsg msg) {
152 ToDeviceActorMsg toDeviceActorMsg = msg.getToDeviceActorMsg(); 152 ToDeviceActorMsg toDeviceActorMsg = msg.getToDeviceActorMsg();
153 ActorRef deviceActor = getOrCreateDeviceActor(toDeviceActorMsg.getDeviceId()); 153 ActorRef deviceActor = getOrCreateDeviceActor(toDeviceActorMsg.getDeviceId());
154 - RuleActorChain chain = new ComplexRuleActorChain(msg.getRuleChain(), ruleManager.getRuleChain()); 154 + RuleActorChain chain = new ComplexRuleActorChain(msg.getRuleChain(), ruleManager.getRuleChain(this.context()));
155 deviceActor.tell(new RuleChainDeviceMsg(toDeviceActorMsg, chain), context().self()); 155 deviceActor.tell(new RuleChainDeviceMsg(toDeviceActorMsg, chain), context().self());
156 } 156 }
157 157
158 private ActorRef getOrCreateDeviceActor(DeviceId deviceId) { 158 private ActorRef getOrCreateDeviceActor(DeviceId deviceId) {
159 - ActorRef deviceActor = deviceActors.get(deviceId);  
160 - if (deviceActor == null) {  
161 - deviceActor = context().actorOf(Props.create(new DeviceActor.ActorCreator(systemContext, tenantId, deviceId))  
162 - .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME), deviceId.toString());  
163 - deviceActors.put(deviceId, deviceActor);  
164 - }  
165 - return deviceActor; 159 + return deviceActors.computeIfAbsent(deviceId, k -> context().actorOf(Props.create(new DeviceActor.ActorCreator(systemContext, tenantId, deviceId))
  160 + .withDispatcher(DefaultActorService.CORE_DISPATCHER_NAME), deviceId.toString()));
166 } 161 }
167 162
168 public static class ActorCreator extends ContextBasedCreator<TenantActor> { 163 public static class ActorCreator extends ContextBasedCreator<TenantActor> {
@@ -15,30 +15,16 @@ @@ -15,30 +15,16 @@
15 */ 15 */
16 package org.thingsboard.server.controller; 16 package org.thingsboard.server.controller;
17 17
18 -import com.google.common.util.concurrent.ListenableFuture;  
19 import org.apache.commons.lang3.StringUtils; 18 import org.apache.commons.lang3.StringUtils;
20 import org.springframework.http.HttpStatus; 19 import org.springframework.http.HttpStatus;
21 import org.springframework.security.access.prepost.PreAuthorize; 20 import org.springframework.security.access.prepost.PreAuthorize;
22 import org.springframework.web.bind.annotation.*; 21 import org.springframework.web.bind.annotation.*;
23 -import org.thingsboard.server.common.data.Customer;  
24 -import org.thingsboard.server.common.data.Event;  
25 import org.thingsboard.server.common.data.alarm.*; 22 import org.thingsboard.server.common.data.alarm.*;
26 -import org.thingsboard.server.common.data.asset.Asset;  
27 import org.thingsboard.server.common.data.id.*; 23 import org.thingsboard.server.common.data.id.*;
28 -import org.thingsboard.server.common.data.page.TextPageData;  
29 -import org.thingsboard.server.common.data.page.TextPageLink;  
30 import org.thingsboard.server.common.data.page.TimePageData; 24 import org.thingsboard.server.common.data.page.TimePageData;
31 import org.thingsboard.server.common.data.page.TimePageLink; 25 import org.thingsboard.server.common.data.page.TimePageLink;
32 -import org.thingsboard.server.dao.asset.AssetSearchQuery;  
33 -import org.thingsboard.server.dao.exception.IncorrectParameterException;  
34 -import org.thingsboard.server.dao.model.ModelConstants;  
35 import org.thingsboard.server.exception.ThingsboardErrorCode; 26 import org.thingsboard.server.exception.ThingsboardErrorCode;
36 import org.thingsboard.server.exception.ThingsboardException; 27 import org.thingsboard.server.exception.ThingsboardException;
37 -import org.thingsboard.server.service.security.model.SecurityUser;  
38 -  
39 -import java.util.ArrayList;  
40 -import java.util.List;  
41 -import java.util.stream.Collectors;  
42 28
43 @RestController 29 @RestController
44 @RequestMapping("/api") 30 @RequestMapping("/api")
@@ -27,7 +27,7 @@ import org.thingsboard.server.common.data.id.CustomerId; @@ -27,7 +27,7 @@ import org.thingsboard.server.common.data.id.CustomerId;
27 import org.thingsboard.server.common.data.id.TenantId; 27 import org.thingsboard.server.common.data.id.TenantId;
28 import org.thingsboard.server.common.data.page.TextPageData; 28 import org.thingsboard.server.common.data.page.TextPageData;
29 import org.thingsboard.server.common.data.page.TextPageLink; 29 import org.thingsboard.server.common.data.page.TextPageLink;
30 -import org.thingsboard.server.dao.asset.AssetSearchQuery; 30 +import org.thingsboard.server.common.data.asset.AssetSearchQuery;
31 import org.thingsboard.server.dao.exception.IncorrectParameterException; 31 import org.thingsboard.server.dao.exception.IncorrectParameterException;
32 import org.thingsboard.server.dao.model.ModelConstants; 32 import org.thingsboard.server.dao.model.ModelConstants;
33 import org.thingsboard.server.exception.ThingsboardException; 33 import org.thingsboard.server.exception.ThingsboardException;
@@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.id.TenantId; @@ -28,7 +28,7 @@ import org.thingsboard.server.common.data.id.TenantId;
28 import org.thingsboard.server.common.data.page.TextPageData; 28 import org.thingsboard.server.common.data.page.TextPageData;
29 import org.thingsboard.server.common.data.page.TextPageLink; 29 import org.thingsboard.server.common.data.page.TextPageLink;
30 import org.thingsboard.server.common.data.security.DeviceCredentials; 30 import org.thingsboard.server.common.data.security.DeviceCredentials;
31 -import org.thingsboard.server.dao.device.DeviceSearchQuery; 31 +import org.thingsboard.server.common.data.device.DeviceSearchQuery;
32 import org.thingsboard.server.dao.exception.IncorrectParameterException; 32 import org.thingsboard.server.dao.exception.IncorrectParameterException;
33 import org.thingsboard.server.dao.model.ModelConstants; 33 import org.thingsboard.server.dao.model.ModelConstants;
34 import org.thingsboard.server.exception.ThingsboardException; 34 import org.thingsboard.server.exception.ThingsboardException;
@@ -159,6 +159,8 @@ cassandra: @@ -159,6 +159,8 @@ cassandra:
159 159
160 # Actor system parameters 160 # Actor system parameters
161 actors: 161 actors:
  162 + tenant:
  163 + create_components_on_init: true
162 session: 164 session:
163 sync: 165 sync:
164 # Default timeout for processing request using synchronous session (HTTP, CoAP) in milliseconds 166 # Default timeout for processing request using synchronous session (HTTP, CoAP) in milliseconds
@@ -97,28 +97,28 @@ public abstract class AbstractControllerTest { @@ -97,28 +97,28 @@ public abstract class AbstractControllerTest {
97 97
98 protected static final String SYS_ADMIN_EMAIL = "sysadmin@thingsboard.org"; 98 protected static final String SYS_ADMIN_EMAIL = "sysadmin@thingsboard.org";
99 private static final String SYS_ADMIN_PASSWORD = "sysadmin"; 99 private static final String SYS_ADMIN_PASSWORD = "sysadmin";
100 - 100 +
101 protected static final String TENANT_ADMIN_EMAIL = "testtenant@thingsboard.org"; 101 protected static final String TENANT_ADMIN_EMAIL = "testtenant@thingsboard.org";
102 private static final String TENANT_ADMIN_PASSWORD = "tenant"; 102 private static final String TENANT_ADMIN_PASSWORD = "tenant";
103 103
104 protected static final String CUSTOMER_USER_EMAIL = "testcustomer@thingsboard.org"; 104 protected static final String CUSTOMER_USER_EMAIL = "testcustomer@thingsboard.org";
105 private static final String CUSTOMER_USER_PASSWORD = "customer"; 105 private static final String CUSTOMER_USER_PASSWORD = "customer";
106 - 106 +
107 protected MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(), 107 protected MediaType contentType = new MediaType(MediaType.APPLICATION_JSON.getType(),
108 MediaType.APPLICATION_JSON.getSubtype(), 108 MediaType.APPLICATION_JSON.getSubtype(),
109 Charset.forName("utf8")); 109 Charset.forName("utf8"));
110 110
111 protected MockMvc mockMvc; 111 protected MockMvc mockMvc;
112 - 112 +
113 protected String token; 113 protected String token;
114 protected String refreshToken; 114 protected String refreshToken;
115 protected String username; 115 protected String username;
116 116
117 private TenantId tenantId; 117 private TenantId tenantId;
118 - 118 +
119 @SuppressWarnings("rawtypes") 119 @SuppressWarnings("rawtypes")
120 private HttpMessageConverter mappingJackson2HttpMessageConverter; 120 private HttpMessageConverter mappingJackson2HttpMessageConverter;
121 - 121 +
122 @Autowired 122 @Autowired
123 private WebApplicationContext webApplicationContext; 123 private WebApplicationContext webApplicationContext;
124 124
@@ -132,7 +132,7 @@ public abstract class AbstractControllerTest { @@ -132,7 +132,7 @@ public abstract class AbstractControllerTest {
132 log.info("Finished test: {}", description.getMethodName()); 132 log.info("Finished test: {}", description.getMethodName());
133 } 133 }
134 }; 134 };
135 - 135 +
136 @Autowired 136 @Autowired
137 void setConverters(HttpMessageConverter<?>[] converters) { 137 void setConverters(HttpMessageConverter<?>[] converters) {
138 138
@@ -144,7 +144,7 @@ public abstract class AbstractControllerTest { @@ -144,7 +144,7 @@ public abstract class AbstractControllerTest {
144 Assert.assertNotNull("the JSON message converter must not be null", 144 Assert.assertNotNull("the JSON message converter must not be null",
145 this.mappingJackson2HttpMessageConverter); 145 this.mappingJackson2HttpMessageConverter);
146 } 146 }
147 - 147 +
148 @Before 148 @Before
149 public void setup() throws Exception { 149 public void setup() throws Exception {
150 log.info("Executing setup"); 150 log.info("Executing setup");
@@ -188,7 +188,7 @@ public abstract class AbstractControllerTest { @@ -188,7 +188,7 @@ public abstract class AbstractControllerTest {
188 public void teardown() throws Exception { 188 public void teardown() throws Exception {
189 log.info("Executing teardown"); 189 log.info("Executing teardown");
190 loginSysAdmin(); 190 loginSysAdmin();
191 - doDelete("/api/tenant/"+tenantId.getId().toString()) 191 + doDelete("/api/tenant/" + tenantId.getId().toString())
192 .andExpect(status().isOk()); 192 .andExpect(status().isOk());
193 log.info("Executed teardown"); 193 log.info("Executed teardown");
194 } 194 }
@@ -196,7 +196,7 @@ public abstract class AbstractControllerTest { @@ -196,7 +196,7 @@ public abstract class AbstractControllerTest {
196 protected void loginSysAdmin() throws Exception { 196 protected void loginSysAdmin() throws Exception {
197 login(SYS_ADMIN_EMAIL, SYS_ADMIN_PASSWORD); 197 login(SYS_ADMIN_EMAIL, SYS_ADMIN_PASSWORD);
198 } 198 }
199 - 199 +
200 protected void loginTenantAdmin() throws Exception { 200 protected void loginTenantAdmin() throws Exception {
201 login(TENANT_ADMIN_EMAIL, TENANT_ADMIN_PASSWORD); 201 login(TENANT_ADMIN_EMAIL, TENANT_ADMIN_PASSWORD);
202 } 202 }
@@ -204,13 +204,13 @@ public abstract class AbstractControllerTest { @@ -204,13 +204,13 @@ public abstract class AbstractControllerTest {
204 protected void loginCustomerUser() throws Exception { 204 protected void loginCustomerUser() throws Exception {
205 login(CUSTOMER_USER_EMAIL, CUSTOMER_USER_PASSWORD); 205 login(CUSTOMER_USER_EMAIL, CUSTOMER_USER_PASSWORD);
206 } 206 }
207 - 207 +
208 protected User createUserAndLogin(User user, String password) throws Exception { 208 protected User createUserAndLogin(User user, String password) throws Exception {
209 User savedUser = doPost("/api/user", user, User.class); 209 User savedUser = doPost("/api/user", user, User.class);
210 logout(); 210 logout();
211 doGet("/api/noauth/activate?activateToken={activateToken}", TestMailService.currentActivateToken) 211 doGet("/api/noauth/activate?activateToken={activateToken}", TestMailService.currentActivateToken)
212 - .andExpect(status().isSeeOther())  
213 - .andExpect(header().string(HttpHeaders.LOCATION, "/login/createPassword?activateToken=" + TestMailService.currentActivateToken)); 212 + .andExpect(status().isSeeOther())
  213 + .andExpect(header().string(HttpHeaders.LOCATION, "/login/createPassword?activateToken=" + TestMailService.currentActivateToken));
214 JsonNode tokenInfo = readResponse(doPost("/api/noauth/activate", "activateToken", TestMailService.currentActivateToken, "password", password).andExpect(status().isOk()), JsonNode.class); 214 JsonNode tokenInfo = readResponse(doPost("/api/noauth/activate", "activateToken", TestMailService.currentActivateToken, "password", password).andExpect(status().isOk()), JsonNode.class);
215 validateAndSetJwtToken(tokenInfo, user.getEmail()); 215 validateAndSetJwtToken(tokenInfo, user.getEmail());
216 return savedUser; 216 return savedUser;
@@ -247,14 +247,14 @@ public abstract class AbstractControllerTest { @@ -247,14 +247,14 @@ public abstract class AbstractControllerTest {
247 Assert.assertNotNull(token); 247 Assert.assertNotNull(token);
248 Assert.assertFalse(token.isEmpty()); 248 Assert.assertFalse(token.isEmpty());
249 int i = token.lastIndexOf('.'); 249 int i = token.lastIndexOf('.');
250 - Assert.assertTrue(i>0);  
251 - String withoutSignature = token.substring(0, i+1);  
252 - Jwt<Header,Claims> jwsClaims = Jwts.parser().parseClaimsJwt(withoutSignature); 250 + Assert.assertTrue(i > 0);
  251 + String withoutSignature = token.substring(0, i + 1);
  252 + Jwt<Header, Claims> jwsClaims = Jwts.parser().parseClaimsJwt(withoutSignature);
253 Claims claims = jwsClaims.getBody(); 253 Claims claims = jwsClaims.getBody();
254 String subject = claims.getSubject(); 254 String subject = claims.getSubject();
255 Assert.assertEquals(username, subject); 255 Assert.assertEquals(username, subject);
256 } 256 }
257 - 257 +
258 protected void logout() throws Exception { 258 protected void logout() throws Exception {
259 this.token = null; 259 this.token = null;
260 this.refreshToken = null; 260 this.refreshToken = null;
@@ -266,24 +266,24 @@ public abstract class AbstractControllerTest { @@ -266,24 +266,24 @@ public abstract class AbstractControllerTest {
266 request.header(ThingsboardSecurityConfiguration.JWT_TOKEN_HEADER_PARAM, "Bearer " + this.token); 266 request.header(ThingsboardSecurityConfiguration.JWT_TOKEN_HEADER_PARAM, "Bearer " + this.token);
267 } 267 }
268 } 268 }
269 - 269 +
270 protected ResultActions doGet(String urlTemplate, Object... urlVariables) throws Exception { 270 protected ResultActions doGet(String urlTemplate, Object... urlVariables) throws Exception {
271 MockHttpServletRequestBuilder getRequest = get(urlTemplate, urlVariables); 271 MockHttpServletRequestBuilder getRequest = get(urlTemplate, urlVariables);
272 setJwtToken(getRequest); 272 setJwtToken(getRequest);
273 return mockMvc.perform(getRequest); 273 return mockMvc.perform(getRequest);
274 } 274 }
275 - 275 +
276 protected <T> T doGet(String urlTemplate, Class<T> responseClass, Object... urlVariables) throws Exception { 276 protected <T> T doGet(String urlTemplate, Class<T> responseClass, Object... urlVariables) throws Exception {
277 return readResponse(doGet(urlTemplate, urlVariables).andExpect(status().isOk()), responseClass); 277 return readResponse(doGet(urlTemplate, urlVariables).andExpect(status().isOk()), responseClass);
278 } 278 }
279 - 279 +
280 protected <T> T doGetTyped(String urlTemplate, TypeReference<T> responseType, Object... urlVariables) throws Exception { 280 protected <T> T doGetTyped(String urlTemplate, TypeReference<T> responseType, Object... urlVariables) throws Exception {
281 return readResponse(doGet(urlTemplate, urlVariables).andExpect(status().isOk()), responseType); 281 return readResponse(doGet(urlTemplate, urlVariables).andExpect(status().isOk()), responseType);
282 } 282 }
283 - 283 +
284 protected <T> T doGetTypedWithPageLink(String urlTemplate, TypeReference<T> responseType, 284 protected <T> T doGetTypedWithPageLink(String urlTemplate, TypeReference<T> responseType,
285 - TextPageLink pageLink,  
286 - Object... urlVariables) throws Exception { 285 + TextPageLink pageLink,
  286 + Object... urlVariables) throws Exception {
287 List<Object> pageLinkVariables = new ArrayList<>(); 287 List<Object> pageLinkVariables = new ArrayList<>();
288 urlTemplate += "limit={limit}"; 288 urlTemplate += "limit={limit}";
289 pageLinkVariables.add(pageLink.getLimit()); 289 pageLinkVariables.add(pageLink.getLimit());
@@ -299,18 +299,18 @@ public abstract class AbstractControllerTest { @@ -299,18 +299,18 @@ public abstract class AbstractControllerTest {
299 urlTemplate += "&textOffset={textOffset}"; 299 urlTemplate += "&textOffset={textOffset}";
300 pageLinkVariables.add(pageLink.getTextOffset()); 300 pageLinkVariables.add(pageLink.getTextOffset());
301 } 301 }
302 -  
303 - Object[] vars = new Object[urlVariables.length + pageLinkVariables.size()]; 302 +
  303 + Object[] vars = new Object[urlVariables.length + pageLinkVariables.size()];
304 System.arraycopy(urlVariables, 0, vars, 0, urlVariables.length); 304 System.arraycopy(urlVariables, 0, vars, 0, urlVariables.length);
305 System.arraycopy(pageLinkVariables.toArray(), 0, vars, urlVariables.length, pageLinkVariables.size()); 305 System.arraycopy(pageLinkVariables.toArray(), 0, vars, urlVariables.length, pageLinkVariables.size());
306 - 306 +
307 return readResponse(doGet(urlTemplate, vars).andExpect(status().isOk()), responseType); 307 return readResponse(doGet(urlTemplate, vars).andExpect(status().isOk()), responseType);
308 } 308 }
309 - 309 +
310 protected <T> T doPost(String urlTemplate, Class<T> responseClass, String... params) throws Exception { 310 protected <T> T doPost(String urlTemplate, Class<T> responseClass, String... params) throws Exception {
311 return readResponse(doPost(urlTemplate, params).andExpect(status().isOk()), responseClass); 311 return readResponse(doPost(urlTemplate, params).andExpect(status().isOk()), responseClass);
312 } 312 }
313 - 313 +
314 protected <T> T doPost(String urlTemplate, T content, Class<T> responseClass, String... params) throws Exception { 314 protected <T> T doPost(String urlTemplate, T content, Class<T> responseClass, String... params) throws Exception {
315 return readResponse(doPost(urlTemplate, content, params).andExpect(status().isOk()), responseClass); 315 return readResponse(doPost(urlTemplate, content, params).andExpect(status().isOk()), responseClass);
316 } 316 }
@@ -318,15 +318,15 @@ public abstract class AbstractControllerTest { @@ -318,15 +318,15 @@ public abstract class AbstractControllerTest {
318 protected <T> T doDelete(String urlTemplate, Class<T> responseClass, String... params) throws Exception { 318 protected <T> T doDelete(String urlTemplate, Class<T> responseClass, String... params) throws Exception {
319 return readResponse(doDelete(urlTemplate, params).andExpect(status().isOk()), responseClass); 319 return readResponse(doDelete(urlTemplate, params).andExpect(status().isOk()), responseClass);
320 } 320 }
321 - 321 +
322 protected ResultActions doPost(String urlTemplate, String... params) throws Exception { 322 protected ResultActions doPost(String urlTemplate, String... params) throws Exception {
323 MockHttpServletRequestBuilder postRequest = post(urlTemplate); 323 MockHttpServletRequestBuilder postRequest = post(urlTemplate);
324 setJwtToken(postRequest); 324 setJwtToken(postRequest);
325 populateParams(postRequest, params); 325 populateParams(postRequest, params);
326 return mockMvc.perform(postRequest); 326 return mockMvc.perform(postRequest);
327 } 327 }
328 -  
329 - protected <T> ResultActions doPost(String urlTemplate, T content, String... params) throws Exception { 328 +
  329 + protected <T> ResultActions doPost(String urlTemplate, T content, String... params) throws Exception {
330 MockHttpServletRequestBuilder postRequest = post(urlTemplate); 330 MockHttpServletRequestBuilder postRequest = post(urlTemplate);
331 setJwtToken(postRequest); 331 setJwtToken(postRequest);
332 String json = json(content); 332 String json = json(content);
@@ -334,25 +334,25 @@ public abstract class AbstractControllerTest { @@ -334,25 +334,25 @@ public abstract class AbstractControllerTest {
334 populateParams(postRequest, params); 334 populateParams(postRequest, params);
335 return mockMvc.perform(postRequest); 335 return mockMvc.perform(postRequest);
336 } 336 }
337 - 337 +
338 protected ResultActions doDelete(String urlTemplate, String... params) throws Exception { 338 protected ResultActions doDelete(String urlTemplate, String... params) throws Exception {
339 MockHttpServletRequestBuilder deleteRequest = delete(urlTemplate); 339 MockHttpServletRequestBuilder deleteRequest = delete(urlTemplate);
340 setJwtToken(deleteRequest); 340 setJwtToken(deleteRequest);
341 populateParams(deleteRequest, params); 341 populateParams(deleteRequest, params);
342 return mockMvc.perform(deleteRequest); 342 return mockMvc.perform(deleteRequest);
343 } 343 }
344 - 344 +
345 protected void populateParams(MockHttpServletRequestBuilder request, String... params) { 345 protected void populateParams(MockHttpServletRequestBuilder request, String... params) {
346 if (params != null && params.length > 0) { 346 if (params != null && params.length > 0) {
347 Assert.assertEquals(params.length % 2, 0); 347 Assert.assertEquals(params.length % 2, 0);
348 MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<String, String>(); 348 MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<String, String>();
349 - for (int i=0;i<params.length;i+=2) {  
350 - paramsMap.add(params[i], params[i+1]); 349 + for (int i = 0; i < params.length; i += 2) {
  350 + paramsMap.add(params[i], params[i + 1]);
351 } 351 }
352 request.params(paramsMap); 352 request.params(paramsMap);
353 } 353 }
354 } 354 }
355 - 355 +
356 @SuppressWarnings("unchecked") 356 @SuppressWarnings("unchecked")
357 protected String json(Object o) throws IOException { 357 protected String json(Object o) throws IOException {
358 MockHttpOutputMessage mockHttpOutputMessage = new MockHttpOutputMessage(); 358 MockHttpOutputMessage mockHttpOutputMessage = new MockHttpOutputMessage();
@@ -360,14 +360,14 @@ public abstract class AbstractControllerTest { @@ -360,14 +360,14 @@ public abstract class AbstractControllerTest {
360 o, MediaType.APPLICATION_JSON, mockHttpOutputMessage); 360 o, MediaType.APPLICATION_JSON, mockHttpOutputMessage);
361 return mockHttpOutputMessage.getBodyAsString(); 361 return mockHttpOutputMessage.getBodyAsString();
362 } 362 }
363 - 363 +
364 @SuppressWarnings("unchecked") 364 @SuppressWarnings("unchecked")
365 protected <T> T readResponse(ResultActions result, Class<T> responseClass) throws Exception { 365 protected <T> T readResponse(ResultActions result, Class<T> responseClass) throws Exception {
366 byte[] content = result.andReturn().getResponse().getContentAsByteArray(); 366 byte[] content = result.andReturn().getResponse().getContentAsByteArray();
367 MockHttpInputMessage mockHttpInputMessage = new MockHttpInputMessage(content); 367 MockHttpInputMessage mockHttpInputMessage = new MockHttpInputMessage(content);
368 return (T) this.mappingJackson2HttpMessageConverter.read(responseClass, mockHttpInputMessage); 368 return (T) this.mappingJackson2HttpMessageConverter.read(responseClass, mockHttpInputMessage);
369 } 369 }
370 - 370 +
371 protected <T> T readResponse(ResultActions result, TypeReference<T> type) throws Exception { 371 protected <T> T readResponse(ResultActions result, TypeReference<T> type) throws Exception {
372 byte[] content = result.andReturn().getResponse().getContentAsByteArray(); 372 byte[] content = result.andReturn().getResponse().getContentAsByteArray();
373 ObjectMapper mapper = new ObjectMapper(); 373 ObjectMapper mapper = new ObjectMapper();
common/data/src/main/java/org/thingsboard/server/common/data/asset/AssetSearchQuery.java renamed from dao/src/main/java/org/thingsboard/server/dao/asset/AssetSearchQuery.java
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.asset; 16 +package org.thingsboard.server.common.data.asset;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import org.thingsboard.server.common.data.EntityType; 19 import org.thingsboard.server.common.data.EntityType;
@@ -22,7 +22,6 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery; @@ -22,7 +22,6 @@ import org.thingsboard.server.common.data.relation.EntityRelationsQuery;
22 import org.thingsboard.server.common.data.relation.EntityTypeFilter; 22 import org.thingsboard.server.common.data.relation.EntityTypeFilter;
23 import org.thingsboard.server.common.data.relation.RelationsSearchParameters; 23 import org.thingsboard.server.common.data.relation.RelationsSearchParameters;
24 24
25 -import javax.annotation.Nullable;  
26 import java.util.Collections; 25 import java.util.Collections;
27 import java.util.List; 26 import java.util.List;
28 27
@@ -33,9 +32,7 @@ import java.util.List; @@ -33,9 +32,7 @@ import java.util.List;
33 public class AssetSearchQuery { 32 public class AssetSearchQuery {
34 33
35 private RelationsSearchParameters parameters; 34 private RelationsSearchParameters parameters;
36 - @Nullable  
37 private String relationType; 35 private String relationType;
38 - @Nullable  
39 private List<String> assetTypes; 36 private List<String> assetTypes;
40 37
41 public EntityRelationsQuery toEntitySearchQuery() { 38 public EntityRelationsQuery toEntitySearchQuery() {
dao/src/main/java/org/thingsboard/server/common/data/device/DeviceSearchQuery.java renamed from dao/src/main/java/org/thingsboard/server/dao/device/DeviceSearchQuery.java
@@ -13,7 +13,7 @@ @@ -13,7 +13,7 @@
13 * See the License for the specific language governing permissions and 13 * See the License for the specific language governing permissions and
14 * limitations under the License. 14 * limitations under the License.
15 */ 15 */
16 -package org.thingsboard.server.dao.device; 16 +package org.thingsboard.server.common.data.device;
17 17
18 import lombok.Data; 18 import lombok.Data;
19 import org.thingsboard.server.common.data.EntityType; 19 import org.thingsboard.server.common.data.EntityType;
@@ -18,6 +18,7 @@ package org.thingsboard.server.dao.asset; @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.asset;
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 import org.thingsboard.server.common.data.EntitySubtype; 19 import org.thingsboard.server.common.data.EntitySubtype;
20 import org.thingsboard.server.common.data.asset.Asset; 20 import org.thingsboard.server.common.data.asset.Asset;
  21 +import org.thingsboard.server.common.data.asset.AssetSearchQuery;
21 import org.thingsboard.server.common.data.id.AssetId; 22 import org.thingsboard.server.common.data.id.AssetId;
22 import org.thingsboard.server.common.data.id.CustomerId; 23 import org.thingsboard.server.common.data.id.CustomerId;
23 import org.thingsboard.server.common.data.id.TenantId; 24 import org.thingsboard.server.common.data.id.TenantId;
@@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.EntitySubtype; @@ -29,6 +29,7 @@ import org.thingsboard.server.common.data.EntitySubtype;
29 import org.thingsboard.server.common.data.EntityType; 29 import org.thingsboard.server.common.data.EntityType;
30 import org.thingsboard.server.common.data.Tenant; 30 import org.thingsboard.server.common.data.Tenant;
31 import org.thingsboard.server.common.data.asset.Asset; 31 import org.thingsboard.server.common.data.asset.Asset;
  32 +import org.thingsboard.server.common.data.asset.AssetSearchQuery;
32 import org.thingsboard.server.common.data.id.AssetId; 33 import org.thingsboard.server.common.data.id.AssetId;
33 import org.thingsboard.server.common.data.id.CustomerId; 34 import org.thingsboard.server.common.data.id.CustomerId;
34 import org.thingsboard.server.common.data.id.EntityId; 35 import org.thingsboard.server.common.data.id.EntityId;
@@ -18,6 +18,7 @@ package org.thingsboard.server.dao.device; @@ -18,6 +18,7 @@ package org.thingsboard.server.dao.device;
18 import com.google.common.util.concurrent.ListenableFuture; 18 import com.google.common.util.concurrent.ListenableFuture;
19 import org.thingsboard.server.common.data.Device; 19 import org.thingsboard.server.common.data.Device;
20 import org.thingsboard.server.common.data.EntitySubtype; 20 import org.thingsboard.server.common.data.EntitySubtype;
  21 +import org.thingsboard.server.common.data.device.DeviceSearchQuery;
21 import org.thingsboard.server.common.data.id.CustomerId; 22 import org.thingsboard.server.common.data.id.CustomerId;
22 import org.thingsboard.server.common.data.id.DeviceId; 23 import org.thingsboard.server.common.data.id.DeviceId;
23 import org.thingsboard.server.common.data.id.TenantId; 24 import org.thingsboard.server.common.data.id.TenantId;
@@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired; @@ -25,6 +25,7 @@ import org.springframework.beans.factory.annotation.Autowired;
25 import org.springframework.stereotype.Service; 25 import org.springframework.stereotype.Service;
26 import org.springframework.util.StringUtils; 26 import org.springframework.util.StringUtils;
27 import org.thingsboard.server.common.data.*; 27 import org.thingsboard.server.common.data.*;
  28 +import org.thingsboard.server.common.data.device.DeviceSearchQuery;
28 import org.thingsboard.server.common.data.id.CustomerId; 29 import org.thingsboard.server.common.data.id.CustomerId;
29 import org.thingsboard.server.common.data.id.DeviceId; 30 import org.thingsboard.server.common.data.id.DeviceId;
30 import org.thingsboard.server.common.data.id.EntityId; 31 import org.thingsboard.server.common.data.id.EntityId;
@@ -16,6 +16,7 @@ @@ -16,6 +16,7 @@
16 package org.thingsboard.server.transport.mqtt; 16 package org.thingsboard.server.transport.mqtt;
17 17
18 import com.fasterxml.jackson.databind.JsonNode; 18 import com.fasterxml.jackson.databind.JsonNode;
  19 +import io.netty.channel.Channel;
19 import io.netty.channel.ChannelHandlerContext; 20 import io.netty.channel.ChannelHandlerContext;
20 import io.netty.channel.ChannelInboundHandlerAdapter; 21 import io.netty.channel.ChannelInboundHandlerAdapter;
21 import io.netty.handler.codec.mqtt.*; 22 import io.netty.handler.codec.mqtt.*;
@@ -45,6 +46,8 @@ import org.thingsboard.server.transport.mqtt.util.SslUtil; @@ -45,6 +46,8 @@ import org.thingsboard.server.transport.mqtt.util.SslUtil;
45 46
46 import javax.net.ssl.SSLPeerUnverifiedException; 47 import javax.net.ssl.SSLPeerUnverifiedException;
47 import javax.security.cert.X509Certificate; 48 import javax.security.cert.X509Certificate;
  49 +import java.net.InetSocketAddress;
  50 +import java.net.SocketAddress;
48 import java.util.ArrayList; 51 import java.util.ArrayList;
49 import java.util.List; 52 import java.util.List;
50 53
@@ -71,6 +74,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -71,6 +74,7 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
71 private final RelationService relationService; 74 private final RelationService relationService;
72 private final SslHandler sslHandler; 75 private final SslHandler sslHandler;
73 private volatile boolean connected; 76 private volatile boolean connected;
  77 + private volatile InetSocketAddress address;
74 private volatile GatewaySessionCtx gatewaySessionCtx; 78 private volatile GatewaySessionCtx gatewaySessionCtx;
75 79
76 public MqttTransportHandler(SessionMsgProcessor processor, DeviceService deviceService, DeviceAuthService authService, RelationService relationService, 80 public MqttTransportHandler(SessionMsgProcessor processor, DeviceService deviceService, DeviceAuthService authService, RelationService relationService,
@@ -94,30 +98,36 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -94,30 +98,36 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
94 } 98 }
95 99
96 private void processMqttMsg(ChannelHandlerContext ctx, MqttMessage msg) { 100 private void processMqttMsg(ChannelHandlerContext ctx, MqttMessage msg) {
97 - deviceSessionCtx.setChannel(ctx);  
98 - switch (msg.fixedHeader().messageType()) {  
99 - case CONNECT:  
100 - processConnect(ctx, (MqttConnectMessage) msg);  
101 - break;  
102 - case PUBLISH:  
103 - processPublish(ctx, (MqttPublishMessage) msg);  
104 - break;  
105 - case SUBSCRIBE:  
106 - processSubscribe(ctx, (MqttSubscribeMessage) msg);  
107 - break;  
108 - case UNSUBSCRIBE:  
109 - processUnsubscribe(ctx, (MqttUnsubscribeMessage) msg);  
110 - break;  
111 - case PINGREQ:  
112 - if (checkConnected(ctx)) {  
113 - ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0)));  
114 - }  
115 - break;  
116 - case DISCONNECT:  
117 - if (checkConnected(ctx)) {  
118 - processDisconnect(ctx);  
119 - }  
120 - break; 101 + address = (InetSocketAddress) ctx.channel().remoteAddress();
  102 + if (msg.fixedHeader() == null) {
  103 + log.info("[{}:{}] Invalid message received", address.getHostName(), address.getPort());
  104 + processDisconnect(ctx);
  105 + } else {
  106 + deviceSessionCtx.setChannel(ctx);
  107 + switch (msg.fixedHeader().messageType()) {
  108 + case CONNECT:
  109 + processConnect(ctx, (MqttConnectMessage) msg);
  110 + break;
  111 + case PUBLISH:
  112 + processPublish(ctx, (MqttPublishMessage) msg);
  113 + break;
  114 + case SUBSCRIBE:
  115 + processSubscribe(ctx, (MqttSubscribeMessage) msg);
  116 + break;
  117 + case UNSUBSCRIBE:
  118 + processUnsubscribe(ctx, (MqttUnsubscribeMessage) msg);
  119 + break;
  120 + case PINGREQ:
  121 + if (checkConnected(ctx)) {
  122 + ctx.writeAndFlush(new MqttMessage(new MqttFixedHeader(PINGRESP, false, AT_MOST_ONCE, false, 0)));
  123 + }
  124 + break;
  125 + case DISCONNECT:
  126 + if (checkConnected(ctx)) {
  127 + processDisconnect(ctx);
  128 + }
  129 + break;
  130 + }
121 } 131 }
122 } 132 }
123 133
@@ -313,9 +323,11 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement @@ -313,9 +323,11 @@ public class MqttTransportHandler extends ChannelInboundHandlerAdapter implement
313 323
314 private void processDisconnect(ChannelHandlerContext ctx) { 324 private void processDisconnect(ChannelHandlerContext ctx) {
315 ctx.close(); 325 ctx.close();
316 - processor.process(SessionCloseMsg.onDisconnect(deviceSessionCtx.getSessionId()));  
317 - if (gatewaySessionCtx != null) {  
318 - gatewaySessionCtx.onGatewayDisconnect(); 326 + if (connected) {
  327 + processor.process(SessionCloseMsg.onDisconnect(deviceSessionCtx.getSessionId()));
  328 + if (gatewaySessionCtx != null) {
  329 + gatewaySessionCtx.onGatewayDisconnect();
  330 + }
319 } 331 }
320 } 332 }
321 333