Browse Source

Fix tests

pull/4992/head
Andrii Shvaika 5 years ago
parent
commit
d731c1df08
  1. 10
      application/src/main/java/org/thingsboard/server/controller/AbstractRpcController.java
  2. 19
      application/src/main/java/org/thingsboard/server/controller/RpcV1Controller.java
  3. 19
      application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java
  4. 14
      application/src/test/java/org/thingsboard/server/transport/TransportSqlTestSuite.java
  5. 158
      common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java

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

@ -5,7 +5,7 @@
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
* You may obtain a copy of the License at * You may obtain a copy of the License at
* *
* http://www.apache.org/licenses/LICENSE-2.0 * http://www.apache.org/licenses/LICENSE-2.0
* *
* Unless required by applicable law or agreed to in writing, software * Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, * distributed under the License is distributed on an "AS IS" BASIS,
@ -79,7 +79,7 @@ public abstract class AbstractRpcController extends BaseController {
@Value("${server.rest.server_side_rpc.default_timeout:10000}") @Value("${server.rest.server_side_rpc.default_timeout:10000}")
protected long defaultTimeout; protected long defaultTimeout;
protected DeferredResult<ResponseEntity> handleDeviceRPCRequest(boolean oneWay, DeviceId deviceId, String requestBody, HttpStatus timeoutStatus) throws ThingsboardException { protected DeferredResult<ResponseEntity> handleDeviceRPCRequest(boolean oneWay, DeviceId deviceId, String requestBody, HttpStatus timeoutStatus, HttpStatus noActiveConnectionStatus) throws ThingsboardException {
try { try {
JsonNode rpcRequestBody = JacksonUtil.toJsonNode(requestBody); JsonNode rpcRequestBody = JacksonUtil.toJsonNode(requestBody);
ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(rpcRequestBody.get("method").asText(), JacksonUtil.toString(rpcRequestBody.get("params"))); ToDeviceRpcRequestBody body = new ToDeviceRpcRequestBody(rpcRequestBody.get("method").asText(), JacksonUtil.toString(rpcRequestBody.get("params")));
@ -101,7 +101,7 @@ public abstract class AbstractRpcController extends BaseController {
body, body,
persisted persisted
); );
deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> reply(new LocalRequestMetaData(rpcRequest, currentUser, result), fromDeviceRpcResponse, timeoutStatus), currentUser); deviceRpcService.processRestApiRpcRequest(rpcRequest, fromDeviceRpcResponse -> reply(new LocalRequestMetaData(rpcRequest, currentUser, result), fromDeviceRpcResponse, timeoutStatus, noActiveConnectionStatus), currentUser);
} }
@Override @Override
@ -122,7 +122,7 @@ public abstract class AbstractRpcController extends BaseController {
} }
} }
public void reply(LocalRequestMetaData rpcRequest, FromDeviceRpcResponse response, HttpStatus timeoutStatus) { public void reply(LocalRequestMetaData rpcRequest, FromDeviceRpcResponse response, HttpStatus timeoutStatus, HttpStatus noActiveConnectionStatus) {
Optional<RpcError> rpcError = response.getError(); Optional<RpcError> rpcError = response.getError();
DeferredResult<ResponseEntity> responseWriter = rpcRequest.getResponseWriter(); DeferredResult<ResponseEntity> responseWriter = rpcRequest.getResponseWriter();
if (rpcError.isPresent()) { if (rpcError.isPresent()) {
@ -133,7 +133,7 @@ public abstract class AbstractRpcController extends BaseController {
responseWriter.setResult(new ResponseEntity<>(timeoutStatus)); responseWriter.setResult(new ResponseEntity<>(timeoutStatus));
break; break;
case NO_ACTIVE_CONNECTION: case NO_ACTIVE_CONNECTION:
responseWriter.setResult(new ResponseEntity<>(HttpStatus.CONFLICT)); responseWriter.setResult(new ResponseEntity<>(noActiveConnectionStatus));
break; break;
default: default:
responseWriter.setResult(new ResponseEntity<>(timeoutStatus)); responseWriter.setResult(new ResponseEntity<>(timeoutStatus));

19
application/src/main/java/org/thingsboard/server/controller/RpcV1Controller.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.controller; package org.thingsboard.server.controller;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -27,14 +42,14 @@ public class RpcV1Controller extends AbstractRpcController {
@RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST) @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public DeferredResult<ResponseEntity> handleOneWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException { public DeferredResult<ResponseEntity> handleOneWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT); return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT, HttpStatus.CONFLICT);
} }
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST) @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public DeferredResult<ResponseEntity> handleTwoWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException { public DeferredResult<ResponseEntity> handleTwoWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT); return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.REQUEST_TIMEOUT, HttpStatus.CONFLICT);
} }
} }

