Add exceptions, add validator service
This commit is contained in:
parent
8a7422286d
commit
1bb9a51e73
29 changed files with 844 additions and 121 deletions
|
|
@ -3,7 +3,7 @@ package org.micord.config;
|
||||||
import com.arangodb.ArangoDB;
|
import com.arangodb.ArangoDB;
|
||||||
import com.arangodb.ArangoDBException;
|
import com.arangodb.ArangoDBException;
|
||||||
import com.arangodb.ArangoDatabase;
|
import com.arangodb.ArangoDatabase;
|
||||||
import org.micord.models.AqlConnectionParams;
|
import org.micord.models.requests.AqlConnectionParams;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Maksim Tereshin
|
* @author Maksim Tereshin
|
||||||
|
|
|
||||||
|
|
@ -1,38 +1,29 @@
|
||||||
package org.micord.config;
|
package org.micord.config;
|
||||||
|
|
||||||
import com.atomikos.icatch.jta.UserTransactionImp;
|
|
||||||
import com.atomikos.icatch.jta.UserTransactionManager;
|
import com.atomikos.icatch.jta.UserTransactionManager;
|
||||||
import javax.transaction.TransactionManager;
|
|
||||||
import javax.transaction.UserTransaction;
|
|
||||||
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.transaction.annotation.EnableTransactionManagement;
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
import org.springframework.transaction.jta.JtaTransactionManager;
|
import org.springframework.transaction.jta.JtaTransactionManager;
|
||||||
|
|
||||||
/**
|
|
||||||
* @author Maksim Tereshin
|
|
||||||
*/
|
|
||||||
@Configuration
|
@Configuration
|
||||||
@EnableTransactionManagement
|
@EnableTransactionManagement
|
||||||
public class AtomikosConfig {
|
public class AtomikosConfig {
|
||||||
|
|
||||||
@Bean
|
@Bean(initMethod = "init", destroyMethod = "close")
|
||||||
public UserTransaction userTransaction() throws Throwable {
|
public UserTransactionManager userTransactionManager() {
|
||||||
UserTransactionImp userTransactionImp = new UserTransactionImp();
|
|
||||||
userTransactionImp.setTransactionTimeout(300);
|
|
||||||
return userTransactionImp;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Bean
|
|
||||||
public TransactionManager atomikosTransactionManager() {
|
|
||||||
UserTransactionManager userTransactionManager = new UserTransactionManager();
|
UserTransactionManager userTransactionManager = new UserTransactionManager();
|
||||||
userTransactionManager.setForceShutdown(true);
|
userTransactionManager.setForceShutdown(true);
|
||||||
return userTransactionManager;
|
return userTransactionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Bean
|
@Bean
|
||||||
public JtaTransactionManager transactionManager() throws Throwable {
|
public JtaTransactionManager transactionManager() {
|
||||||
return new JtaTransactionManager(userTransaction(), atomikosTransactionManager());
|
JtaTransactionManager jtaTransactionManager = new JtaTransactionManager();
|
||||||
|
jtaTransactionManager.setTransactionManager(userTransactionManager());
|
||||||
|
jtaTransactionManager.setUserTransaction(userTransactionManager());
|
||||||
|
return jtaTransactionManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package org.micord.config;
|
package org.micord.config;
|
||||||
|
|
||||||
import com.atomikos.jdbc.AtomikosDataSourceBean;
|
import com.atomikos.jdbc.AtomikosDataSourceBean;
|
||||||
import org.micord.models.SqlConnectionParams;
|
import org.micord.models.requests.SqlConnectionParams;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
package org.micord.config;
|
package org.micord.config;
|
||||||
|
|
||||||
import org.micord.models.S3ConnectionParams;
|
import org.micord.models.requests.S3ConnectionParams;
|
||||||
import org.micord.models.S3Request;
|
import org.micord.models.requests.S3Request;
|
||||||
|
|
||||||
import javax.crypto.Mac;
|
import javax.crypto.Mac;
|
||||||
import javax.crypto.spec.SecretKeySpec;
|
import javax.crypto.spec.SecretKeySpec;
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,28 @@
|
||||||
package org.micord.controller;
|
package org.micord.controller;
|
||||||
|
|
||||||
import java.io.File;
|
import org.micord.enums.ConfigType;
|
||||||
import java.io.FileInputStream;
|
import org.micord.exceptions.ValidationException;
|
||||||
import java.io.FileNotFoundException;
|
import org.micord.models.requests.DownloadCSVRequest;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import org.micord.models.DownloadCSVRequest;
|
|
||||||
import org.micord.service.ApiService;
|
import org.micord.service.ApiService;
|
||||||
|
import org.micord.service.ValidationService;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.core.io.InputStreamResource;
|
import org.springframework.core.io.InputStreamResource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.MediaType;
|
import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.ResponseEntity;
|
import org.springframework.http.ResponseEntity;
|
||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* REST Controller for API operations.
|
* REST Controller for API operations.
|
||||||
*/
|
*/
|
||||||
|
|
@ -30,38 +35,91 @@ public class ApiController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ApiService apiService;
|
private ApiService apiService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ValidationService validationService;
|
||||||
|
|
||||||
@PostMapping("/block")
|
@PostMapping("/block")
|
||||||
public ResponseEntity<?> block(@RequestBody List<String> ids) throws FileNotFoundException {
|
public ResponseEntity<?> block(@RequestBody List<String> ids) {
|
||||||
logger.debug("Starting block process for ids: {}", ids);
|
try {
|
||||||
apiService.process("block", ids);
|
validationService.validateAll(ids);
|
||||||
logger.debug("Finished block process for ids: {}", ids);
|
|
||||||
return ResponseEntity.ok("Операция \"Блокировка\" завершена успешно.");
|
logger.debug("Starting block process for ids: {}", ids);
|
||||||
|
apiService.process(ConfigType.BLOCK, ids);
|
||||||
|
logger.debug("Finished block process for ids: {}", ids);
|
||||||
|
return ResponseEntity.ok("Операция \"Блокировка\" завершена успешно.");
|
||||||
|
} catch (ValidationException e) {
|
||||||
|
logger.error("Validation failed for IDs: {}", ids, e);
|
||||||
|
return ResponseEntity.badRequest().body(Map.of(
|
||||||
|
"message", "Validation error occurred",
|
||||||
|
"details", e.getValidationDetails()
|
||||||
|
));
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Unexpected error during processing: {}", e.getMessage(), e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal error occurred.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/unblock")
|
@PostMapping("/unblock")
|
||||||
public ResponseEntity<?> unblock(@RequestBody List<String> ids) throws FileNotFoundException {
|
public ResponseEntity<?> unblock(@RequestBody List<String> ids) {
|
||||||
logger.debug("Starting unblock process for ids: {}", ids);
|
try {
|
||||||
apiService.process("unblock", ids);
|
validationService.validateAll(ids);
|
||||||
logger.debug("Finished unblock process for ids: {}", ids);
|
|
||||||
return ResponseEntity.ok("Операция \"Разблокировка\" завершена успешно.");
|
logger.debug("Starting unblock process for ids: {}", ids);
|
||||||
|
apiService.process(ConfigType.UNBLOCK, ids);
|
||||||
|
logger.debug("Finished unblock process for ids: {}", ids);
|
||||||
|
return ResponseEntity.ok("Операция \"Разблокировка\" завершена успешно.");
|
||||||
|
} catch (ValidationException e) {
|
||||||
|
logger.error("Validation failed for IDs: {}", ids, e);
|
||||||
|
return ResponseEntity.badRequest().body(Map.of(
|
||||||
|
"message", "Validation error occurred",
|
||||||
|
"details", e.getValidationDetails()
|
||||||
|
));
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Unexpected error during processing: {}", e.getMessage(), e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal error occurred.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/removeFromSystem")
|
@PostMapping("/removeFromSystem")
|
||||||
public ResponseEntity<?> removeFromSystem(@RequestBody List<String> ids)
|
public ResponseEntity<?> removeFromSystem(@RequestBody List<String> ids) {
|
||||||
throws FileNotFoundException {
|
try {
|
||||||
logger.debug("Starting removeFromSystem process for ids: {}", ids);
|
validationService.validateAll(ids);
|
||||||
apiService.process("removeFromSystem", ids);
|
|
||||||
logger.debug("Finished removeFromSystem process for ids: {}", ids);
|
logger.debug("Starting removeFromSystem process for ids: {}", ids);
|
||||||
return ResponseEntity.ok("Операция \"Удаление данных по гражданину\" завершена успешно.");
|
apiService.process(ConfigType.REMOVE_FROM_SYSTEM, ids);
|
||||||
|
logger.debug("Finished removeFromSystem process for ids: {}", ids);
|
||||||
|
return ResponseEntity.ok("Операция \"Удаление данных по гражданину\" завершена успешно.");
|
||||||
|
} catch (ValidationException e) {
|
||||||
|
logger.error("Validation failed for IDs: {}", ids, e);
|
||||||
|
return ResponseEntity.badRequest().body(Map.of(
|
||||||
|
"message", "Validation error occurred",
|
||||||
|
"details", e.getValidationDetails()
|
||||||
|
));
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Unexpected error during processing: {}", e.getMessage(), e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal error occurred.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/removeFromCallList")
|
@PostMapping("/removeFromCallList")
|
||||||
public ResponseEntity<?> removeFromCallList(@RequestBody List<String> ids)
|
public ResponseEntity<?> removeFromCallList(@RequestBody List<String> ids) {
|
||||||
throws FileNotFoundException {
|
try {
|
||||||
logger.debug("Starting removeFromCallList process for ids: {}", ids);
|
validationService.validateAll(ids);
|
||||||
apiService.process("removeFromCallList", ids);
|
|
||||||
logger.debug("Finished removeFromCallList process for ids: {}", ids);
|
logger.debug("Starting removeFromCallList process for ids: {}", ids);
|
||||||
return ResponseEntity.ok("Операция \"Удаление из списков на вызов\" завершена успешно.");
|
apiService.process(ConfigType.REMOVE_FROM_CALL_LIST, ids);
|
||||||
|
logger.debug("Finished removeFromCallList process for ids: {}", ids);
|
||||||
|
return ResponseEntity.ok("Операция \"Удаление из списков на вызов\" завершена успешно.");
|
||||||
|
} catch (ValidationException e) {
|
||||||
|
logger.error("Validation failed for IDs: {}", ids, e);
|
||||||
|
return ResponseEntity.badRequest().body(Map.of(
|
||||||
|
"message", "Validation error occurred",
|
||||||
|
"details", e.getValidationDetails()
|
||||||
|
));
|
||||||
|
} catch (Exception e) {
|
||||||
|
logger.error("Unexpected error during processing: {}", e.getMessage(), e);
|
||||||
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Internal error occurred.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/downloadCSV")
|
@PostMapping("/downloadCSV")
|
||||||
|
|
@ -74,7 +132,7 @@ public class ApiController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
File csvFile = apiService.download("downloadCSV", request);
|
File csvFile = apiService.download(ConfigType.DOWNLOAD_CSV, request);
|
||||||
InputStreamResource resource = new InputStreamResource(new FileInputStream(csvFile));
|
InputStreamResource resource = new InputStreamResource(new FileInputStream(csvFile));
|
||||||
|
|
||||||
logger.debug("Finished downloadCSV process for request: {}. Sending to user...", request.getType());
|
logger.debug("Finished downloadCSV process for request: {}. Sending to user...", request.getType());
|
||||||
|
|
@ -89,7 +147,7 @@ public class ApiController {
|
||||||
@GetMapping("/listDownloadTypes")
|
@GetMapping("/listDownloadTypes")
|
||||||
public ResponseEntity<?> listDownloadTypes()
|
public ResponseEntity<?> listDownloadTypes()
|
||||||
throws FileNotFoundException {
|
throws FileNotFoundException {
|
||||||
List<String> downloadCSVTypes = apiService.getDownloadTypes("downloadCSV");
|
List<String> downloadCSVTypes = apiService.getDownloadTypes(ConfigType.DOWNLOAD_CSV);
|
||||||
|
|
||||||
return ResponseEntity.ok(downloadCSVTypes);
|
return ResponseEntity.ok(downloadCSVTypes);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.micord.enums;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public enum ConfigType {
|
||||||
|
|
||||||
|
BLOCK("block"),
|
||||||
|
UNBLOCK("block"),
|
||||||
|
REMOVE_FROM_SYSTEM("removeFromSystem"),
|
||||||
|
REMOVE_FROM_CALL_LIST("removeFromCallList"),
|
||||||
|
DOWNLOAD_CSV("downloadCSV"),
|
||||||
|
VALIDATE_BLOCK("validateBlock");
|
||||||
|
|
||||||
|
private final String type;
|
||||||
|
|
||||||
|
ConfigType(String type) {
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.micord.exceptions;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
public class ValidationException extends RuntimeException {
|
||||||
|
private final Map<String, String> validationDetails;
|
||||||
|
|
||||||
|
public ValidationException(String message, Map<String, String> validationDetails) {
|
||||||
|
super(message);
|
||||||
|
this.validationDetails = validationDetails;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,21 +1,16 @@
|
||||||
package org.micord.models;
|
package org.micord.models;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
import java.nio.file.attribute.FileTime;
|
import java.nio.file.attribute.FileTime;
|
||||||
|
|
||||||
public class CachedConfig {
|
@Getter
|
||||||
private final Requests config;
|
public class CachedConfig<T> {
|
||||||
|
private final T config;
|
||||||
private final FileTime modifiedTime;
|
private final FileTime modifiedTime;
|
||||||
|
|
||||||
public CachedConfig(Requests config, FileTime modifiedTime) {
|
public CachedConfig(T config, FileTime modifiedTime) {
|
||||||
this.config = config;
|
this.config = config;
|
||||||
this.modifiedTime = modifiedTime;
|
this.modifiedTime = modifiedTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Requests getConfig() {
|
|
||||||
return config;
|
|
||||||
}
|
|
||||||
|
|
||||||
public FileTime getModifiedTime() {
|
|
||||||
return modifiedTime;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Maksim Tereshin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
public class AqlConnectionParams {
|
||||||
|
|
||||||
|
private String host;
|
||||||
|
private int port;
|
||||||
|
private String username;
|
||||||
|
private String password;
|
||||||
|
private String database;
|
||||||
|
private String collection;
|
||||||
|
|
||||||
|
@XmlElement(name = "Host")
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "Port")
|
||||||
|
public int getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "Username")
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "Password")
|
||||||
|
public String getPassword() {
|
||||||
|
return password;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "Database")
|
||||||
|
public String getDatabase() {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "Collection")
|
||||||
|
public String getCollection() {
|
||||||
|
return collection;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import jakarta.xml.bind.annotation.XmlElementWrapper;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
public class AqlRequest extends BaseRequest {
|
||||||
|
|
||||||
|
private AqlConnectionParams aqlConnectionParams;
|
||||||
|
private List<AqlRequestCollection> aqlRequestCollections;
|
||||||
|
|
||||||
|
@XmlElement(name = "AqlConnectionParams")
|
||||||
|
public AqlConnectionParams getAqlConnectionParams() {
|
||||||
|
return aqlConnectionParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElementWrapper(name = "AqlRequestCollections")
|
||||||
|
@XmlElement(name = "AqlRequestCollection")
|
||||||
|
public List<AqlRequestCollection> getAqlRequestCollections() {
|
||||||
|
return aqlRequestCollections;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlAttribute;
|
||||||
|
import jakarta.xml.bind.annotation.XmlValue;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
public class AqlRequestCollection {
|
||||||
|
|
||||||
|
private String type;
|
||||||
|
private String collectionUrl;
|
||||||
|
|
||||||
|
@XmlAttribute(name = "type")
|
||||||
|
public String getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlValue
|
||||||
|
public String getCollectionUrl() {
|
||||||
|
return collectionUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import jakarta.xml.bind.annotation.XmlSeeAlso;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Maksim Tereshin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@XmlSeeAlso({SqlRequest.class, S3Request.class, AqlRequest.class})
|
||||||
|
public abstract class BaseRequest {
|
||||||
|
|
||||||
|
private List<RequestArgument> requestArguments;
|
||||||
|
private String requestURL;
|
||||||
|
|
||||||
|
@XmlElement(name = "RequestArgument")
|
||||||
|
public List<RequestArgument> getRequestArguments() {
|
||||||
|
return requestArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "RequestURL")
|
||||||
|
public String getRequestURL() {
|
||||||
|
return requestURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
import java.time.LocalDate;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class DownloadCSVRequest {
|
||||||
|
private String type;
|
||||||
|
private List<String> ids;
|
||||||
|
private LocalDate startDate;
|
||||||
|
private LocalDate endDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
public class DownloadRequest extends BaseRequest {
|
||||||
|
|
||||||
|
private SqlConnectionParams sqlConnectionParams;
|
||||||
|
private String downloadRequestType;
|
||||||
|
|
||||||
|
@XmlElement(name = "SqlConnectionParams")
|
||||||
|
public SqlConnectionParams getSqlConnectionParams() {
|
||||||
|
return sqlConnectionParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "DownloadRequestType")
|
||||||
|
public String getDownloadRequestType() {
|
||||||
|
return downloadRequestType;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import jakarta.xml.bind.annotation.XmlSeeAlso;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Maksim Tereshin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@XmlSeeAlso({SqlRequest.class, S3Request.class})
|
||||||
|
public abstract class Request {
|
||||||
|
|
||||||
|
private List<RequestArgument> requestArguments;
|
||||||
|
private String requestURL;
|
||||||
|
|
||||||
|
@XmlElement(name = "RequestArgument")
|
||||||
|
public List<RequestArgument> getRequestArguments() {
|
||||||
|
return requestArguments;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "RequestURL")
|
||||||
|
public String getRequestURL() {
|
||||||
|
return requestURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlAttribute;
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.micord.enums.RequestArgumentType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Maksim Tereshin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@XmlRootElement(name = "RequestArgument")
|
||||||
|
public class RequestArgument {
|
||||||
|
|
||||||
|
private RequestArgumentType type;
|
||||||
|
private String requestArgumentName;;
|
||||||
|
private String requestArgumentURL;
|
||||||
|
private SqlConnectionParams requestArgumentConnectionParams;
|
||||||
|
|
||||||
|
@XmlAttribute(name = "type")
|
||||||
|
public RequestArgumentType getType() {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "RequestArgumentName")
|
||||||
|
public String getRequestArgumentName() {
|
||||||
|
return requestArgumentName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "RequestArgumentURL")
|
||||||
|
public String getRequestArgumentURL() {
|
||||||
|
return requestArgumentURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "RequestArgumentConnectionParams")
|
||||||
|
public SqlConnectionParams getRequestArgumentConnectionParams() {
|
||||||
|
return requestArgumentConnectionParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Maksim Tereshin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
@XmlRootElement(name = "Requests")
|
||||||
|
public class Requests {
|
||||||
|
|
||||||
|
private List<SqlRequest> sqlRequests;
|
||||||
|
private List<AqlRequest> aqlRequests;
|
||||||
|
private List<S3Request> s3Requests;
|
||||||
|
private List<DownloadRequest> downloadRequests;
|
||||||
|
|
||||||
|
@XmlElement(name = "DownloadRequest")
|
||||||
|
public List<DownloadRequest> getDownloadRequests() {
|
||||||
|
return downloadRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "SqlRequest")
|
||||||
|
public List<SqlRequest> getSqlRequests() {
|
||||||
|
return sqlRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "AqlRequest")
|
||||||
|
public List<AqlRequest> getAqlRequests() {
|
||||||
|
return aqlRequests;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "S3Request")
|
||||||
|
public List<S3Request> getS3Requests() {
|
||||||
|
return s3Requests;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Maksim Tereshin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
public class S3ConnectionParams {
|
||||||
|
|
||||||
|
private String s3Key;
|
||||||
|
private String s3Secret;
|
||||||
|
private String host;
|
||||||
|
private String port;
|
||||||
|
private String contentType;
|
||||||
|
private String method;
|
||||||
|
private String body;
|
||||||
|
|
||||||
|
@XmlElement(name = "S3Key")
|
||||||
|
public String getS3Key() {
|
||||||
|
return s3Key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "S3Secret")
|
||||||
|
public String getS3Secret() {
|
||||||
|
return s3Secret;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "Host")
|
||||||
|
public String getHost() {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "Port")
|
||||||
|
public String getPort() {
|
||||||
|
return port;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "ContentType")
|
||||||
|
public String getContentType() {
|
||||||
|
return contentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "Method")
|
||||||
|
public String getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "Body")
|
||||||
|
public String getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Maksim Tereshin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
public class S3Request extends BaseRequest {
|
||||||
|
|
||||||
|
private S3ConnectionParams s3ConnectionParams;
|
||||||
|
|
||||||
|
@XmlElement(name = "S3ConnectionParams")
|
||||||
|
public S3ConnectionParams getS3ConnectionParams() {
|
||||||
|
return s3ConnectionParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
public class SqlConnectionParams {
|
||||||
|
|
||||||
|
private String jdbcHost;
|
||||||
|
private String jdbcPort;
|
||||||
|
private String jdbcUsername;
|
||||||
|
private String jdbcPassword;
|
||||||
|
private String jdbcDriverClassName;
|
||||||
|
private String jdbcXaDataSourceClassName;
|
||||||
|
private String jdbcXaDataSourcePoolSize;
|
||||||
|
private String jdbcDatabase;
|
||||||
|
private String jdbcXaDataSourceBorrowConnectionTimeout;
|
||||||
|
|
||||||
|
|
||||||
|
@XmlElement(name = "JdbcXaDataSourceBorrowConnectionTimeout")
|
||||||
|
public String getJdbcXaDataSourceBorrowConnectionTimeout() {
|
||||||
|
return jdbcXaDataSourceBorrowConnectionTimeout;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "JdbcXaDataSourcePoolSize")
|
||||||
|
public String getJdbcXaDataSourcePoolSize() {
|
||||||
|
return jdbcXaDataSourcePoolSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "JdbcHost")
|
||||||
|
public String getJdbcHost() {
|
||||||
|
return jdbcHost;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "JdbcPort")
|
||||||
|
public String getJdbcPort() {
|
||||||
|
return jdbcPort;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "JdbcUsername")
|
||||||
|
public String getJdbcUsername() {
|
||||||
|
return jdbcUsername;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "JdbcPassword")
|
||||||
|
public String getJdbcPassword() {
|
||||||
|
return jdbcPassword;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "JdbcDriverClassName")
|
||||||
|
public String getJdbcDriverClassName() {
|
||||||
|
return jdbcDriverClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "JdbcXaDataSourceClassName")
|
||||||
|
public String getJdbcXaDataSourceClassName() {
|
||||||
|
return jdbcXaDataSourceClassName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "JdbcDatabase")
|
||||||
|
public String getJdbcDatabase() {
|
||||||
|
return jdbcDatabase;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
package org.micord.models.requests;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Maksim Tereshin
|
||||||
|
*/
|
||||||
|
@Setter
|
||||||
|
public class SqlRequest extends BaseRequest {
|
||||||
|
|
||||||
|
private SqlConnectionParams sqlConnectionParams;
|
||||||
|
|
||||||
|
@XmlElement(name = "SqlConnectionParams")
|
||||||
|
public SqlConnectionParams getSqlConnectionParams() {
|
||||||
|
return sqlConnectionParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package org.micord.models.validations;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlAttribute;
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import lombok.Setter;
|
||||||
|
import org.micord.models.requests.SqlConnectionParams;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
public class ValidationRule {
|
||||||
|
|
||||||
|
private SqlConnectionParams sqlConnectionParams;
|
||||||
|
private String requestURL;
|
||||||
|
private String idColumn;
|
||||||
|
private List<String> validationColumns;
|
||||||
|
|
||||||
|
@XmlElement(name = "RequestURL")
|
||||||
|
public String getRequestURL() {
|
||||||
|
return requestURL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlElement(name = "SqlConnectionParams")
|
||||||
|
public SqlConnectionParams getSqlConnectionParams() {
|
||||||
|
return sqlConnectionParams;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlAttribute(name = "validationColumns")
|
||||||
|
public List<String> getValidationColumns() {
|
||||||
|
return validationColumns;
|
||||||
|
}
|
||||||
|
|
||||||
|
@XmlAttribute(name = "idColumn")
|
||||||
|
public String getIdColumn() {
|
||||||
|
return idColumn;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package org.micord.models.validations;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.annotation.XmlElement;
|
||||||
|
import jakarta.xml.bind.annotation.XmlRootElement;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
|
||||||
|
@Setter
|
||||||
|
@XmlRootElement(name = "ValidationRules")
|
||||||
|
public class ValidationRules {
|
||||||
|
|
||||||
|
private List<ValidationRule> validationRules;
|
||||||
|
|
||||||
|
@XmlElement(name = "ValidationRule")
|
||||||
|
public List<ValidationRule> getValidationRules() {
|
||||||
|
return validationRules;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,7 +1,9 @@
|
||||||
package org.micord.service;
|
package org.micord.service;
|
||||||
|
|
||||||
import org.micord.models.*;
|
import org.micord.enums.ConfigType;
|
||||||
import org.micord.utils.ConfigLoader;
|
import org.micord.models.requests.DownloadCSVRequest;
|
||||||
|
import org.micord.models.requests.DownloadRequest;
|
||||||
|
import org.micord.models.requests.Requests;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
@ -10,7 +12,8 @@ import org.springframework.stereotype.Service;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.*;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
|
|
@ -18,22 +21,22 @@ public class ApiService {
|
||||||
|
|
||||||
private static final Logger logger = LoggerFactory.getLogger(ApiService.class);
|
private static final Logger logger = LoggerFactory.getLogger(ApiService.class);
|
||||||
|
|
||||||
@Autowired
|
|
||||||
private ConfigLoader configLoader;
|
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private RequestService sqlAndAqlService;
|
private RequestService sqlAndAqlService;
|
||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private DownloadService downloadService;
|
private DownloadService downloadService;
|
||||||
|
|
||||||
public void process(String methodName, List<String> ids) throws FileNotFoundException {
|
@Autowired
|
||||||
Requests config = getConfig(methodName);
|
private ConfigService configService;
|
||||||
|
|
||||||
|
public void process(ConfigType methodName, List<String> ids) throws FileNotFoundException {
|
||||||
|
Requests config = configService.getConfig(methodName, Requests.class);
|
||||||
sqlAndAqlService.processSqlAndAqlRequests(config, ids);
|
sqlAndAqlService.processSqlAndAqlRequests(config, ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
public File download(String methodName, DownloadCSVRequest request) throws IOException {
|
public File download(ConfigType methodName, DownloadCSVRequest request) throws IOException {
|
||||||
Requests config = getConfig(methodName);
|
Requests config = configService.getConfig(methodName, Requests.class);
|
||||||
|
|
||||||
String type = request.getType();
|
String type = request.getType();
|
||||||
List<String> ids = Optional.ofNullable(request.getIds())
|
List<String> ids = Optional.ofNullable(request.getIds())
|
||||||
|
|
@ -48,22 +51,12 @@ public class ApiService {
|
||||||
return downloadService.download(selectedRequest, ids, request.getStartDate(), request.getEndDate());
|
return downloadService.download(selectedRequest, ids, request.getStartDate(), request.getEndDate());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<String> getDownloadTypes(String methodName) throws FileNotFoundException {
|
public List<String> getDownloadTypes(ConfigType methodName) throws FileNotFoundException {
|
||||||
Requests config = getConfig(methodName);
|
Requests config = configService.getConfig(methodName, Requests.class);
|
||||||
|
|
||||||
return config.getDownloadRequests().stream()
|
return config.getDownloadRequests().stream()
|
||||||
.map(DownloadRequest::getDownloadRequestType)
|
.map(DownloadRequest::getDownloadRequestType)
|
||||||
.collect(Collectors.toList());
|
.collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
private Requests getConfig(String methodName) throws FileNotFoundException {
|
|
||||||
logger.debug("Loading configuration for method: {}", methodName);
|
|
||||||
Optional<Requests> optionalConfig = configLoader.loadConfigIfModified(methodName);
|
|
||||||
|
|
||||||
if (optionalConfig.isEmpty()) {
|
|
||||||
throw new FileNotFoundException("Configuration for method " + methodName + " could not be loaded.");
|
|
||||||
}
|
|
||||||
|
|
||||||
return optionalConfig.get();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
package org.micord.service;
|
||||||
|
|
||||||
|
|
||||||
|
import org.micord.enums.ConfigType;
|
||||||
|
import org.micord.utils.ConfigLoader;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ConfigService {
|
||||||
|
|
||||||
|
private static final Logger logger = LoggerFactory.getLogger(ConfigService.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigLoader configLoader;
|
||||||
|
|
||||||
|
public <T> T getConfig(ConfigType methodName, Class<T> configClass) throws FileNotFoundException {
|
||||||
|
logger.debug("Loading configuration for method: {}", methodName);
|
||||||
|
Optional<T> optionalConfig = configLoader.loadConfigIfModified(methodName, configClass);
|
||||||
|
|
||||||
|
if (optionalConfig.isEmpty()) {
|
||||||
|
throw new FileNotFoundException("Configuration for method " + methodName + " could not be loaded.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return optionalConfig.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
package org.micord.service;
|
package org.micord.service;
|
||||||
|
|
||||||
import org.micord.config.DatabaseConnection;
|
import org.micord.config.DatabaseConnection;
|
||||||
import org.micord.models.DownloadRequest;
|
import org.micord.models.requests.DownloadRequest;
|
||||||
import org.micord.models.RequestArgument;
|
import org.micord.models.requests.RequestArgument;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,22 @@
|
||||||
package org.micord.service;
|
package org.micord.service;
|
||||||
|
|
||||||
|
import com.arangodb.ArangoCursor;
|
||||||
|
import com.arangodb.ArangoDBException;
|
||||||
|
import com.arangodb.ArangoDatabase;
|
||||||
|
import com.arangodb.entity.StreamTransactionEntity;
|
||||||
|
import com.arangodb.model.AqlQueryOptions;
|
||||||
|
import com.arangodb.model.StreamTransactionOptions;
|
||||||
|
import org.micord.config.ArangoDBConnection;
|
||||||
|
import org.micord.config.DatabaseConnection;
|
||||||
|
import org.micord.config.S3HttpConnection;
|
||||||
|
import org.micord.enums.RequestArgumentType;
|
||||||
|
import org.micord.models.requests.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.http.HttpClient;
|
import java.net.http.HttpClient;
|
||||||
import java.net.http.HttpRequest;
|
import java.net.http.HttpRequest;
|
||||||
|
|
@ -12,23 +29,6 @@ import java.util.*;
|
||||||
import java.util.concurrent.CompletableFuture;
|
import java.util.concurrent.CompletableFuture;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import com.arangodb.ArangoCursor;
|
|
||||||
import com.arangodb.ArangoDBException;
|
|
||||||
import com.arangodb.ArangoDatabase;
|
|
||||||
import com.arangodb.entity.StreamTransactionEntity;
|
|
||||||
import com.arangodb.model.AqlQueryOptions;
|
|
||||||
import com.arangodb.model.StreamTransactionOptions;
|
|
||||||
import org.micord.config.ArangoDBConnection;
|
|
||||||
import org.micord.config.DatabaseConnection;
|
|
||||||
import org.micord.config.S3HttpConnection;
|
|
||||||
import org.micord.enums.RequestArgumentType;
|
|
||||||
import org.micord.models.*;
|
|
||||||
import org.slf4j.Logger;
|
|
||||||
import org.slf4j.LoggerFactory;
|
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
|
||||||
import org.springframework.stereotype.Service;
|
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Maksim Tereshin
|
* @author Maksim Tereshin
|
||||||
*/
|
*/
|
||||||
|
|
@ -44,16 +44,20 @@ public class RequestService {
|
||||||
logger.debug("Starting processing of S3 requests");
|
logger.debug("Starting processing of S3 requests");
|
||||||
if (s3Requests != null && !s3Requests.isEmpty()) {
|
if (s3Requests != null && !s3Requests.isEmpty()) {
|
||||||
List<CompletableFuture<Void>> requestFutures = s3Requests.stream()
|
List<CompletableFuture<Void>> requestFutures = s3Requests.stream()
|
||||||
.map(request -> CompletableFuture.runAsync(() -> processS3Request(request, ids)))
|
.map(request -> CompletableFuture.runAsync(() -> {
|
||||||
|
try {
|
||||||
|
processS3Request(request, ids);
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new RuntimeException("Error processing S3 request: " + request, e);
|
||||||
|
}
|
||||||
|
}))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
CompletableFuture.allOf(requestFutures.toArray(new CompletableFuture[0]))
|
CompletableFuture.allOf(requestFutures.toArray(new CompletableFuture[0]))
|
||||||
.thenRun(() -> logger.info("Successfully processed all S3 requests."))
|
|
||||||
.whenComplete((result, ex) -> {
|
.whenComplete((result, ex) -> {
|
||||||
if (ex != null) {
|
if (ex != null) {
|
||||||
logger.error("Error processing S3 requests", ex);
|
logger.error("Error processing S3 requests", ex);
|
||||||
} else {
|
throw new RuntimeException("Error processing S3 requests", ex);
|
||||||
logger.info("Successfully processed all S3 requests.");
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -81,10 +85,16 @@ public class RequestService {
|
||||||
}
|
}
|
||||||
catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
logger.error("Failed to execute query for RequestArgument", e);
|
logger.error("Failed to execute query for RequestArgument", e);
|
||||||
|
throw new RuntimeException("Error executing database query: " + argument.getRequestArgumentURL(), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (files.isEmpty()) {
|
||||||
|
logger.warn("No files found for S3 request");
|
||||||
|
throw new RuntimeException("No files found for S3 request");
|
||||||
|
}
|
||||||
|
|
||||||
files.forEach(file -> {
|
files.forEach(file -> {
|
||||||
HttpRequest httpRequest;
|
HttpRequest httpRequest;
|
||||||
logger.debug("Starting building HTTP request for S3 request");
|
logger.debug("Starting building HTTP request for S3 request");
|
||||||
|
|
@ -92,7 +102,7 @@ public class RequestService {
|
||||||
|
|
||||||
if (file == null || file.isBlank()) {
|
if (file == null || file.isBlank()) {
|
||||||
logger.warn("Skipping invalid file path: {}", file);
|
logger.warn("Skipping invalid file path: {}", file);
|
||||||
return;
|
throw new RuntimeException("Invalid file path");
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
httpRequest = S3HttpConnection.buildHttpRequest(request, file);
|
httpRequest = S3HttpConnection.buildHttpRequest(request, file);
|
||||||
|
|
@ -167,6 +177,7 @@ public class RequestService {
|
||||||
}
|
}
|
||||||
catch (SQLException e) {
|
catch (SQLException e) {
|
||||||
logger.error("SQL execution failed for query: {}", query, e);
|
logger.error("SQL execution failed for query: {}", query, e);
|
||||||
|
throw new RuntimeException("Error executing SQL query", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,101 @@
|
||||||
|
package org.micord.service;
|
||||||
|
|
||||||
|
import org.micord.config.DatabaseConnection;
|
||||||
|
import org.micord.enums.ConfigType;
|
||||||
|
import org.micord.exceptions.ValidationException;
|
||||||
|
import org.micord.models.validations.ValidationRule;
|
||||||
|
import org.micord.models.validations.ValidationRules;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.sql.Connection;
|
||||||
|
import java.sql.PreparedStatement;
|
||||||
|
import java.sql.ResultSet;
|
||||||
|
import java.sql.SQLException;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.UUID;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ValidationService {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ConfigService configService;
|
||||||
|
|
||||||
|
public Map<String, Map<String, Object>> validate(List<String> ids, ValidationRule rule) throws SQLException {
|
||||||
|
|
||||||
|
String query = rule.getRequestURL();
|
||||||
|
if (!query.contains("${endpointArguments}")) {
|
||||||
|
throw new IllegalArgumentException("The query must contain the placeholder '${endpointArguments}' for ID replacement.");
|
||||||
|
}
|
||||||
|
|
||||||
|
String finalQuery = query.replace("${endpointArguments}", "(" + ids.stream().map(id -> "?").collect(Collectors.joining(", ")) + ")");
|
||||||
|
|
||||||
|
try (Connection connection = DatabaseConnection.getConnection(
|
||||||
|
rule.getSqlConnectionParams());
|
||||||
|
PreparedStatement preparedStatement = connection.prepareStatement(finalQuery)) {
|
||||||
|
|
||||||
|
for (int i = 0; i < ids.size(); i++) {
|
||||||
|
preparedStatement.setObject(i + 1, UUID.fromString(ids.get(i)));
|
||||||
|
}
|
||||||
|
|
||||||
|
try (ResultSet resultSet = preparedStatement.executeQuery()) {
|
||||||
|
Map<String, Map<String, Object>> validationResults = new HashMap<>();
|
||||||
|
|
||||||
|
while (resultSet.next()) {
|
||||||
|
String id = resultSet.getString(rule.getIdColumn());
|
||||||
|
Map<String, Object> columnValues = new HashMap<>();
|
||||||
|
|
||||||
|
for (String column : rule.getValidationColumns()) {
|
||||||
|
Object value = resultSet.getObject(column);
|
||||||
|
columnValues.put(column, value);
|
||||||
|
}
|
||||||
|
validationResults.put(id, columnValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
return validationResults;
|
||||||
|
} catch (SQLException e) {
|
||||||
|
throw new SQLException("Failed to execute query for ValidationRule", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Map<String, String> validateAll(List<String> ids) throws ValidationException, FileNotFoundException, SQLException {
|
||||||
|
ValidationRules config = configService.getConfig(ConfigType.VALIDATE_BLOCK, ValidationRules.class);
|
||||||
|
|
||||||
|
if (config.getValidationRules() == null || config.getValidationRules().isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, Map<String, Object>> validationResults = new HashMap<>();
|
||||||
|
|
||||||
|
for (ValidationRule rule : config.getValidationRules()) {
|
||||||
|
validationResults.putAll(validate(ids, rule));
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, String> invalidRecords = new HashMap<>();
|
||||||
|
|
||||||
|
validationResults.forEach((id, columnValues) -> {
|
||||||
|
List<String> invalidColumns = columnValues.entrySet().stream()
|
||||||
|
.filter(entry -> Boolean.FALSE.equals(entry.getValue()))
|
||||||
|
.map(Map.Entry::getKey)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
|
||||||
|
if (!invalidColumns.isEmpty()) {
|
||||||
|
String message = "Запись с UUID = " + id + " не прошла проверку по следующим колонкам: " + String.join(", ", invalidColumns);
|
||||||
|
invalidRecords.put(id, message);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!invalidRecords.isEmpty()) {
|
||||||
|
throw new ValidationException("Validation failed for some records", invalidRecords);
|
||||||
|
}
|
||||||
|
|
||||||
|
return invalidRecords;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,13 @@
|
||||||
package org.micord.utils;
|
package org.micord.utils;
|
||||||
|
|
||||||
|
import jakarta.xml.bind.JAXBContext;
|
||||||
|
import jakarta.xml.bind.JAXBException;
|
||||||
|
import jakarta.xml.bind.Unmarshaller;
|
||||||
|
import org.micord.enums.ConfigType;
|
||||||
|
import org.micord.models.CachedConfig;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
|
|
@ -10,14 +18,6 @@ import java.util.Optional;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
import jakarta.xml.bind.JAXBContext;
|
|
||||||
import jakarta.xml.bind.JAXBException;
|
|
||||||
import jakarta.xml.bind.Unmarshaller;
|
|
||||||
|
|
||||||
import org.micord.models.CachedConfig;
|
|
||||||
import org.micord.models.Requests;
|
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
|
||||||
import org.springframework.stereotype.Component;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Maksim Tereshin
|
* @author Maksim Tereshin
|
||||||
|
|
@ -31,7 +31,9 @@ public class ConfigLoader {
|
||||||
@Value("${configDirectory}")
|
@Value("${configDirectory}")
|
||||||
private String configDirectory;
|
private String configDirectory;
|
||||||
|
|
||||||
public Optional<Requests> loadConfigIfModified(String methodName) {
|
|
||||||
|
public <T> Optional<T> loadConfigIfModified(ConfigType configType, Class<T> configClass) {
|
||||||
|
String methodName = configType.getType();
|
||||||
String fileName = methodName + ".xml";
|
String fileName = methodName + ".xml";
|
||||||
|
|
||||||
if (configDirectory == null) {
|
if (configDirectory == null) {
|
||||||
|
|
@ -47,14 +49,14 @@ public class ConfigLoader {
|
||||||
|
|
||||||
if (cachedConfig == null || !currentModifiedTime.equals(cachedConfig.getModifiedTime())) {
|
if (cachedConfig == null || !currentModifiedTime.equals(cachedConfig.getModifiedTime())) {
|
||||||
// Load the updated configuration
|
// Load the updated configuration
|
||||||
JAXBContext jaxbContext = JAXBContext.newInstance(Requests.class);
|
JAXBContext jaxbContext = JAXBContext.newInstance(configClass);
|
||||||
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
||||||
Requests loadedConfig = (Requests) unmarshaller.unmarshal(configFile);
|
T loadedConfig = unmarshalConfig(configFile, configClass);
|
||||||
cachedConfigs.put(methodName, new CachedConfig(loadedConfig, currentModifiedTime));
|
cachedConfigs.put(methodName, new CachedConfig(loadedConfig, currentModifiedTime));
|
||||||
return Optional.of(loadedConfig);
|
return Optional.of(loadedConfig);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return Optional.of(cachedConfigs.get(methodName).getConfig());
|
return (Optional<T>) Optional.of(cachedConfigs.get(methodName).getConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -67,4 +69,10 @@ public class ConfigLoader {
|
||||||
return Optional.empty(); // Return empty if unmarshalling fails
|
return Optional.empty(); // Return empty if unmarshalling fails
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private <T> T unmarshalConfig(File configFile, Class<T> configClass) throws JAXBException {
|
||||||
|
JAXBContext jaxbContext = JAXBContext.newInstance(configClass);
|
||||||
|
Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
|
||||||
|
return configClass.cast(unmarshaller.unmarshal(configFile));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue