Merge pull request #1500 from thingsboard/feature/spring-boot-2

[WIP] Migrate to Spring Boot 2.1.0 and Spring 5.1.2
This commit is contained in:
Igor Kulikov 2019-03-07 13:55:11 +02:00 committed by GitHub
commit e7bb6da9c2
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 385 additions and 124 deletions

View File

@ -118,17 +118,23 @@ class DeviceActorMessageProcessor extends AbstractContextAwareMsgProcessor {
this.rpcSubscriptions = new HashMap<>(); this.rpcSubscriptions = new HashMap<>();
this.toDeviceRpcPendingMap = new HashMap<>(); this.toDeviceRpcPendingMap = new HashMap<>();
this.toServerRpcPendingMap = new HashMap<>(); this.toServerRpcPendingMap = new HashMap<>();
initAttributes(); if (initAttributes()) {
restoreSessions(); restoreSessions();
} }
}
private void initAttributes() { private boolean initAttributes() {
Device device = systemContext.getDeviceService().findDeviceById(tenantId, deviceId); Device device = systemContext.getDeviceService().findDeviceById(tenantId, deviceId);
if (device != null) {
this.deviceName = device.getName(); this.deviceName = device.getName();
this.deviceType = device.getType(); this.deviceType = device.getType();
this.defaultMetaData = new TbMsgMetaData(); this.defaultMetaData = new TbMsgMetaData();
this.defaultMetaData.putValue("deviceName", deviceName); this.defaultMetaData.putValue("deviceName", deviceName);
this.defaultMetaData.putValue("deviceType", deviceType); this.defaultMetaData.putValue("deviceType", deviceType);
return true;
} else {
return false;
}
} }
void processRpcRequest(ActorContext context, ToDeviceRpcRequestActorMsg msg) { void processRpcRequest(ActorContext context, ToDeviceRpcRequestActorMsg msg) {

View File

@ -91,6 +91,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
public void start(ActorContext context) { public void start(ActorContext context) {
if (!started) { if (!started) {
RuleChain ruleChain = service.findRuleChainById(tenantId, entityId); RuleChain ruleChain = service.findRuleChainById(tenantId, entityId);
if (ruleChain != null) {
ruleChainName = ruleChain.getName(); ruleChainName = ruleChain.getName();
List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId); List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId);
log.trace("[{}][{}] Starting rule chain with {} nodes", tenantId, entityId, ruleNodeList.size()); log.trace("[{}][{}] Starting rule chain with {} nodes", tenantId, entityId, ruleNodeList.size());
@ -102,6 +103,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
} }
initRoutes(ruleChain, ruleNodeList); initRoutes(ruleChain, ruleNodeList);
started = true; started = true;
}
} else { } else {
onUpdate(context); onUpdate(context);
} }
@ -110,6 +112,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
@Override @Override
public void onUpdate(ActorContext context) { public void onUpdate(ActorContext context) {
RuleChain ruleChain = service.findRuleChainById(tenantId, entityId); RuleChain ruleChain = service.findRuleChainById(tenantId, entityId);
if (ruleChain != null) {
ruleChainName = ruleChain.getName(); ruleChainName = ruleChain.getName();
List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId); List<RuleNode> ruleNodeList = service.getRuleChainNodes(tenantId, entityId);
log.trace("[{}][{}] Updating rule chain with {} nodes", tenantId, entityId, ruleNodeList.size()); log.trace("[{}][{}] Updating rule chain with {} nodes", tenantId, entityId, ruleNodeList.size());
@ -136,6 +139,7 @@ public class RuleChainActorMessageProcessor extends ComponentMsgProcessor<RuleCh
initRoutes(ruleChain, ruleNodeList); initRoutes(ruleChain, ruleNodeList);
} }
}
@Override @Override
public void stop(ActorContext context) { public void stop(ActorContext context) {

View File

@ -55,8 +55,10 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod
@Override @Override
public void start(ActorContext context) throws Exception { public void start(ActorContext context) throws Exception {
tbNode = initComponent(ruleNode); tbNode = initComponent(ruleNode);
if (tbNode != null) {
state = ComponentLifecycleState.ACTIVE; state = ComponentLifecycleState.ACTIVE;
} }
}
@Override @Override
public void onUpdate(ActorContext context) throws Exception { public void onUpdate(ActorContext context) throws Exception {
@ -118,9 +120,12 @@ public class RuleNodeActorMessageProcessor extends ComponentMsgProcessor<RuleNod
} }
private TbNode initComponent(RuleNode ruleNode) throws Exception { private TbNode initComponent(RuleNode ruleNode) throws Exception {
TbNode tbNode = null;
if (ruleNode != null) {
Class<?> componentClazz = Class.forName(ruleNode.getType()); Class<?> componentClazz = Class.forName(ruleNode.getType());
TbNode tbNode = (TbNode) (componentClazz.newInstance()); tbNode = (TbNode) (componentClazz.newInstance());
tbNode.init(defaultCtx, new TbNodeConfiguration(ruleNode.getConfiguration())); tbNode.init(defaultCtx, new TbNodeConfiguration(ruleNode.getConfiguration()));
}
return tbNode; return tbNode;
} }

View File

@ -22,7 +22,7 @@ import java.util.HashMap;
import java.util.Map; import java.util.Map;
@Configuration @Configuration
@ConfigurationProperties(prefix = "audit_log.logging_level") @ConfigurationProperties(prefix = "audit-log.logging-level")
public class AuditLogLevelProperties { public class AuditLogLevelProperties {
private Map<String, String> mask = new HashMap<>(); private Map<String, String> mask = new HashMap<>();

View File

@ -0,0 +1,46 @@
/**
* Copyright © 2016-2019 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.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.SchedulingConfigurer;
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
import org.springframework.scheduling.config.ScheduledTaskRegistrar;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
@Configuration
@EnableScheduling
public class SchedulingConfiguration implements SchedulingConfigurer {
@Override
public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
taskRegistrar.setScheduler(taskScheduler());
}
@Bean(destroyMethod="shutdown")
public TaskScheduler taskScheduler() {
ThreadPoolTaskScheduler threadPoolScheduler = new ThreadPoolTaskScheduler();
threadPoolScheduler.setThreadNamePrefix("TB-Scheduling-");
threadPoolScheduler.setPoolSize(Runtime.getRuntime().availableProcessors());
threadPoolScheduler.setRemoveOnCancelPolicy(true);
return threadPoolScheduler;
}
}

View File

@ -15,11 +15,28 @@
*/ */
package org.thingsboard.server.config; package org.thingsboard.server.config;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary; import org.springframework.context.annotation.Primary;
import org.springframework.context.support.ResourceBundleMessageSource; import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.StringUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
@Configuration @Configuration
public class ThingsboardMessageConfiguration { public class ThingsboardMessageConfiguration {
@ -33,4 +50,113 @@ public class ThingsboardMessageConfiguration {
return messageSource; return messageSource;
} }
private static final String DEFAULT_RESOURCE_LOADER_PATH = "classpath:/templates/";
private ResourceLoader resourceLoader = new DefaultResourceLoader();
@Bean
public VelocityEngine velocityEngine() {
VelocityEngine velocityEngine = new VelocityEngine();
try {
Resource resource = resourceLoader.getResource(DEFAULT_RESOURCE_LOADER_PATH);
File file = resource.getFile();
velocityEngine.setProperty(RuntimeConstants.RESOURCE_LOADER, "file");
velocityEngine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_CACHE, "true");
velocityEngine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, file.getAbsolutePath());
} catch (IOException e) {
initSpringResourceLoader(velocityEngine, DEFAULT_RESOURCE_LOADER_PATH);
}
velocityEngine.init();
return velocityEngine;
}
private void initSpringResourceLoader(VelocityEngine velocityEngine, String resourceLoaderPath) {
velocityEngine.setProperty(
RuntimeConstants.RESOURCE_LOADER, SpringResourceLoader.NAME);
velocityEngine.setProperty(
SpringResourceLoader.SPRING_RESOURCE_LOADER_CLASS, SpringResourceLoader.class.getName());
velocityEngine.setProperty(
SpringResourceLoader.SPRING_RESOURCE_LOADER_CACHE, "true");
velocityEngine.setApplicationAttribute(
SpringResourceLoader.SPRING_RESOURCE_LOADER, resourceLoader);
velocityEngine.setApplicationAttribute(
SpringResourceLoader.SPRING_RESOURCE_LOADER_PATH, resourceLoaderPath);
}
@Slf4j
static class SpringResourceLoader extends org.apache.velocity.runtime.resource.loader.ResourceLoader {
public static final String NAME = "spring";
public static final String SPRING_RESOURCE_LOADER_CLASS = "spring.resource.loader.class";
public static final String SPRING_RESOURCE_LOADER_CACHE = "spring.resource.loader.cache";
public static final String SPRING_RESOURCE_LOADER = "spring.resource.loader";
public static final String SPRING_RESOURCE_LOADER_PATH = "spring.resource.loader.path";
private org.springframework.core.io.ResourceLoader resourceLoader;
private String[] resourceLoaderPaths;
@Override
public void init(ExtendedProperties configuration) {
this.resourceLoader = (org.springframework.core.io.ResourceLoader)
this.rsvc.getApplicationAttribute(SPRING_RESOURCE_LOADER);
String resourceLoaderPath = (String) this.rsvc.getApplicationAttribute(SPRING_RESOURCE_LOADER_PATH);
if (this.resourceLoader == null) {
throw new IllegalArgumentException(
"'resourceLoader' application attribute must be present for SpringResourceLoader");
}
if (resourceLoaderPath == null) {
throw new IllegalArgumentException(
"'resourceLoaderPath' application attribute must be present for SpringResourceLoader");
}
this.resourceLoaderPaths = StringUtils.commaDelimitedListToStringArray(resourceLoaderPath);
for (int i = 0; i < this.resourceLoaderPaths.length; i++) {
String path = this.resourceLoaderPaths[i];
if (!path.endsWith("/")) {
this.resourceLoaderPaths[i] = path + "/";
}
}
if (log.isInfoEnabled()) {
log.info("SpringResourceLoader for Velocity: using resource loader [" + this.resourceLoader +
"] and resource loader paths " + Arrays.asList(this.resourceLoaderPaths));
}
}
@Override
public InputStream getResourceStream(String source) throws ResourceNotFoundException {
if (log.isDebugEnabled()) {
log.debug("Looking for Velocity resource with name [" + source + "]");
}
for (String resourceLoaderPath : this.resourceLoaderPaths) {
org.springframework.core.io.Resource resource =
this.resourceLoader.getResource(resourceLoaderPath + source);
try {
return resource.getInputStream();
}
catch (IOException ex) {
if (log.isDebugEnabled()) {
log.debug("Could not find Velocity resource: " + resource);
}
}
}
throw new ResourceNotFoundException(
"Could not find resource [" + source + "] in Spring resource loader path");
}
@Override
public boolean isSourceModified(org.apache.velocity.runtime.resource.Resource resource) {
return false;
}
@Override
public long getLastModified(org.apache.velocity.runtime.resource.Resource resource) {
return 0;
}
}
} }

View File

@ -57,7 +57,7 @@ import java.util.List;
@Configuration @Configuration
@EnableWebSecurity @EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true) @EnableGlobalMethodSecurity(prePostEnabled=true)
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) @Order(SecurityProperties.BASIC_AUTH_ORDER)
public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapter { public class ThingsboardSecurityConfiguration extends WebSecurityConfigurerAdapter {
public static final String JWT_TOKEN_HEADER_PARAM = "X-Authorization"; public static final String JWT_TOKEN_HEADER_PARAM = "X-Authorization";

View File

@ -17,6 +17,7 @@ package org.thingsboard.server.service.install;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.thingsboard.server.dao.cassandra.CassandraInstallCluster; import org.thingsboard.server.dao.cassandra.CassandraInstallCluster;
import org.thingsboard.server.service.install.cql.CQLStatementsParser; import org.thingsboard.server.service.install.cql.CQLStatementsParser;
@ -30,6 +31,7 @@ public abstract class CassandraAbstractDatabaseSchemaService implements Database
private static final String CASSANDRA_DIR = "cassandra"; private static final String CASSANDRA_DIR = "cassandra";
@Autowired @Autowired
@Qualifier("CassandraInstallCluster")
private CassandraInstallCluster cluster; private CassandraInstallCluster cluster;
@Autowired @Autowired

View File

@ -18,6 +18,7 @@ package org.thingsboard.server.service.install;
import com.datastax.driver.core.KeyspaceMetadata; import com.datastax.driver.core.KeyspaceMetadata;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Profile; import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.thingsboard.server.dao.cassandra.CassandraCluster; import org.thingsboard.server.dao.cassandra.CassandraCluster;
@ -65,6 +66,7 @@ public class CassandraDatabaseUpgradeService implements DatabaseUpgradeService {
private CassandraCluster cluster; private CassandraCluster cluster;
@Autowired @Autowired
@Qualifier("CassandraInstallCluster")
private CassandraInstallCluster installCluster; private CassandraInstallCluster installCluster;
@Autowired @Autowired

View File

@ -18,7 +18,9 @@ package org.thingsboard.server.service.mail;
import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.JsonNode;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine; import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.exception.VelocityException;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.MessageSource; import org.springframework.context.MessageSource;
@ -26,7 +28,6 @@ import org.springframework.core.NestedRuntimeException;
import org.springframework.mail.javamail.JavaMailSenderImpl; import org.springframework.mail.javamail.JavaMailSenderImpl;
import org.springframework.mail.javamail.MimeMessageHelper; import org.springframework.mail.javamail.MimeMessageHelper;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.ui.velocity.VelocityEngineUtils;
import org.thingsboard.rule.engine.api.MailService; import org.thingsboard.rule.engine.api.MailService;
import org.thingsboard.server.common.data.AdminSettings; import org.thingsboard.server.common.data.AdminSettings;
import org.thingsboard.server.common.data.exception.ThingsboardErrorCode; import org.thingsboard.server.common.data.exception.ThingsboardErrorCode;
@ -39,6 +40,8 @@ import org.thingsboard.server.dao.settings.AdminSettingsService;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.mail.MessagingException; import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMessage;
import java.io.StringWriter;
import java.io.Writer;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale; import java.util.Locale;
import java.util.Map; import java.util.Map;
@ -126,7 +129,7 @@ public class DefaultMailService implements MailService {
Map<String, Object> model = new HashMap<String, Object>(); Map<String, Object> model = new HashMap<String, Object>();
model.put(TARGET_EMAIL, email); model.put(TARGET_EMAIL, email);
String message = VelocityEngineUtils.mergeTemplateIntoString(this.engine, String message = mergeTemplateIntoString(this.engine,
"test.vm", UTF_8, model); "test.vm", UTF_8, model);
sendMail(testMailSender, mailFrom, email, subject, message); sendMail(testMailSender, mailFrom, email, subject, message);
@ -141,7 +144,7 @@ public class DefaultMailService implements MailService {
model.put("activationLink", activationLink); model.put("activationLink", activationLink);
model.put(TARGET_EMAIL, email); model.put(TARGET_EMAIL, email);
String message = VelocityEngineUtils.mergeTemplateIntoString(this.engine, String message = mergeTemplateIntoString(this.engine,
"activation.vm", UTF_8, model); "activation.vm", UTF_8, model);
sendMail(mailSender, mailFrom, email, subject, message); sendMail(mailSender, mailFrom, email, subject, message);
@ -156,7 +159,7 @@ public class DefaultMailService implements MailService {
model.put("loginLink", loginLink); model.put("loginLink", loginLink);
model.put(TARGET_EMAIL, email); model.put(TARGET_EMAIL, email);
String message = VelocityEngineUtils.mergeTemplateIntoString(this.engine, String message = mergeTemplateIntoString(this.engine,
"account.activated.vm", UTF_8, model); "account.activated.vm", UTF_8, model);
sendMail(mailSender, mailFrom, email, subject, message); sendMail(mailSender, mailFrom, email, subject, message);
@ -171,7 +174,7 @@ public class DefaultMailService implements MailService {
model.put("passwordResetLink", passwordResetLink); model.put("passwordResetLink", passwordResetLink);
model.put(TARGET_EMAIL, email); model.put(TARGET_EMAIL, email);
String message = VelocityEngineUtils.mergeTemplateIntoString(this.engine, String message = mergeTemplateIntoString(this.engine,
"reset.password.vm", UTF_8, model); "reset.password.vm", UTF_8, model);
sendMail(mailSender, mailFrom, email, subject, message); sendMail(mailSender, mailFrom, email, subject, message);
@ -186,7 +189,7 @@ public class DefaultMailService implements MailService {
model.put("loginLink", loginLink); model.put("loginLink", loginLink);
model.put(TARGET_EMAIL, email); model.put(TARGET_EMAIL, email);
String message = VelocityEngineUtils.mergeTemplateIntoString(this.engine, String message = mergeTemplateIntoString(this.engine,
"password.was.reset.vm", UTF_8, model); "password.was.reset.vm", UTF_8, model);
sendMail(mailSender, mailFrom, email, subject, message); sendMail(mailSender, mailFrom, email, subject, message);
@ -225,6 +228,22 @@ public class DefaultMailService implements MailService {
} }
} }
private static String mergeTemplateIntoString(VelocityEngine velocityEngine, String templateLocation,
String encoding, Map<String, Object> model) throws VelocityException {
StringWriter result = new StringWriter();
mergeTemplate(velocityEngine, templateLocation, encoding, model, result);
return result.toString();
}
private static void mergeTemplate(
VelocityEngine velocityEngine, String templateLocation, String encoding,
Map<String, Object> model, Writer writer) throws VelocityException {
VelocityContext velocityContext = new VelocityContext(model);
velocityEngine.mergeTemplate(templateLocation, encoding, velocityContext, writer);
}
protected ThingsboardException handleException(Exception exception) { protected ThingsboardException handleException(Exception exception) {
String message; String message;
if (exception instanceof NestedRuntimeException) { if (exception instanceof NestedRuntimeException) {

View File

@ -27,7 +27,6 @@ import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.web.socket.CloseStatus; import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.WebSocketSession;
import org.thingsboard.server.common.data.DataConstants; import org.thingsboard.server.common.data.DataConstants;
import org.thingsboard.server.common.data.id.CustomerId; import org.thingsboard.server.common.data.id.CustomerId;
import org.thingsboard.server.common.data.id.EntityId; import org.thingsboard.server.common.data.id.EntityId;

View File

@ -293,11 +293,13 @@ spring.mvc.cors:
# spring serve gzip compressed static resources # spring serve gzip compressed static resources
spring.resources.chain: spring.resources.chain:
gzipped: "true" compressed: "true"
strategy: strategy:
content: content:
enabled: "true" enabled: "true"
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation: "true"
# HSQLDB DAO Configuration # HSQLDB DAO Configuration
spring: spring:
data: data:
@ -331,7 +333,7 @@ spring:
# password: "${SPRING_DATASOURCE_PASSWORD:postgres}" # password: "${SPRING_DATASOURCE_PASSWORD:postgres}"
# Audit log parameters # Audit log parameters
audit_log: audit-log:
# Enable/disable audit log functionality. # Enable/disable audit log functionality.
enabled: "${AUDIT_LOG_ENABLED:true}" enabled: "${AUDIT_LOG_ENABLED:true}"
# Specify partitioning size for audit log by tenant id storage. Example MINUTES, HOURS, DAYS, MONTHS # Specify partitioning size for audit log by tenant id storage. Example MINUTES, HOURS, DAYS, MONTHS
@ -340,7 +342,7 @@ audit_log:
default_query_period: "${AUDIT_LOG_DEFAULT_QUERY_PERIOD:30}" default_query_period: "${AUDIT_LOG_DEFAULT_QUERY_PERIOD:30}"
# Logging levels per each entity type. # Logging levels per each entity type.
# Allowed values: OFF (disable), W (log write operations), RW (log read and write operations) # Allowed values: OFF (disable), W (log write operations), RW (log read and write operations)
logging_level: logging-level:
mask: mask:
"device": "${AUDIT_LOG_MASK_DEVICE:W}" "device": "${AUDIT_LOG_MASK_DEVICE:W}"
"asset": "${AUDIT_LOG_MASK_ASSET:W}" "asset": "${AUDIT_LOG_MASK_ASSET:W}"

View File

@ -128,7 +128,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC
String accessToken = deviceCredentials.getCredentialsId(); String accessToken = deviceCredentials.getCredentialsId();
assertNotNull(accessToken); assertNotNull(accessToken);
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1},\"timeout\": 6000}";
String deviceId = savedDevice.getId().getId().toString(); String deviceId = savedDevice.getId().getId().toString();
doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isRequestTimeout(), doPostAsync("/api/plugins/rpc/oneway/" + deviceId, setGpioRequest, String.class, status().isRequestTimeout(),
@ -183,7 +183,7 @@ public abstract class AbstractMqttServerSideRpcIntegrationTest extends AbstractC
String accessToken = deviceCredentials.getCredentialsId(); String accessToken = deviceCredentials.getCredentialsId();
assertNotNull(accessToken); assertNotNull(accessToken);
String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1}}"; String setGpioRequest = "{\"method\":\"setGpio\",\"params\":{\"pin\": \"23\",\"value\": 1},\"timeout\": 6000}";
String deviceId = savedDevice.getId().getId().toString(); String deviceId = savedDevice.getId().getId().toString();
doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isRequestTimeout(), doPostAsync("/api/plugins/rpc/twoway/" + deviceId, setGpioRequest, String.class, status().isRequestTimeout(),

View File

@ -111,7 +111,7 @@ public abstract class AbstractMqttTelemetryIntegrationTest extends AbstractContr
client.subscribe("v1/devices/me/attributes", MqttQoS.AT_MOST_ONCE.value()); client.subscribe("v1/devices/me/attributes", MqttQoS.AT_MOST_ONCE.value());
String payload = "{\"key\":\"value\"}"; String payload = "{\"key\":\"value\"}";
String result = doPostAsync("/api/plugins/telemetry/" + savedDevice.getId() + "/SHARED_SCOPE", payload, String.class, status().isOk()); String result = doPostAsync("/api/plugins/telemetry/" + savedDevice.getId() + "/SHARED_SCOPE", payload, String.class, status().isOk());
latch.await(3, TimeUnit.SECONDS); latch.await(10, TimeUnit.SECONDS);
assertEquals(payload, callback.getPayload()); assertEquals(payload, callback.getPayload());
assertEquals(MqttQoS.AT_MOST_ONCE.value(), callback.getQoS()); assertEquals(MqttQoS.AT_MOST_ONCE.value(), callback.getQoS());
} }

View File

@ -18,11 +18,7 @@ package org.thingsboard.server.dao;
import org.thingsboard.server.common.data.id.UUIDBased; import org.thingsboard.server.common.data.id.UUIDBased;
import org.thingsboard.server.dao.model.ToData; import org.thingsboard.server.dao.model.ToData;
import java.util.ArrayList; import java.util.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
public abstract class DaoUtil { public abstract class DaoUtil {
@ -50,6 +46,14 @@ public abstract class DaoUtil {
return object; return object;
} }
public static <T> T getData(Optional<? extends ToData<T>> data) {
T object = null;
if (data.isPresent()) {
object = data.get().toData();
}
return object;
}
public static UUID getId(UUIDBased idBased) { public static UUID getId(UUIDBased idBased) {
UUID id = null; UUID id = null;
if (idBased != null) { if (idBased != null) {

View File

@ -60,7 +60,7 @@ import static org.thingsboard.server.dao.service.Validator.validateId;
@Slf4j @Slf4j
@Service @Service
@ConditionalOnProperty(prefix = "audit_log", value = "enabled", havingValue = "true") @ConditionalOnProperty(prefix = "audit-log", value = "enabled", havingValue = "true")
public class AuditLogServiceImpl implements AuditLogService { public class AuditLogServiceImpl implements AuditLogService {
private static final ObjectMapper objectMapper = new ObjectMapper(); private static final ObjectMapper objectMapper = new ObjectMapper();

View File

@ -88,11 +88,11 @@ public class CassandraAuditLogDao extends CassandraAbstractSearchTimeDao<AuditLo
protected ExecutorService readResultsProcessingExecutor; protected ExecutorService readResultsProcessingExecutor;
@Value("${audit_log.by_tenant_partitioning}") @Value("${audit-log.by_tenant_partitioning}")
private String partitioning; private String partitioning;
private TsPartitionDate tsFormat; private TsPartitionDate tsFormat;
@Value("${audit_log.default_query_period}") @Value("${audit-log.default_query_period}")
private Integer defaultQueryPeriodInDays; private Integer defaultQueryPeriodInDays;
private PreparedStatement partitionInsertStmt; private PreparedStatement partitionInsertStmt;

View File

@ -33,7 +33,7 @@ import org.thingsboard.server.common.data.page.TimePageLink;
import java.util.List; import java.util.List;
@Service @Service
@ConditionalOnProperty(prefix = "audit_log", value = "enabled", havingValue = "false") @ConditionalOnProperty(prefix = "audit-log", value = "enabled", havingValue = "false")
public class DummyAuditLogServiceImpl implements AuditLogService { public class DummyAuditLogServiceImpl implements AuditLogService {
@Override @Override

View File

@ -20,7 +20,7 @@ import org.springframework.stereotype.Component;
import org.thingsboard.server.common.data.audit.AuditLog; import org.thingsboard.server.common.data.audit.AuditLog;
@Component @Component
@ConditionalOnProperty(prefix = "audit_log.sink", value = "type", havingValue = "none") @ConditionalOnProperty(prefix = "audit-log.sink", value = "type", havingValue = "none")
public class DummyAuditLogSink implements AuditLogSink { public class DummyAuditLogSink implements AuditLogSink {
@Override @Override

View File

@ -44,7 +44,7 @@ import java.time.format.DateTimeFormatter;
import java.util.Collections; import java.util.Collections;
@Component @Component
@ConditionalOnProperty(prefix = "audit_log.sink", value = "type", havingValue = "elasticsearch") @ConditionalOnProperty(prefix = "audit-log.sink", value = "type", havingValue = "elasticsearch")
@Slf4j @Slf4j
public class ElasticsearchAuditLogSink implements AuditLogSink { public class ElasticsearchAuditLogSink implements AuditLogSink {
@ -54,19 +54,19 @@ public class ElasticsearchAuditLogSink implements AuditLogSink {
private final ObjectMapper mapper = new ObjectMapper(); private final ObjectMapper mapper = new ObjectMapper();
@Value("${audit_log.sink.index_pattern}") @Value("${audit-log.sink.index_pattern}")
private String indexPattern; private String indexPattern;
@Value("${audit_log.sink.scheme_name}") @Value("${audit-log.sink.scheme_name}")
private String schemeName; private String schemeName;
@Value("${audit_log.sink.host}") @Value("${audit-log.sink.host}")
private String host; private String host;
@Value("${audit_log.sink.port}") @Value("${audit-log.sink.port}")
private int port; private int port;
@Value("${audit_log.sink.user_name}") @Value("${audit-log.sink.user_name}")
private String userName; private String userName;
@Value("${audit_log.sink.password}") @Value("${audit-log.sink.password}")
private String password; private String password;
@Value("${audit_log.sink.date_format}") @Value("${audit-log.sink.date_format}")
private String dateFormat; private String dateFormat;
private RestClient restClient; private RestClient restClient;

View File

@ -19,14 +19,37 @@ import lombok.Data;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.cache.CacheManager; import org.springframework.cache.CacheManager;
import org.springframework.cache.interceptor.SimpleKey;
import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.core.convert.converter.ConditionalGenericConverter;
import org.springframework.core.convert.converter.Converter;
import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cache.interceptor.KeyGenerator; import org.springframework.cache.interceptor.KeyGenerator;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.core.convert.converter.ConverterRegistry;
import org.springframework.data.convert.ReadingConverter;
import org.springframework.data.convert.WritingConverter;
import org.springframework.data.redis.cache.RedisCacheConfiguration;
import org.springframework.data.redis.cache.RedisCacheManager; import org.springframework.data.redis.cache.RedisCacheManager;
import org.springframework.data.redis.connection.RedisConnectionFactory; import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.convert.RedisCustomConversions;
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import org.thingsboard.server.common.data.EntityType;
import org.thingsboard.server.common.data.id.EntityId;
import org.thingsboard.server.common.data.id.EntityIdFactory;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.UUID;
@Configuration @Configuration
@ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis", matchIfMissing = false) @ConditionalOnProperty(prefix = "cache", value = "type", havingValue = "redis", matchIfMissing = false)
@ -57,15 +80,12 @@ public class TBRedisCacheConfiguration {
} }
@Bean @Bean
public RedisTemplate<String, String> redisTemplate(RedisConnectionFactory cf) { public CacheManager cacheManager(RedisConnectionFactory cf) {
RedisTemplate<String, String> redisTemplate = new RedisTemplate<>(); DefaultFormattingConversionService redisConversionService = new DefaultFormattingConversionService();
redisTemplate.setConnectionFactory(cf); RedisCacheConfiguration.registerDefaultConverters(redisConversionService);
return redisTemplate; registerDefaultConverters(redisConversionService);
} RedisCacheConfiguration configuration = RedisCacheConfiguration.defaultCacheConfig().withConversionService(redisConversionService);
return RedisCacheManager.builder(cf).cacheDefaults(configuration).build();
@Bean
public CacheManager cacheManager(RedisTemplate redisTemplate) {
return new RedisCacheManager(redisTemplate);
} }
@Bean @Bean
@ -73,5 +93,8 @@ public class TBRedisCacheConfiguration {
return new PreviousDeviceCredentialsIdKeyGenerator(); return new PreviousDeviceCredentialsIdKeyGenerator();
} }
private static void registerDefaultConverters(ConverterRegistry registry) {
Assert.notNull(registry, "ConverterRegistry must not be null!");
registry.addConverter(EntityId.class, String.class, EntityId::toString);
}
} }

View File

@ -21,7 +21,7 @@ import org.thingsboard.server.dao.util.NoSqlAnyDao;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@Component @Component("CassandraCluster")
@NoSqlAnyDao @NoSqlAnyDao
public class CassandraCluster extends AbstractCassandraCluster { public class CassandraCluster extends AbstractCassandraCluster {

View File

@ -21,7 +21,7 @@ import org.thingsboard.server.dao.util.NoSqlAnyDao;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@Component @Component("CassandraInstallCluster")
@NoSqlAnyDao @NoSqlAnyDao
@Profile("install") @Profile("install")
public class CassandraInstallCluster extends AbstractCassandraCluster { public class CassandraInstallCluster extends AbstractCassandraCluster {

View File

@ -27,6 +27,7 @@ import com.datastax.driver.core.TypeCodec;
import com.datastax.driver.core.exceptions.CodecNotFoundException; import com.datastax.driver.core.exceptions.CodecNotFoundException;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.thingsboard.server.common.data.id.TenantId; import org.thingsboard.server.common.data.id.TenantId;
import org.thingsboard.server.dao.cassandra.CassandraCluster; import org.thingsboard.server.dao.cassandra.CassandraCluster;
import org.thingsboard.server.dao.model.type.AuthorityCodec; import org.thingsboard.server.dao.model.type.AuthorityCodec;
@ -44,6 +45,7 @@ import java.util.concurrent.ConcurrentMap;
public abstract class CassandraAbstractDao { public abstract class CassandraAbstractDao {
@Autowired @Autowired
@Qualifier("CassandraCluster")
protected CassandraCluster cluster; protected CassandraCluster cluster;
private ConcurrentMap<String, PreparedStatement> preparedStatementMap = new ConcurrentHashMap<>(); private ConcurrentMap<String, PreparedStatement> preparedStatementMap = new ConcurrentHashMap<>();

View File

@ -27,6 +27,7 @@ import org.thingsboard.server.dao.DaoUtil;
import org.thingsboard.server.dao.model.BaseEntity; import org.thingsboard.server.dao.model.BaseEntity;
import java.util.List; import java.util.List;
import java.util.Optional;
import java.util.UUID; import java.util.UUID;
import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID; import static org.thingsboard.server.common.data.UUIDConverter.fromTimeUUID;
@ -67,23 +68,23 @@ public abstract class JpaAbstractDao<E extends BaseEntity<D>, D>
@Override @Override
public D findById(TenantId tenantId, UUID key) { public D findById(TenantId tenantId, UUID key) {
log.debug("Get entity by key {}", key); log.debug("Get entity by key {}", key);
E entity = getCrudRepository().findOne(fromTimeUUID(key)); Optional<E> entity = getCrudRepository().findById(fromTimeUUID(key));
return DaoUtil.getData(entity); return DaoUtil.getData(entity);
} }
@Override @Override
public ListenableFuture<D> findByIdAsync(TenantId tenantId, UUID key) { public ListenableFuture<D> findByIdAsync(TenantId tenantId, UUID key) {
log.debug("Get entity by key async {}", key); log.debug("Get entity by key async {}", key);
return service.submit(() -> DaoUtil.getData(getCrudRepository().findOne(fromTimeUUID(key)))); return service.submit(() -> DaoUtil.getData(getCrudRepository().findById(fromTimeUUID(key))));
} }
@Override @Override
@Transactional @Transactional
public boolean removeById(TenantId tenantId, UUID id) { public boolean removeById(TenantId tenantId, UUID id) {
String key = fromTimeUUID(id); String key = fromTimeUUID(id);
getCrudRepository().delete(key); getCrudRepository().deleteById(key);
log.debug("Remove request: {}", key); log.debug("Remove request: {}", key);
return getCrudRepository().findOne(key) == null; return !getCrudRepository().existsById(key);
} }
@Override @Override

View File

@ -52,7 +52,7 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl
AttributeKvCompositeKey compositeKey = AttributeKvCompositeKey compositeKey =
getAttributeKvCompositeKey(entityId, attributeType, attributeKey); getAttributeKvCompositeKey(entityId, attributeType, attributeKey);
return Futures.immediateFuture( return Futures.immediateFuture(
Optional.ofNullable(DaoUtil.getData(attributeKvRepository.findOne(compositeKey)))); Optional.ofNullable(DaoUtil.getData(attributeKvRepository.findById(compositeKey))));
} }
@Override @Override
@ -64,7 +64,7 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl
getAttributeKvCompositeKey(entityId, attributeType, attributeKey)) getAttributeKvCompositeKey(entityId, attributeType, attributeKey))
.collect(Collectors.toList()); .collect(Collectors.toList());
return Futures.immediateFuture( return Futures.immediateFuture(
DaoUtil.convertDataList(Lists.newArrayList(attributeKvRepository.findAll(compositeKeys)))); DaoUtil.convertDataList(Lists.newArrayList(attributeKvRepository.findAllById(compositeKeys))));
} }
@Override @Override
@ -103,7 +103,7 @@ public class JpaAttributeDao extends JpaAbstractDaoListeningExecutorService impl
}).collect(Collectors.toList()); }).collect(Collectors.toList());
return service.submit(() -> { return service.submit(() -> {
attributeKvRepository.delete(entitiesToDelete); attributeKvRepository.deleteAll(entitiesToDelete);
return null; return null;
}); });
} }

View File

@ -66,7 +66,7 @@ public class JpaBaseComponentDescriptorDao extends JpaAbstractSearchTextDao<Comp
if (component.getId() == null) { if (component.getId() == null) {
component.setId(new ComponentDescriptorId(UUIDs.timeBased())); component.setId(new ComponentDescriptorId(UUIDs.timeBased()));
} }
if (componentDescriptorRepository.findOne(UUIDConverter.fromTimeUUID(component.getId().getId())) == null) { if (!componentDescriptorRepository.existsById(UUIDConverter.fromTimeUUID(component.getId().getId()))) {
return Optional.of(save(tenantId, component)); return Optional.of(save(tenantId, component));
} }
return Optional.empty(); return Optional.empty();

View File

@ -97,13 +97,13 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple
@Override @Override
public ListenableFuture<Boolean> checkRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { public ListenableFuture<Boolean> checkRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
RelationCompositeKey key = getRelationCompositeKey(from, to, relationType, typeGroup); RelationCompositeKey key = getRelationCompositeKey(from, to, relationType, typeGroup);
return service.submit(() -> relationRepository.findOne(key) != null); return service.submit(() -> relationRepository.existsById(key));
} }
@Override @Override
public ListenableFuture<EntityRelation> getRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { public ListenableFuture<EntityRelation> getRelation(TenantId tenantId, EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
RelationCompositeKey key = getRelationCompositeKey(from, to, relationType, typeGroup); RelationCompositeKey key = getRelationCompositeKey(from, to, relationType, typeGroup);
return service.submit(() -> DaoUtil.getData(relationRepository.findOne(key))); return service.submit(() -> DaoUtil.getData(relationRepository.findById(key)));
} }
private RelationCompositeKey getRelationCompositeKey(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) { private RelationCompositeKey getRelationCompositeKey(EntityId from, EntityId to, String relationType, RelationTypeGroup typeGroup) {
@ -152,9 +152,9 @@ public class JpaRelationDao extends JpaAbstractDaoListeningExecutorService imple
} }
private boolean deleteRelationIfExists(RelationCompositeKey key) { private boolean deleteRelationIfExists(RelationCompositeKey key) {
boolean relationExistsBeforeDelete = relationRepository.exists(key); boolean relationExistsBeforeDelete = relationRepository.existsById(key);
if (relationExistsBeforeDelete) { if (relationExistsBeforeDelete) {
relationRepository.delete(key); relationRepository.deleteById(key);
} }
return relationExistsBeforeDelete; return relationExistsBeforeDelete;
} }

View File

@ -53,7 +53,7 @@ public interface RelationRepository
RelationEntity save(RelationEntity entity); RelationEntity save(RelationEntity entity);
@Transactional @Transactional
void delete(RelationCompositeKey id); void deleteById(RelationCompositeKey id);
@Transactional @Transactional
void deleteByFromIdAndFromType(String fromId, String fromType); void deleteByFromIdAndFromType(String fromId, String fromType);

View File

@ -284,10 +284,10 @@ public class JpaTimeseriesDao extends JpaAbstractDaoListeningExecutorService imp
entityId.getEntityType(), entityId.getEntityType(),
fromTimeUUID(entityId.getId()), fromTimeUUID(entityId.getId()),
key); key);
TsKvLatestEntity entry = tsKvLatestRepository.findOne(compositeKey); Optional<TsKvLatestEntity> entry = tsKvLatestRepository.findById(compositeKey);
TsKvEntry result; TsKvEntry result;
if (entry != null) { if (entry.isPresent()) {
result = DaoUtil.getData(entry); result = DaoUtil.getData(entry.get());
} else { } else {
result = new BasicTsKvEntry(System.currentTimeMillis(), new StringDataEntry(key, null)); result = new BasicTsKvEntry(System.currentTimeMillis(), new StringDataEntry(key, null));
} }

View File

@ -82,6 +82,7 @@ public class CustomCassandraCQLUnit extends BaseCassandraUnit {
session = null; session = null;
cluster = null; cluster = null;
} }
System.setSecurityManager(null);
} }
// Getters for those who do not like to directly access fields // Getters for those who do not like to directly access fields

View File

@ -4,10 +4,10 @@ zk.zk_dir=/thingsboard
updates.enabled=false updates.enabled=false
audit_log.enabled=true audit-log.enabled=true
audit_log.by_tenant_partitioning=MONTHS audit-log.by_tenant_partitioning=MONTHS
audit_log.default_query_period=30 audit-log.default_query_period=30
audit_log.sink.type=none audit-log.sink.type=none
cache.type=caffeine cache.type=caffeine
#cache.type=redis #cache.type=redis

View File

@ -4,6 +4,7 @@ database.entities.type=sql
sql.ts_inserts_executor_type=fixed sql.ts_inserts_executor_type=fixed
sql.ts_inserts_fixed_thread_pool_size=10 sql.ts_inserts_fixed_thread_pool_size=10
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
spring.jpa.show-sql=false spring.jpa.show-sql=false
spring.jpa.hibernate.ddl-auto=validate spring.jpa.hibernate.ddl-auto=validate
spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect spring.jpa.database-platform=org.hibernate.dialect.HSQLDialect

38
pom.xml
View File

@ -29,10 +29,10 @@
<properties> <properties>
<main.dir>${basedir}</main.dir> <main.dir>${basedir}</main.dir>
<spring-boot.version>1.4.3.RELEASE</spring-boot.version> <spring-boot.version>2.1.3.RELEASE</spring-boot.version>
<spring.version>4.3.4.RELEASE</spring.version> <spring.version>5.1.5.RELEASE</spring.version>
<spring-security.version>4.2.0.RELEASE</spring-security.version> <spring-security.version>5.1.4.RELEASE</spring-security.version>
<spring-data-redis.version>1.8.10.RELEASE</spring-data-redis.version> <spring-data-redis.version>2.1.5.RELEASE</spring-data-redis.version>
<jedis.version>2.9.0</jedis.version> <jedis.version>2.9.0</jedis.version>
<jjwt.version>0.7.0</jjwt.version> <jjwt.version>0.7.0</jjwt.version>
<json-path.version>2.2.0</json-path.version> <json-path.version>2.2.0</json-path.version>
@ -41,8 +41,8 @@
<logback.version>1.2.3</logback.version> <logback.version>1.2.3</logback.version>
<mockito.version>1.9.5</mockito.version> <mockito.version>1.9.5</mockito.version>
<rat.version>0.10</rat.version> <rat.version>0.10</rat.version>
<cassandra.version>3.5.0</cassandra.version> <cassandra.version>3.6.0</cassandra.version>
<cassandra-unit.version>3.3.0.2</cassandra-unit.version> <cassandra-unit.version>3.5.0.1</cassandra-unit.version>
<takari-cpsuite.version>1.2.7</takari-cpsuite.version> <takari-cpsuite.version>1.2.7</takari-cpsuite.version>
<guava.version>21.0</guava.version> <guava.version>21.0</guava.version>
<caffeine.version>2.6.1</caffeine.version> <caffeine.version>2.6.1</caffeine.version>
@ -50,7 +50,7 @@
<commons-validator.version>1.5.0</commons-validator.version> <commons-validator.version>1.5.0</commons-validator.version>
<commons-io.version>2.5</commons-io.version> <commons-io.version>2.5</commons-io.version>
<commons-csv.version>1.4</commons-csv.version> <commons-csv.version>1.4</commons-csv.version>
<jackson.version>2.8.11.1</jackson.version> <jackson.version>2.9.7</jackson.version>
<json-schema-validator.version>2.2.6</json-schema-validator.version> <json-schema-validator.version>2.2.6</json-schema-validator.version>
<scala.version>2.11</scala.version> <scala.version>2.11</scala.version>
<akka.version>2.4.2</akka.version> <akka.version>2.4.2</akka.version>
@ -60,11 +60,11 @@
<velocity-tools.version>2.0</velocity-tools.version> <velocity-tools.version>2.0</velocity-tools.version>
<mail.version>1.4.3</mail.version> <mail.version>1.4.3</mail.version>
<curator.version>4.0.1</curator.version> <curator.version>4.0.1</curator.version>
<protobuf.version>3.0.2</protobuf.version> <protobuf.version>3.6.1</protobuf.version>
<grpc.version>1.12.0</grpc.version> <grpc.version>1.16.1</grpc.version>
<lombok.version>1.16.18</lombok.version> <lombok.version>1.16.18</lombok.version>
<paho.client.version>1.1.0</paho.client.version> <paho.client.version>1.1.0</paho.client.version>
<netty.version>4.1.22.Final</netty.version> <netty.version>4.1.30.Final</netty.version>
<os-maven-plugin.version>1.5.0</os-maven-plugin.version> <os-maven-plugin.version>1.5.0</os-maven-plugin.version>
<rabbitmq.version>4.8.0</rabbitmq.version> <rabbitmq.version>4.8.0</rabbitmq.version>
<surfire.version>2.19.1</surfire.version> <surfire.version>2.19.1</surfire.version>
@ -85,6 +85,8 @@
<kafka.version>2.0.0</kafka.version> <kafka.version>2.0.0</kafka.version>
<bucket4j.version>4.1.1</bucket4j.version> <bucket4j.version>4.1.1</bucket4j.version>
<fst.version>2.57</fst.version> <fst.version>2.57</fst.version>
<antlr.version>2.7.7</antlr.version>
<snakeyaml.version>1.23</snakeyaml.version>
</properties> </properties>
<modules> <modules>
@ -512,6 +514,16 @@
</exclusion> </exclusion>
</exclusions> </exclusions>
</dependency> </dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>${snakeyaml.version}</version>
</dependency>
<dependency>
<groupId>antlr</groupId>
<artifactId>antlr</artifactId>
<version>${antlr.version}</version>
</dependency>
<dependency> <dependency>
<groupId>com.rabbitmq</groupId> <groupId>com.rabbitmq</groupId>
<artifactId>amqp-client</artifactId> <artifactId>amqp-client</artifactId>
@ -794,6 +806,12 @@
<groupId>de.ruedigermoeller</groupId> <groupId>de.ruedigermoeller</groupId>
<artifactId>fst</artifactId> <artifactId>fst</artifactId>
<version>${fst.version}</version> <version>${fst.version}</version>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
</exclusions>
</dependency> </dependency>
<dependency> <dependency>
<groupId>io.springfox.ui</groupId> <groupId>io.springfox.ui</groupId>