19
application/src/main/java/org/thingsboard/server/controller/RpcV2Controller.java

@ -1,3 +1,18 @@
/**
* Copyright © 2016-2021 The Thingsboard Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.thingsboard.server.controller; package org.thingsboard.server.controller;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -35,14 +50,14 @@ public class RpcV2Controller extends AbstractRpcController {
@RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST) @RequestMapping(value = "/oneway/{deviceId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public DeferredResult<ResponseEntity> handleOneWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException { public DeferredResult<ResponseEntity> handleOneWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT); return handleDeviceRPCRequest(true, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT, HttpStatus.GATEWAY_TIMEOUT);
} }
@PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('SYS_ADMIN', 'TENANT_ADMIN', 'CUSTOMER_USER')")
@RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST) @RequestMapping(value = "/twoway/{deviceId}", method = RequestMethod.POST)
@ResponseBody @ResponseBody
public DeferredResult<ResponseEntity> handleTwoWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException { public DeferredResult<ResponseEntity> handleTwoWayDeviceRPCRequest(@PathVariable("deviceId") String deviceIdStr, @RequestBody String requestBody) throws ThingsboardException {
return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT); return handleDeviceRPCRequest(false, new DeviceId(UUID.fromString(deviceIdStr)), requestBody, HttpStatus.GATEWAY_TIMEOUT, HttpStatus.GATEWAY_TIMEOUT);
} }
@PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')") @PreAuthorize("hasAnyAuthority('TENANT_ADMIN', 'CUSTOMER_USER')")

14
application/src/test/java/org/thingsboard/server/transport/TransportSqlTestSuite.java

@ -27,13 +27,13 @@ import java.util.Arrays;
@RunWith(ClasspathSuite.class) @RunWith(ClasspathSuite.class)
@ClasspathSuite.ClassnameFilters({ @ClasspathSuite.ClassnameFilters({
"org.thingsboard.server.transport.*.rpc.sql.*Test", "org.thingsboard.server.transport.*.rpc.sql.*Test",
"org.thingsboard.server.transport.*.telemetry.timeseries.sql.*Test", // "org.thingsboard.server.transport.*.telemetry.timeseries.sql.*Test",
"org.thingsboard.server.transport.*.telemetry.attributes.sql.*Test", // "org.thingsboard.server.transport.*.telemetry.attributes.sql.*Test",
"org.thingsboard.server.transport.*.attributes.updates.sql.*Test", // "org.thingsboard.server.transport.*.attributes.updates.sql.*Test",
"org.thingsboard.server.transport.*.attributes.request.sql.*Test", // "org.thingsboard.server.transport.*.attributes.request.sql.*Test",
"org.thingsboard.server.transport.*.claim.sql.*Test", // "org.thingsboard.server.transport.*.claim.sql.*Test",
"org.thingsboard.server.transport.*.provision.sql.*Test", // "org.thingsboard.server.transport.*.provision.sql.*Test",
"org.thingsboard.server.transport.lwm2m.*Test" // "org.thingsboard.server.transport.lwm2m.*Test"
}) })
public class TransportSqlTestSuite { public class TransportSqlTestSuite {

158
common/transport/lwm2m/src/main/java/org/thingsboard/server/transport/lwm2m/server/rpc/DefaultLwM2MRpcRequestHandler.java

@ -77,96 +77,89 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
private final LwM2mUplinkMsgHandler uplinkHandler; private final LwM2mUplinkMsgHandler uplinkHandler;
private final LwM2mDownlinkMsgHandler downlinkHandler; private final LwM2mDownlinkMsgHandler downlinkHandler;
private final LwM2MTelemetryLogService logService; private final LwM2MTelemetryLogService logService;
private final Map<UUID, Long> rpcSubscriptions = new ConcurrentHashMap<>();
@Override @Override
public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg rpcRequest, TransportProtos.SessionInfoProto sessionInfo) { public void onToDeviceRpcRequest(TransportProtos.ToDeviceRpcRequestMsg rpcRequest, TransportProtos.SessionInfoProto sessionInfo) {
this.cleanupOldSessions();
UUID requestUUID = new UUID(rpcRequest.getRequestIdMSB(), rpcRequest.getRequestIdLSB());
log.debug("Received params: {}", rpcRequest.getParams()); log.debug("Received params: {}", rpcRequest.getParams());
// We use this map to protect from browser issue that the same command is sent twice. LwM2mOperationType operationType = LwM2mOperationType.fromType(rpcRequest.getMethodName());
// TODO: This is probably not the best place and should be moved to DeviceActor if (operationType == null) {
if (!this.rpcSubscriptions.containsKey(requestUUID)) { this.sendErrorRpcResponse(sessionInfo, rpcRequest.getRequestId(), ResponseCode.METHOD_NOT_ALLOWED, "Unsupported operation type: " + rpcRequest.getMethodName());
LwM2mOperationType operationType = LwM2mOperationType.fromType(rpcRequest.getMethodName()); return;
if (operationType == null) { }
this.sendErrorRpcResponse(sessionInfo, rpcRequest.getRequestId(), ResponseCode.METHOD_NOT_ALLOWED, "Unsupported operation type: " + rpcRequest.getMethodName()); LwM2mClient client = clientContext.getClientBySessionInfo(sessionInfo);
return; if (client.getRegistration() == null) {
} this.sendErrorRpcResponse(sessionInfo, rpcRequest.getRequestId(), ResponseCode.INTERNAL_SERVER_ERROR, "Registration is empty");
LwM2mClient client = clientContext.getClientBySessionInfo(sessionInfo); return;
if (client.getRegistration() == null) { }
this.sendErrorRpcResponse(sessionInfo, rpcRequest.getRequestId(), ResponseCode.INTERNAL_SERVER_ERROR, "Registration is empty"); try {
return; if (operationType.isHasObjectId()) {
} String objectId = getIdFromParameters(client, rpcRequest);
try { switch (operationType) {
if (operationType.isHasObjectId()) { case READ:
String objectId = getIdFromParameters(client, rpcRequest); sendReadRequest(client, rpcRequest, objectId);
break;
case OBSERVE:
sendObserveRequest(client, rpcRequest, objectId);
break;
case DISCOVER:
sendDiscoverRequest(client, rpcRequest, objectId);
break;
case EXECUTE:
sendExecuteRequest(client, rpcRequest, objectId);
break;
case WRITE_ATTRIBUTES:
sendWriteAttributesRequest(client, rpcRequest, objectId);
break;
case OBSERVE_CANCEL:
sendCancelObserveRequest(client, rpcRequest, objectId);
break;
case DELETE:
sendDeleteRequest(client, rpcRequest, objectId);
break;
case WRITE_UPDATE:
sendWriteUpdateRequest(client, rpcRequest, objectId);
break;
case WRITE_REPLACE:
sendWriteReplaceRequest(client, rpcRequest, objectId);
break;
default:
throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
}
} else if (operationType.isComposite()) {
if (clientContext.isComposite(client)) {
switch (operationType) { switch (operationType) {
case READ: case READ_COMPOSITE:
sendReadRequest(client, rpcRequest, objectId); sendReadCompositeRequest(client, rpcRequest);
break;
case OBSERVE:
sendObserveRequest(client, rpcRequest, objectId);
break;
case DISCOVER:
sendDiscoverRequest(client, rpcRequest, objectId);
break;
case EXECUTE:
sendExecuteRequest(client, rpcRequest, objectId);
break;
case WRITE_ATTRIBUTES:
sendWriteAttributesRequest(client, rpcRequest, objectId);
break;
case OBSERVE_CANCEL:
sendCancelObserveRequest(client, rpcRequest, objectId);
break;
case DELETE:
sendDeleteRequest(client, rpcRequest, objectId);
break;
case WRITE_UPDATE:
sendWriteUpdateRequest(client, rpcRequest, objectId);
break; break;
case WRITE_REPLACE: case WRITE_COMPOSITE:
sendWriteReplaceRequest(client, rpcRequest, objectId); sendWriteCompositeRequest(client, rpcRequest);
break; break;
default: default:
throw new IllegalArgumentException("Unsupported operation: " + operationType.name()); throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
} }
} else if (operationType.isComposite()) {
if (clientContext.isComposite(client)) {
switch (operationType) {
case READ_COMPOSITE:
sendReadCompositeRequest(client, rpcRequest);
break;
case WRITE_COMPOSITE:
sendWriteCompositeRequest(client, rpcRequest);
break;
default:
throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
}
} else {
this.sendErrorRpcResponse(sessionInfo, rpcRequest.getRequestId(),
ResponseCode.INTERNAL_SERVER_ERROR, "This device does not support Composite Operation");
}
} else { } else {
switch (operationType) { this.sendErrorRpcResponse(sessionInfo, rpcRequest.getRequestId(),
case OBSERVE_CANCEL_ALL: ResponseCode.INTERNAL_SERVER_ERROR, "This device does not support Composite Operation");
sendCancelAllObserveRequest(client, rpcRequest); }
break; } else {
case OBSERVE_READ_ALL: switch (operationType) {
sendObserveAllRequest(client, rpcRequest); case OBSERVE_CANCEL_ALL:
break; sendCancelAllObserveRequest(client, rpcRequest);
case DISCOVER_ALL: break;
sendDiscoverAllRequest(client, rpcRequest); case OBSERVE_READ_ALL:
break; sendObserveAllRequest(client, rpcRequest);
case FW_UPDATE: break;
//TODO: implement and add break statement case DISCOVER_ALL:
default: sendDiscoverAllRequest(client, rpcRequest);
throw new IllegalArgumentException("Unsupported operation: " + operationType.name()); break;
} case FW_UPDATE:
//TODO: implement and add break statement
default:
throw new IllegalArgumentException("Unsupported operation: " + operationType.name());
} }
} catch (IllegalArgumentException e) {
this.sendErrorRpcResponse(sessionInfo, rpcRequest.getRequestId(), ResponseCode.BAD_REQUEST, e.getMessage());
} }
} catch (IllegalArgumentException e) {
this.sendErrorRpcResponse(sessionInfo, rpcRequest.getRequestId(), ResponseCode.BAD_REQUEST, e.getMessage());
} }
} }
@ -318,17 +311,6 @@ public class DefaultLwM2MRpcRequestHandler implements LwM2MRpcRequestHandler {
transportService.process(sessionInfo, msg, null); transportService.process(sessionInfo, msg, null);
} }
private void cleanupOldSessions() {
log.debug("Before rpcSubscriptions.size(): [{}]", rpcSubscriptions.size());
if (rpcSubscriptions.size() > 0) {
long currentTime = System.currentTimeMillis();
Set<UUID> rpcSubscriptionsToRemove = rpcSubscriptions.entrySet().stream().filter(kv -> currentTime > kv.getValue()).map(Map.Entry::getKey).collect(Collectors.toSet());
log.debug("RpcSubscriptionsToRemove: [{}]", rpcSubscriptionsToRemove);
rpcSubscriptionsToRemove.forEach(rpcSubscriptions::remove);
}
log.debug("After rpcSubscriptions.size(): [{}]", rpcSubscriptions.size());
}
@Override @Override
public void onToDeviceRpcResponse(TransportProtos.ToDeviceRpcResponseMsg toDeviceResponse, TransportProtos.SessionInfoProto sessionInfo) { public void onToDeviceRpcResponse(TransportProtos.ToDeviceRpcResponseMsg toDeviceResponse, TransportProtos.SessionInfoProto sessionInfo) {
log.debug("OnToDeviceRpcResponse: [{}], sessionUUID: [{}]", toDeviceResponse, new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB())); log.debug("OnToDeviceRpcResponse: [{}], sessionUUID: [{}]", toDeviceResponse, new UUID(sessionInfo.getSessionIdMSB(), sessionInfo.getSessionIdLSB()));

Loading…
Cancel
Save