MapBasedDeviceConnectionService implements DeviceConnectionService { @Override public final Future<DeviceConnectionResult> setLastKnownGatewayForDevice(final String tenantId, final String deviceId, final String gatewayId, final Span span) { Objects.requireNonNull(tenantId); Objects.requireNonNull(deviceId); Objects.requireNonNull(gatewayId); final Map<String, JsonObject> lastKnownGatewaysForTenantMap = lastKnownGatewaysMap.computeIfAbsent(tenantId, k -> new ConcurrentHashMap<>()); final DeviceConnectionResult result; final int currentMapSize = lastKnownGatewaysForTenantMap.size(); if (currentMapSize < getConfig().getMaxDevicesPerTenant() || (currentMapSize == getConfig().getMaxDevicesPerTenant() && lastKnownGatewaysForTenantMap.containsKey(deviceId))) { lastKnownGatewaysForTenantMap.compute(deviceId, (key, oldValue) -> { return oldValue != null ? setLastUpdateDate(oldValue) : createLastKnownGatewayJson(gatewayId); }); result = DeviceConnectionResult.from(HttpURLConnection.HTTP_NO_CONTENT); } else { log.debug("cannot set last known gateway for device [{}], tenant [{}]: max number of entries per tenant reached ({})", deviceId, tenantId, getConfig().getMaxDevicesPerTenant()); result = DeviceConnectionResult.from(HttpURLConnection.HTTP_FORBIDDEN); } return Future.succeededFuture(result); }  @Autowired void setConfig(final MapBasedDeviceConnectionsConfigProperties configuration); MapBasedDeviceConnectionsConfigProperties getConfig(); @Override final Future<DeviceConnectionResult> setLastKnownGatewayForDevice(final String tenantId, final String deviceId,
            final String gatewayId, final Span span); @Override final Future<DeviceConnectionResult> getLastKnownGatewayForDevice(final String tenantId, final String deviceId,
            final Span span); @Override final Future<DeviceConnectionResult> setCommandHandlingAdapterInstance(final String tenantId,
            final String deviceId, final String protocolAdapterInstanceId, final Duration lifespan, final Span span); @Override final Future<DeviceConnectionResult> removeCommandHandlingAdapterInstance(
            final String tenantId,
            final String deviceId,
            final String adapterInstanceId,
            final Span span); @Override final Future<DeviceConnectionResult> getCommandHandlingAdapterInstances(final String tenantId,
            final String deviceId, final List<String> viaGateways, final Span span);  }
@Test public void testSetLastKnownGatewayForDeviceFailsIfLimitReached(final VertxTestContext ctx) { props.setMaxDevicesPerTenant(1); final String deviceId = "testDevice"; final String gatewayId = "testGateway"; svc.setLastKnownGatewayForDevice(Constants.DEFAULT_TENANT, deviceId, gatewayId, span) .compose(deviceConnectionResult -> { ctx.verify(() -> { assertEquals(HttpURLConnection.HTTP_NO_CONTENT, deviceConnectionResult.getStatus()); }); return svc.setLastKnownGatewayForDevice(Constants.DEFAULT_TENANT, "testDevice2", gatewayId, span); }).onComplete(ctx.succeeding(deviceConnectionResult -> ctx.verify(() -> { assertEquals(HttpURLConnection.HTTP_FORBIDDEN, deviceConnectionResult.getStatus()); assertNull(deviceConnectionResult.getPayload()); ctx.completeNow(); }))); }