From 7c5e9430cb6484f0c820dc5709dca0d4d39784fd Mon Sep 17 00:00:00 2001 From: ikalyvas Date: Thu, 28 Feb 2019 12:23:08 +0200 Subject: [PATCH] Logging Circuit breaker --- .../logger/common/AbstractBatchLogger.java | 10 +- .../logger/remote/http/HttpRemoteLogger.java | 456 +++++++++--------- .../ElasticSearchConfiguration.java | 9 +- .../sql}/DevelDatabaseConfiguration.java | 3 +- .../sql}/ProductionDatabaseConfiguration.java | 2 +- .../DynamicProjectConfigurationDevelImpl.java | 6 +- .../http/HttpClientConfigurations.java | 48 ++ .../{ => misc}/ExecutorServiceConfig.java | 5 +- .../{ => web}/WebMVCConfiguration.java | 2 +- .../CircuitBreakerHttpClientInterceptor.java | 27 ++ .../utilities/circuitbreaker/Circuit.java | 98 ++++ .../circuitbreaker/CircuitBreaker.java | 47 ++ .../utilities/interfaces/CheckedSupplier.java | 8 + 13 files changed, 469 insertions(+), 252 deletions(-) rename dmp-backend/web/src/main/java/eu/eudat/configurations/{ => database/elasticsearch}/ElasticSearchConfiguration.java (75%) rename dmp-backend/web/src/main/java/eu/eudat/configurations/{ => database/sql}/DevelDatabaseConfiguration.java (96%) rename dmp-backend/web/src/main/java/eu/eudat/configurations/{ => database/sql}/ProductionDatabaseConfiguration.java (98%) create mode 100644 dmp-backend/web/src/main/java/eu/eudat/configurations/http/HttpClientConfigurations.java rename dmp-backend/web/src/main/java/eu/eudat/configurations/{ => misc}/ExecutorServiceConfig.java (79%) rename dmp-backend/web/src/main/java/eu/eudat/configurations/{ => web}/WebMVCConfiguration.java (97%) create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/handlers/CircuitBreakerHttpClientInterceptor.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/utilities/circuitbreaker/Circuit.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/utilities/circuitbreaker/CircuitBreaker.java create mode 100644 dmp-backend/web/src/main/java/eu/eudat/logic/utilities/interfaces/CheckedSupplier.java diff --git a/dmp-backend/logging/src/main/java/eu/eudat/core/logger/common/AbstractBatchLogger.java b/dmp-backend/logging/src/main/java/eu/eudat/core/logger/common/AbstractBatchLogger.java index e9938a5ff..15d915950 100644 --- a/dmp-backend/logging/src/main/java/eu/eudat/core/logger/common/AbstractBatchLogger.java +++ b/dmp-backend/logging/src/main/java/eu/eudat/core/logger/common/AbstractBatchLogger.java @@ -21,7 +21,13 @@ public abstract class AbstractBatchLogger { public AbstractBatchLogger(Environment environment) { ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); - executor.scheduleAtFixedRate(() -> this.outputData(), Long.parseLong(environment.getProperty("http-logger.initial-delay")), Long.parseLong(environment.getProperty("http-logger.delay")), TimeUnit.SECONDS); + executor.scheduleAtFixedRate(() -> { + try { + this.outputData(); + } catch (Exception e) { + + } + }, Long.parseLong(environment.getProperty("http-logger.initial-delay")), Long.parseLong(environment.getProperty("http-logger.delay")), TimeUnit.SECONDS); } public abstract LoggingOutputType logOutputType(); @@ -53,5 +59,5 @@ public abstract class AbstractBatchLogger { } else return null; } - public abstract void outputData(); + public abstract void outputData() throws Exception; } diff --git a/dmp-backend/logging/src/main/java/eu/eudat/core/logger/remote/http/HttpRemoteLogger.java b/dmp-backend/logging/src/main/java/eu/eudat/core/logger/remote/http/HttpRemoteLogger.java index 774fdff9a..0e88eca34 100644 --- a/dmp-backend/logging/src/main/java/eu/eudat/core/logger/remote/http/HttpRemoteLogger.java +++ b/dmp-backend/logging/src/main/java/eu/eudat/core/logger/remote/http/HttpRemoteLogger.java @@ -15,7 +15,6 @@ import org.springframework.core.env.Environment; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.HttpMethod; -import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import types.LoggingOutputType; @@ -31,257 +30,252 @@ import java.util.Map; @Service("logger") public class HttpRemoteLogger extends AbstractBatchLogger implements Logger { - private RestTemplate rest; - private HttpHeaders headers; - private Environment environment; + private RestTemplate rest; + private HttpHeaders headers; + private Environment environment; - @Autowired - public HttpRemoteLogger(Environment environment) { - super(environment); - this.rest = new RestTemplate(); - this.headers = new HttpHeaders(); - this.environment = environment; - headers.add("Content-Type", "application/json"); - headers.add("Accept", "*/*"); - } + @Autowired + public HttpRemoteLogger(Environment environment, RestTemplate loggerClient) { + super(environment); + this.rest = loggerClient; + this.headers = new HttpHeaders(); + this.environment = environment; + headers.add("Content-Type", "application/json"); + headers.add("Accept", "*/*"); + } - @Override - public void outputData() { - try { - String log = this.tranformLog(); - if (log != null) { - HttpEntity requestEntity = new HttpEntity(log, headers); - ResponseEntity Object = rest.exchange(this.environment.getProperty("http-logger.server-address"), HttpMethod.POST, requestEntity, String.class); - } - } catch (Exception ex) { - ex.printStackTrace(); - } + @Override + public void outputData() throws Exception { + String log = this.tranformLog(); + if (log != null) { + HttpEntity requestEntity = new HttpEntity(log, headers); + rest.exchange(this.environment.getProperty("http-logger.server-address"), HttpMethod.POST, requestEntity, String.class); + } + } - } + @Override + public LoggingOutputType logOutputType() { + return LoggingOutputType.JSON; + } - @Override - public LoggingOutputType logOutputType() { - return LoggingOutputType.JSON; - } + @Override + public void debug(T model) { + LoggingModel loggingModel = new SimpleLoggingModel<>(); + loggingModel.setData(model); + loggingModel.setType(LoggingType.DEBUG); + this.put(String.valueOf(model.hashCode()), loggingModel); + } - @Override - public void debug(T model) { - LoggingModel loggingModel = new SimpleLoggingModel<>(); - loggingModel.setData(model); - loggingModel.setType(LoggingType.DEBUG); - this.put(String.valueOf(model.hashCode()), loggingModel); - } + @Override + public void debug(T model, String message) { + LoggingModel loggingModel = new SimpleLoggingModel<>(); + loggingModel.setData(model); + loggingModel.setMessage(message); + loggingModel.setType(LoggingType.DEBUG); + this.put(String.valueOf(model.hashCode()), loggingModel); + } - @Override - public void debug(T model, String message) { - LoggingModel loggingModel = new SimpleLoggingModel<>(); - loggingModel.setData(model); - loggingModel.setMessage(message); - loggingModel.setType(LoggingType.DEBUG); - this.put(String.valueOf(model.hashCode()), loggingModel); - } + @Override + public void debug(String message) { + LoggingModel loggingModel = new SimpleLoggingModel<>(); + loggingModel.setMessage(message); + loggingModel.setType(LoggingType.DEBUG); + this.put(String.valueOf(message.hashCode()), loggingModel); + } - @Override - public void debug(String message) { - LoggingModel loggingModel = new SimpleLoggingModel<>(); - loggingModel.setMessage(message); - loggingModel.setType(LoggingType.DEBUG); - this.put(String.valueOf(message.hashCode()), loggingModel); - } + @Override + public void debug(T exception) { + ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); + Map map = new HashMap<>(); + ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + try { + String json = ow.writeValueAsString(exception); + map.put("exception", json); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + exceptionLoggingModel.setData(map); + exceptionLoggingModel.setType(LoggingType.DEBUG); + this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); + } - @Override - public void debug(T exception) { - ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); - Map map = new HashMap<>(); - ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); - try { - String json = ow.writeValueAsString(exception); - map.put("exception", json); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - exceptionLoggingModel.setData(map); - exceptionLoggingModel.setType(LoggingType.DEBUG); - this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); - } + @Override + public void debug(T exception, String message) { + ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); + Map map = new HashMap<>(); + ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + try { + String json = ow.writeValueAsString(exception); + map.put("exception", json); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } - @Override - public void debug(T exception, String message) { - ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); - Map map = new HashMap<>(); - ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); - try { - String json = ow.writeValueAsString(exception); - map.put("exception", json); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } + exceptionLoggingModel.setData(map); + exceptionLoggingModel.setMessage(message); + exceptionLoggingModel.setType(LoggingType.DEBUG); + this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); + } - exceptionLoggingModel.setData(map); - exceptionLoggingModel.setMessage(message); - exceptionLoggingModel.setType(LoggingType.DEBUG); - this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); - } + @Override + public void warn(T model) { + LoggingModel loggingModel = new SimpleLoggingModel<>(); + loggingModel.setData(model); + loggingModel.setType(LoggingType.WARNING); + this.put(String.valueOf(model.hashCode()), loggingModel); + } - @Override - public void warn(T model) { - LoggingModel loggingModel = new SimpleLoggingModel<>(); - loggingModel.setData(model); - loggingModel.setType(LoggingType.WARNING); - this.put(String.valueOf(model.hashCode()), loggingModel); - } + @Override + public void warn(T model, String message) { + LoggingModel loggingModel = new SimpleLoggingModel<>(); + loggingModel.setData(model); + loggingModel.setMessage(message); + loggingModel.setType(LoggingType.WARNING); + this.put(String.valueOf(model.hashCode()), loggingModel); + } - @Override - public void warn(T model, String message) { - LoggingModel loggingModel = new SimpleLoggingModel<>(); - loggingModel.setData(model); - loggingModel.setMessage(message); - loggingModel.setType(LoggingType.WARNING); - this.put(String.valueOf(model.hashCode()), loggingModel); - } + @Override + public void warn(String message) { + LoggingModel loggingModel = new SimpleLoggingModel<>(); + loggingModel.setMessage(message); + loggingModel.setType(LoggingType.WARNING); + this.put(String.valueOf(message.hashCode()), loggingModel); + } - @Override - public void warn(String message) { - LoggingModel loggingModel = new SimpleLoggingModel<>(); - loggingModel.setMessage(message); - loggingModel.setType(LoggingType.WARNING); - this.put(String.valueOf(message.hashCode()), loggingModel); - } + @Override + public void warn(T exception) { + ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); + Map map = new HashMap<>(); + ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + try { + String json = ow.writeValueAsString(exception); + map.put("exception", json); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + exceptionLoggingModel.setData(map); + exceptionLoggingModel.setType(LoggingType.WARNING); + this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); + } - @Override - public void warn(T exception) { - ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); - Map map = new HashMap<>(); - ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); - try { - String json = ow.writeValueAsString(exception); - map.put("exception", json); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - exceptionLoggingModel.setData(map); - exceptionLoggingModel.setType(LoggingType.WARNING); - this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); - } + @Override + public void warn(T exception, String message) { + ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); + Map map = new HashMap<>(); + ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + try { + String json = ow.writeValueAsString(exception); + map.put("exception", json); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + exceptionLoggingModel.setData(map); + exceptionLoggingModel.setMessage(message); + exceptionLoggingModel.setType(LoggingType.WARNING); + this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); + } - @Override - public void warn(T exception, String message) { - ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); - Map map = new HashMap<>(); - ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); - try { - String json = ow.writeValueAsString(exception); - map.put("exception", json); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - exceptionLoggingModel.setData(map); - exceptionLoggingModel.setMessage(message); - exceptionLoggingModel.setType(LoggingType.WARNING); - this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); - } + @Override + public void info(String message) { + SimpleAuditModel simpleAuditModel = new SimpleAuditModel<>(); + simpleAuditModel.setMessage(message); + simpleAuditModel.setType(LoggingType.INFO); + this.put(String.valueOf(simpleAuditModel.hashCode()), simpleAuditModel); + } - @Override - public void info(String message) { - SimpleAuditModel simpleAuditModel = new SimpleAuditModel<>(); - simpleAuditModel.setMessage(message); - simpleAuditModel.setType(LoggingType.INFO); - this.put(String.valueOf(simpleAuditModel.hashCode()), simpleAuditModel); - } + @Override + public void info(T model) { + SimpleAuditModel simpleAuditModel = new SimpleAuditModel<>(); + simpleAuditModel.setData(model); + simpleAuditModel.setType(LoggingType.INFO); + this.put(String.valueOf(model.hashCode()), simpleAuditModel); + } - @Override - public void info(T model) { - SimpleAuditModel simpleAuditModel = new SimpleAuditModel<>(); - simpleAuditModel.setData(model); - simpleAuditModel.setType(LoggingType.INFO); - this.put(String.valueOf(model.hashCode()), simpleAuditModel); - } + @Override + public void info(T model, String message) { + SimpleAuditModel simpleAuditModel = new SimpleAuditModel<>(); + simpleAuditModel.setData(model); + simpleAuditModel.setMessage(message); + simpleAuditModel.setType(LoggingType.INFO); + this.put(String.valueOf(model.hashCode()), simpleAuditModel); + } - @Override - public void info(T model, String message) { - SimpleAuditModel simpleAuditModel = new SimpleAuditModel<>(); - simpleAuditModel.setData(model); - simpleAuditModel.setMessage(message); - simpleAuditModel.setType(LoggingType.INFO); - this.put(String.valueOf(model.hashCode()), simpleAuditModel); - } + @Override + public void info(T exception) { + ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); + Map map = new HashMap<>(); + ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + try { + String json = ow.writeValueAsString(exception); + map.put("exception", json); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + exceptionLoggingModel.setData(map); + exceptionLoggingModel.setType(LoggingType.INFO); + this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); + } - @Override - public void info(T exception) { - ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); - Map map = new HashMap<>(); - ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); - try { - String json = ow.writeValueAsString(exception); - map.put("exception", json); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - exceptionLoggingModel.setData(map); - exceptionLoggingModel.setType(LoggingType.INFO); - this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); - } + @Override + public void info(T exception, String message) { + ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); + Map map = new HashMap<>(); + ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + try { + String json = ow.writeValueAsString(exception); + map.put("exception", json); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + exceptionLoggingModel.setData(map); + exceptionLoggingModel.setMessage(message); + exceptionLoggingModel.setType(LoggingType.INFO); + this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); + } - @Override - public void info(T exception, String message) { - ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); - Map map = new HashMap<>(); - ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); - try { - String json = ow.writeValueAsString(exception); - map.put("exception", json); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - exceptionLoggingModel.setData(map); - exceptionLoggingModel.setMessage(message); - exceptionLoggingModel.setType(LoggingType.INFO); - this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); - } + @Override + public void error(ApiExceptionLoggingModel model) { + this.put(String.valueOf(model.hashCode()), model); + } - @Override - public void error(ApiExceptionLoggingModel model) { - this.put(String.valueOf(model.hashCode()), model); - } + @Override + public void error(T model) { + LoggingModel loggingModel = new SimpleLoggingModel<>(); + loggingModel.setType(LoggingType.DEBUG); + loggingModel.setData(model); + this.put(String.valueOf(model.hashCode()), loggingModel); + } - @Override - public void error(T model) { - LoggingModel loggingModel = new SimpleLoggingModel<>(); - loggingModel.setType(LoggingType.DEBUG); - loggingModel.setData(model); - this.put(String.valueOf(model.hashCode()), loggingModel); - } + @Override + public void error(T exception) { + ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); + Map map = new HashMap<>(); + ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + try { + String json = ow.writeValueAsString(exception); + map.put("exception", json); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + exceptionLoggingModel.setData(map); + exceptionLoggingModel.setType(LoggingType.ERROR); + this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); + } - @Override - public void error(T exception) { - ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); - Map map = new HashMap<>(); - ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); - try { - String json = ow.writeValueAsString(exception); - map.put("exception", json); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - exceptionLoggingModel.setData(map); - exceptionLoggingModel.setType(LoggingType.ERROR); - this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); - } - - @Override - public void error(T exception, String message) { - ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); - Map map = new HashMap<>(); - ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); - try { - String json = ow.writeValueAsString(exception); - map.put("exception", json); - } catch (JsonProcessingException e) { - e.printStackTrace(); - } - exceptionLoggingModel.setData(map); - exceptionLoggingModel.setMessage(message); - exceptionLoggingModel.setType(LoggingType.ERROR); - this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); - } + @Override + public void error(T exception, String message) { + ExceptionLoggingModel exceptionLoggingModel = new ExceptionLoggingModel(); + Map map = new HashMap<>(); + ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); + try { + String json = ow.writeValueAsString(exception); + map.put("exception", json); + } catch (JsonProcessingException e) { + e.printStackTrace(); + } + exceptionLoggingModel.setData(map); + exceptionLoggingModel.setMessage(message); + exceptionLoggingModel.setType(LoggingType.ERROR); + this.put(String.valueOf(exception.hashCode()), exceptionLoggingModel); + } } diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/ElasticSearchConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/database/elasticsearch/ElasticSearchConfiguration.java similarity index 75% rename from dmp-backend/web/src/main/java/eu/eudat/configurations/ElasticSearchConfiguration.java rename to dmp-backend/web/src/main/java/eu/eudat/configurations/database/elasticsearch/ElasticSearchConfiguration.java index e9e8f9b1c..358296c35 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/ElasticSearchConfiguration.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/database/elasticsearch/ElasticSearchConfiguration.java @@ -1,20 +1,13 @@ -package eu.eudat.configurations; +package eu.eudat.configurations.database.elasticsearch; import org.apache.http.HttpHost; -import org.elasticsearch.client.Client; import org.elasticsearch.client.RestClient; import org.elasticsearch.client.RestHighLevelClient; -import org.elasticsearch.client.transport.TransportClient; -import org.elasticsearch.common.settings.Settings; -import org.elasticsearch.common.transport.TransportAddress; -import org.elasticsearch.transport.client.PreBuiltTransportClient; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; -import java.net.InetAddress; - /** * Created by ikalyvas on 7/5/2018. */ diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/DevelDatabaseConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/database/sql/DevelDatabaseConfiguration.java similarity index 96% rename from dmp-backend/web/src/main/java/eu/eudat/configurations/DevelDatabaseConfiguration.java rename to dmp-backend/web/src/main/java/eu/eudat/configurations/database/sql/DevelDatabaseConfiguration.java index 1c5c48bed..1ac6fb920 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/DevelDatabaseConfiguration.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/database/sql/DevelDatabaseConfiguration.java @@ -1,4 +1,4 @@ -package eu.eudat.configurations; +package eu.eudat.configurations.database.sql; import org.springframework.beans.factory.annotation.Autowired; @@ -7,7 +7,6 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.context.annotation.*; import org.springframework.core.env.Environment; import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; -import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/ProductionDatabaseConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/database/sql/ProductionDatabaseConfiguration.java similarity index 98% rename from dmp-backend/web/src/main/java/eu/eudat/configurations/ProductionDatabaseConfiguration.java rename to dmp-backend/web/src/main/java/eu/eudat/configurations/database/sql/ProductionDatabaseConfiguration.java index e26ca6732..eaf714595 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/ProductionDatabaseConfiguration.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/database/sql/ProductionDatabaseConfiguration.java @@ -1,4 +1,4 @@ -package eu.eudat.configurations; +package eu.eudat.configurations.database.sql; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java index 62306332c..0aa73d4c6 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/dynamicproject/DynamicProjectConfigurationDevelImpl.java @@ -48,7 +48,7 @@ public class DynamicProjectConfigurationDevelImpl implements DynamicProjectConfi JAXBContext jaxbContext = JAXBContext.newInstance(Configuration.class); Unmarshaller jaxbUnmarshaller = jaxbContext.createUnmarshaller(); - is = new URL("file:///"+current + "/web/src/main/resources/ProjectConfiguration.xml").openStream(); + is = new URL("file:///"+current + "/dmp-backend/web/src/main/resources/ProjectConfiguration.xml").openStream(); this.configuration = (Configuration) jaxbUnmarshaller.unmarshal(is); } catch (Exception ex) { ex.printStackTrace(); @@ -69,14 +69,14 @@ public class DynamicProjectConfigurationDevelImpl implements DynamicProjectConfi Configuration configuration = this.getConfiguration(); List fields = new LinkedList<>(); List properties = configuration.getConfigurationProperties(); - properties.stream().forEach(item -> { + properties.forEach(item -> { DynamicField dynamicField = new DynamicField(); dynamicField.setId(item.getId()); dynamicField.setName(item.getName()); dynamicField.setQueryProperty(item.getQueryProperty()); dynamicField.setRequired(item.getRequired()); List dependencies = new LinkedList<>(); - item.getDependencies().stream().forEach(dependency -> { + item.getDependencies().forEach(dependency -> { Dependency modelDependency = new Dependency(); modelDependency.setId(dependency.getId()); modelDependency.setQueryProperty(dependency.getQueryProperty()); diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/http/HttpClientConfigurations.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/http/HttpClientConfigurations.java new file mode 100644 index 000000000..5de016e13 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/http/HttpClientConfigurations.java @@ -0,0 +1,48 @@ +package eu.eudat.configurations.http; + +import eu.eudat.logic.handlers.CircuitBreakerHttpClientInterceptor; +import eu.eudat.logic.utilities.circuitbreaker.Circuit; +import eu.eudat.logic.utilities.circuitbreaker.CircuitBreaker; +import org.apache.commons.collections4.CollectionUtils; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.web.client.RestTemplate; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by ikalyvas on 2/25/2019. + */ +@Configuration +public class HttpClientConfigurations { + + @Bean + public RestTemplate loggerClient(CircuitBreaker circuitBreaker) { + RestTemplate restTemplate = new RestTemplate(); + + List interceptors + = restTemplate.getInterceptors(); + if (CollectionUtils.isEmpty(interceptors)) { + interceptors = new ArrayList<>(); + } + interceptors.add(new CircuitBreakerHttpClientInterceptor(circuitBreaker)); + restTemplate.setInterceptors(interceptors); + return restTemplate; + } + + @Bean + public CircuitBreaker circuitBreaker(){ + CircuitBreaker circuitBreaker = new CircuitBreaker(); + circuitBreaker.addCircuitResolver( + new Circuit.CircuitBuilder() + .url("http://localhost:31311") + .method("POST") + .build(), + httpRequest -> { + System.out.println(httpRequest); + }); + return circuitBreaker; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/ExecutorServiceConfig.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/misc/ExecutorServiceConfig.java similarity index 79% rename from dmp-backend/web/src/main/java/eu/eudat/configurations/ExecutorServiceConfig.java rename to dmp-backend/web/src/main/java/eu/eudat/configurations/misc/ExecutorServiceConfig.java index 78da24f79..28944e8dd 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/ExecutorServiceConfig.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/misc/ExecutorServiceConfig.java @@ -1,13 +1,10 @@ -package eu.eudat.configurations; +package eu.eudat.configurations.misc; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; -import org.springframework.core.task.TaskExecutor; import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor; import java.util.concurrent.Executor; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; /** * Created by ikalyvas on 9/26/2018. diff --git a/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java b/dmp-backend/web/src/main/java/eu/eudat/configurations/web/WebMVCConfiguration.java similarity index 97% rename from dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java rename to dmp-backend/web/src/main/java/eu/eudat/configurations/web/WebMVCConfiguration.java index 91fb7babc..fe37d4b32 100644 --- a/dmp-backend/web/src/main/java/eu/eudat/configurations/WebMVCConfiguration.java +++ b/dmp-backend/web/src/main/java/eu/eudat/configurations/web/WebMVCConfiguration.java @@ -1,4 +1,4 @@ -package eu.eudat.configurations; +package eu.eudat.configurations.web; import eu.eudat.controllers.interceptors.RequestInterceptor; import eu.eudat.logic.handlers.PrincipalArgumentResolver; diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/handlers/CircuitBreakerHttpClientInterceptor.java b/dmp-backend/web/src/main/java/eu/eudat/logic/handlers/CircuitBreakerHttpClientInterceptor.java new file mode 100644 index 000000000..77179429b --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/handlers/CircuitBreakerHttpClientInterceptor.java @@ -0,0 +1,27 @@ +package eu.eudat.logic.handlers; + +import eu.eudat.logic.utilities.circuitbreaker.CircuitBreaker; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpRequest; +import org.springframework.http.client.ClientHttpRequestExecution; +import org.springframework.http.client.ClientHttpRequestInterceptor; +import org.springframework.http.client.ClientHttpResponse; + +/** + * Created by ikalyvas on 2/25/2019. + */ +public class CircuitBreakerHttpClientInterceptor implements ClientHttpRequestInterceptor { + + private CircuitBreaker circuitBreaker; + + @Autowired + public CircuitBreakerHttpClientInterceptor(CircuitBreaker circuitBreaker) { + this.circuitBreaker = circuitBreaker; + } + + @Override + public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) { + System.out.println(request); + return this.circuitBreaker.handle(request, () -> execution.execute(request, body)); + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/circuitbreaker/Circuit.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/circuitbreaker/Circuit.java new file mode 100644 index 000000000..3a9d4c2eb --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/circuitbreaker/Circuit.java @@ -0,0 +1,98 @@ +package eu.eudat.logic.utilities.circuitbreaker; + +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +/** + * Created by ikalyvas on 2/25/2019. + */ + + +public final class Circuit { + private final String url; + private final String method; + private Integer numberOfFails; + private CircuitState state; + private final Integer MAX_NUMBER_OF_FAILS = 5; + public String getUrl() { + return url; + } + + public String getMethod() { + return method; + } + + public Integer getNumberOfFails() { + return numberOfFails; + } + + public Circuit(String url, String method, Integer numberOfFails) { + this.url = url; + this.method = method; + this.numberOfFails = numberOfFails; + ScheduledExecutorService executor = Executors.newScheduledThreadPool(1); + executor.scheduleAtFixedRate(this::halfOpenCircuit, 0, 20, TimeUnit.SECONDS); + } + + public enum CircuitState { + CLOSED, HALF_OPENED, OPENED + } + + public static class CircuitBuilder { + private String url; + private String method; + + public CircuitBuilder url(String url) { + this.url = url; + return this; + } + + public CircuitBuilder method(String method) { + this.method = method; + return this; + } + + public Circuit build() { + return new Circuit(url, method, 0); + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Circuit circuit = (Circuit) o; + + if (!url.equals(circuit.url)) return false; + return method.equals(circuit.method); + } + + @Override + public int hashCode() { + int result = url.hashCode(); + result = 31 * result + method.hashCode(); + return result; + } + + private void halfOpenCircuit() { + if (this.state == CircuitState.CLOSED) { + this.state = CircuitState.HALF_OPENED; + } + } + + public void addFailure() { + this.numberOfFails++; + if(this.state == CircuitState.OPENED && this.numberOfFails > MAX_NUMBER_OF_FAILS){ + this.state = CircuitState.CLOSED; + } + else if(this.state == CircuitState.HALF_OPENED){ + this.state = CircuitState.CLOSED; + } + } + + public boolean isOpen(){ + return this.state == CircuitState.OPENED; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/circuitbreaker/CircuitBreaker.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/circuitbreaker/CircuitBreaker.java new file mode 100644 index 000000000..75f798e36 --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/circuitbreaker/CircuitBreaker.java @@ -0,0 +1,47 @@ +package eu.eudat.logic.utilities.circuitbreaker; + +import eu.eudat.logic.utilities.interfaces.CheckedSupplier; +import org.apache.commons.lang3.StringUtils; +import org.springframework.http.HttpRequest; +import org.springframework.stereotype.Component; +import org.springframework.web.client.RestClientResponseException; + +import java.util.*; +import java.util.function.Consumer; + +/** + * Created by ikalyvas on 2/25/2019. + */ +@Component +public class CircuitBreaker { + private Set circuits = new HashSet<>(); + private Map> resolvers = new HashMap<>(); + + public R handle(HttpRequest request, CheckedSupplier function) throws RestClientResponseException { + Optional circuitOptional = this.circuits.stream() + .filter(circuit -> + circuit.getMethod().equals(request.getMethod().name()) && circuit.getUrl().equals(request.getURI().toString())) + .findFirst(); + if (circuitOptional.isPresent() && circuitOptional.get().isOpen()) { + Consumer resolver = resolvers.get(circuitOptional.get()); + if (resolver != null) { + resolver.accept(request); + return null; + } else throw new RuntimeException("Resolver not found for " + request); + } else { + try { + return function.get(); + } catch (Exception ex) { + if (circuitOptional.isPresent()) circuitOptional.get().addFailure(); + else + circuits.add(new Circuit.CircuitBuilder().method(request.getMethod().name()).url(request.getURI().toString()).build()); + throw new RestClientResponseException(StringUtils.EMPTY, 400, StringUtils.EMPTY, null, null, null); + } + } + } + + public CircuitBreaker addCircuitResolver(Circuit circuit, Consumer requestConsumer) { + this.resolvers.put(circuit, requestConsumer); + return this; + } +} diff --git a/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/interfaces/CheckedSupplier.java b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/interfaces/CheckedSupplier.java new file mode 100644 index 000000000..125e5d58a --- /dev/null +++ b/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/interfaces/CheckedSupplier.java @@ -0,0 +1,8 @@ +package eu.eudat.logic.utilities.interfaces; + +/** + * Created by ikalyvas on 2/25/2019. + */ +public interface CheckedSupplier { + T get() throws Exception; +}