This commit is contained in:
parent
0a9af63689
commit
6f6ace106d
29 changed files with 479 additions and 66 deletions
|
|
@ -8,14 +8,13 @@ import java.util.Locale;
|
|||
|
||||
@Configuration
|
||||
public class MessagesConfig {
|
||||
@Bean
|
||||
@Bean("validation-error-messages")
|
||||
public ResourceBundleMessageSource messages() {
|
||||
ResourceBundleMessageSource source = new ResourceBundleMessageSource();
|
||||
source.setBasenames("messages/response");
|
||||
source.setBasenames("messages/error");
|
||||
source.setUseCodeAsDefaultMessage(true);
|
||||
source.setDefaultEncoding("utf8");
|
||||
source.setDefaultLocale(Locale.ROOT);
|
||||
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,95 +1,88 @@
|
|||
package ru.spcex.clearing.backendapi.controller.cud;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import io.swagger.annotations.*;
|
||||
import org.apache.kafka.clients.producer.Producer;
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||
import io.swagger.annotations.ApiOperation;
|
||||
import io.swagger.annotations.ApiParam;
|
||||
import io.swagger.annotations.ApiResponse;
|
||||
import io.swagger.annotations.ApiResponses;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
|
||||
import ru.spcex.clearing.backendapi.controller.response.cud.CudResponse;
|
||||
import ru.spcex.clearing.backendapi.domain.actions.IAction;
|
||||
import ru.spcex.clearing.backendapi.meta.CudMetaService;
|
||||
import ru.spcex.clearing.backendapi.service.IOperator;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
@Controller
|
||||
@RequestMapping("/cud")
|
||||
public class CudController {
|
||||
private final Producer<String, Object> kafka;
|
||||
private final IOperator operator;
|
||||
private final ObjectMapper json;
|
||||
private final CudMetaService meta;
|
||||
|
||||
@Autowired
|
||||
public CudController(Producer<String, Object> kafka, CudMetaService meta) {
|
||||
this.kafka = kafka;
|
||||
public CudController(IOperator operator, CudMetaService meta) {
|
||||
this.meta = meta;
|
||||
this.json = new ObjectMapper();
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@ApiOperation(value = "create/update/delete business objects. See meta.xml for field descriptions.")
|
||||
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = MetaDataResponse.class)})
|
||||
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
|
||||
@RequestMapping(value = "/{destination}", method = RequestMethod.POST)
|
||||
@ResponseBody
|
||||
public MetaDataResponse add(
|
||||
public CudResponse add(
|
||||
@ApiParam(value = "Последняя часть URL определяет 'направление', по которому пойдет запрос. " +
|
||||
"Должно биться с форматом запроса.", required = true, example = "money-market-security-new")
|
||||
@PathVariable("destination")
|
||||
String destination,
|
||||
@ApiParam(value = "Параметры команды в JSON формате, поля см. в meta.xml.", required = true)
|
||||
@RequestBody String body) throws JsonProcessingException, ExecutionException, InterruptedException {
|
||||
return processRequest(destination, body);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "create/update/delete business objects. See meta.xml for field descriptions.")
|
||||
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
|
||||
@RequestMapping(value = "/{destination}", method = RequestMethod.PUT)
|
||||
@ResponseBody
|
||||
public CudResponse update(
|
||||
@ApiParam(value = "Последняя часть URL определяет 'направление', по которому пойдет запрос. " +
|
||||
"Должно биться с форматом запроса.", required = true, example = "money-market-security-new")
|
||||
@PathVariable("destination")
|
||||
String destination,
|
||||
@ApiParam(value = "Параметры команды в JSON формате, поля см. в meta.xml.", required = true)
|
||||
@RequestBody String body) throws JsonProcessingException, ExecutionException, InterruptedException {
|
||||
return processRequest(destination, body);
|
||||
}
|
||||
|
||||
@ApiOperation(value = "delete business objects. See meta.xml for field descriptions.")
|
||||
@ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = CudResponse.class), @ApiResponse(code = 400, message = "Ошибка валидации", response = BasicSpcexResponse.class)})
|
||||
@RequestMapping(value = "/{destination}", method = RequestMethod.DELETE)
|
||||
@ResponseBody
|
||||
public CudResponse delete(
|
||||
@ApiParam(value = "Последняя часть URL определяет 'направление', по которому пойдет запрос. " +
|
||||
"Должно биться с форматом запроса.", required = true, example = "money-market-security-new")
|
||||
@PathVariable("destination")
|
||||
String destination,
|
||||
@ApiParam(value = "Параметры команды в JSON формате, поля см. в meta.xml.", required = true)
|
||||
@RequestBody String body) throws JsonProcessingException, ExecutionException, InterruptedException {
|
||||
return processRequest(destination, body);
|
||||
}
|
||||
|
||||
private CudResponse processRequest(String destination, String body) throws ExecutionException, InterruptedException, JsonProcessingException {
|
||||
Class<IAction<?>> actionClazz = meta.byDestination(destination);
|
||||
if (actionClazz == null) {
|
||||
throw new UnsupportedOperationException("unsupported destination " + destination);
|
||||
}
|
||||
IAction<?> iAction = json.readValue(body, actionClazz);
|
||||
Future<RecordMetadata> send = kafka.send(new ProducerRecord<>(destination, iAction.toRequest()));
|
||||
RecordMetadata kafkaMetaData = send.get();
|
||||
MetaDataResponse responseToClient = new MetaDataResponse();
|
||||
responseToClient.setOffset(kafkaMetaData.offset());
|
||||
responseToClient.setPartition(kafkaMetaData.partition());
|
||||
responseToClient.setTopic(kafkaMetaData.topic());
|
||||
CudResponse responseToClient = new CudResponse();
|
||||
responseToClient.setResponse(operator.sendRequestToQueue(destination, iAction));
|
||||
responseToClient.setCode(0);
|
||||
responseToClient.setMessage("success");
|
||||
return responseToClient;
|
||||
}
|
||||
|
||||
@ApiModel(description="Ответ в результате отправки операции в топик Kafka.")
|
||||
private static class MetaDataResponse extends BasicSpcexResponse {
|
||||
@ApiModelProperty(value="Offset положенного сообщения")
|
||||
@JsonProperty
|
||||
private Long offset;
|
||||
@ApiModelProperty(value="Partition положенного сообщения")
|
||||
@JsonProperty
|
||||
private Integer partition;
|
||||
@ApiModelProperty(value="Название топика, в который было положено сообщение")
|
||||
@JsonProperty
|
||||
private String topic;
|
||||
|
||||
public Long getOffset() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
public void setOffset(Long offset) {
|
||||
this.offset = offset;
|
||||
}
|
||||
|
||||
public Integer getPartition() {
|
||||
return partition;
|
||||
}
|
||||
|
||||
public void setPartition(Integer partition) {
|
||||
this.partition = partition;
|
||||
}
|
||||
|
||||
public String getTopic() {
|
||||
return topic;
|
||||
}
|
||||
|
||||
public void setTopic(String topic) {
|
||||
this.topic = topic;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,43 @@
|
|||
package ru.spcex.clearing.backendapi.controller.cud;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.annotation.Order;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
import org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler;
|
||||
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
|
||||
import ru.spcex.clearing.backendapi.errors.ActionValidationException;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
|
||||
@ControllerAdvice("ru.spcex.clearing.backendapi.controller.cud")
|
||||
@Order(Ordered.HIGHEST_PRECEDENCE)
|
||||
public class CudExceptionHandler extends ResponseEntityExceptionHandler {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final IMessageResolver errorResolver;
|
||||
|
||||
@Autowired
|
||||
public CudExceptionHandler(@Qualifier("errorResolver") IMessageResolver errorResolver) {
|
||||
this.errorResolver = errorResolver;
|
||||
}
|
||||
|
||||
@ExceptionHandler(value = ActionValidationException.class)
|
||||
@ResponseStatus(HttpStatus.BAD_REQUEST)
|
||||
@ResponseBody
|
||||
public BasicSpcexResponse handleValidationException(ActionValidationException e) {
|
||||
log.error("Default scoring exception handler: {}", ExceptionUtils.getStackTrace(e));
|
||||
EnumMessage firstError = e.getErrors().iterator().next();
|
||||
BasicSpcexResponse errorResponse = new BasicSpcexResponse();
|
||||
errorResponse.setCode(firstError.getSubject().getId());
|
||||
errorResponse.setMessage(errorResolver.resolve(firstError));
|
||||
return errorResponse;
|
||||
}
|
||||
}
|
||||
|
|
@ -4,10 +4,15 @@ import com.fasterxml.jackson.annotation.JsonFormat;
|
|||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import ru.spcex.clearing.backendapi.domain.actions.IAction;
|
||||
import ru.spcex.clearing.backendapi.errors.BackEndError;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.securitites.MoneyMarketSecurityNewRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.json.deserialize.InstantDeserializer;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
public class MoneyMarketSecurityNewAction implements IAction<MoneyMarketSecurityNewRequest> {
|
||||
@JsonFormat(pattern = "yyyy-MM-dd", timezone = "Europe/Moscow")
|
||||
|
|
@ -31,6 +36,13 @@ public class MoneyMarketSecurityNewAction implements IAction<MoneyMarketSecurity
|
|||
@JsonProperty
|
||||
public Double lotSize;
|
||||
|
||||
@Override
|
||||
public Collection<EnumMessage> validate() {
|
||||
if (this.startDate == null)
|
||||
return List.of(new EnumMessage(BackEndError.ValidationError, "startDate"));
|
||||
else return Collections.emptyList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoneyMarketSecurityNewRequest toRequest() {
|
||||
var req = new MoneyMarketSecurityNewRequest();
|
||||
|
|
|
|||
|
|
@ -6,15 +6,15 @@ import io.swagger.annotations.ApiModelProperty;
|
|||
@ApiModel(description="Базовый формат ответа")
|
||||
public class BasicSpcexResponse {
|
||||
@ApiModelProperty(value="Код ответа (успешный 0)", required = true)
|
||||
private int code;
|
||||
private long code;
|
||||
@ApiModelProperty(value="Сообщение ответа")
|
||||
private String message;
|
||||
|
||||
public int getCode() {
|
||||
public long getCode() {
|
||||
return code;
|
||||
}
|
||||
|
||||
public void setCode(int code) {
|
||||
public void setCode(long code) {
|
||||
this.code = code;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
package ru.spcex.clearing.backendapi.controller.response.cud;
|
||||
|
||||
import io.swagger.annotations.ApiModel;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import ru.spcex.clearing.backendapi.controller.response.BasicSpcexResponse;
|
||||
|
||||
@ApiModel(description = "Ответ в результате отправки операции в топик Kafka.")
|
||||
public class CudResponse extends BasicSpcexResponse {
|
||||
@ApiModelProperty(value = "Информация о принятом запросе")
|
||||
QueueSuccessResponse response;
|
||||
|
||||
public QueueSuccessResponse getResponse() {
|
||||
return response;
|
||||
}
|
||||
|
||||
public void setResponse(QueueSuccessResponse response) {
|
||||
this.response = response;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
package ru.spcex.clearing.backendapi.controller.response.cud;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import io.swagger.annotations.ApiModelProperty;
|
||||
import ru.spcex.clearing.platform.messaging.domain.ActionType;
|
||||
|
||||
public class QueueSuccessResponse {
|
||||
@ApiModelProperty(value = "Тип запроса")
|
||||
@JsonProperty
|
||||
private final ActionType action;
|
||||
@ApiModelProperty(value = "Идентификатор запроса")
|
||||
@JsonProperty
|
||||
private final Long id;
|
||||
|
||||
public QueueSuccessResponse(ActionType action, Long id) {
|
||||
this.action = action;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public ActionType getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,5 +1,12 @@
|
|||
package ru.spcex.clearing.backendapi.domain.actions;
|
||||
|
||||
public interface IAction<T> {
|
||||
public T toRequest();
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
||||
public interface IAction<T extends BaseRequest> {
|
||||
T toRequest();
|
||||
default Collection<EnumMessage> validate() {return Collections.emptyList();}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
package ru.spcex.clearing.backendapi.errors;
|
||||
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public class ActionValidationException extends RuntimeException {
|
||||
protected Collection<EnumMessage> errors;
|
||||
|
||||
public ActionValidationException(Collection<EnumMessage> errors) {
|
||||
this.errors = errors;
|
||||
}
|
||||
|
||||
public ActionValidationException(EnumMessage error) {
|
||||
this.errors = List.of(error);
|
||||
}
|
||||
|
||||
public Collection<EnumMessage> getErrors() {
|
||||
return errors;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
package ru.spcex.clearing.backendapi.errors;
|
||||
|
||||
import ru.spcex.platform.utils.enumeration.IEnumId;
|
||||
|
||||
public enum BackEndError implements IEnumId {
|
||||
ValidationError(3000L);
|
||||
private final Long id;
|
||||
|
||||
BackEndError(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
package ru.spcex.clearing.backendapi.errors;
|
||||
|
||||
import org.springframework.context.support.ResourceBundleMessageSource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
||||
|
||||
import java.util.Locale;
|
||||
|
||||
@Service("errorResolver")
|
||||
public class ErrorResolver implements IMessageResolver {
|
||||
private final ResourceBundleMessageSource errorMessages;
|
||||
|
||||
public ErrorResolver(ResourceBundleMessageSource errorMessages) {
|
||||
this.errorMessages = errorMessages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String resolve(EnumMessage errorMessage) {
|
||||
Long id = errorMessage.getSubject().getId();
|
||||
String messageTemplate = errorMessages.getMessage(id.toString(), null, Locale.ENGLISH);
|
||||
if (errorMessage.getArgs().length > 0)
|
||||
return String.format(messageTemplate, errorMessage.getArgs());
|
||||
else {
|
||||
return messageTemplate;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
package ru.spcex.clearing.backendapi.service;
|
||||
|
||||
import ru.spcex.clearing.backendapi.controller.response.cud.QueueSuccessResponse;
|
||||
import ru.spcex.clearing.backendapi.domain.actions.IAction;
|
||||
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
public interface IOperator {
|
||||
QueueSuccessResponse sendRequestToQueue(String destination, IAction<?> iAction) throws ExecutionException, InterruptedException;
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
package ru.spcex.clearing.backendapi.service.impl;
|
||||
|
||||
import org.apache.kafka.clients.producer.Producer;
|
||||
import org.apache.kafka.clients.producer.ProducerRecord;
|
||||
import org.apache.kafka.clients.producer.RecordMetadata;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.spcex.clearing.backendapi.controller.response.cud.QueueSuccessResponse;
|
||||
import ru.spcex.clearing.backendapi.domain.actions.IAction;
|
||||
import ru.spcex.clearing.backendapi.errors.ActionValidationException;
|
||||
import ru.spcex.clearing.backendapi.service.IOperator;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.platform.imdg.api.ImdgId;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.utils.enumeration.EnumMessage;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
@Service
|
||||
public class OperatorImpl implements IOperator {
|
||||
private final Producer<String, Object> kafka;
|
||||
private final ImdgId idGenerator;
|
||||
|
||||
public OperatorImpl(Producer<String, Object> kafka, ImdgProvider imdgProvider) {
|
||||
this.kafka = kafka;
|
||||
this.idGenerator = imdgProvider.getImdgIdGenerator();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QueueSuccessResponse sendRequestToQueue(String destination, IAction<?> iAction) throws ExecutionException, InterruptedException {
|
||||
throwValidate(iAction);
|
||||
BaseRequest request = iAction.toRequest();
|
||||
request.setId(idGenerator.nextId());
|
||||
Future<RecordMetadata> send = kafka.send(new ProducerRecord<>(destination, request));
|
||||
send.get();
|
||||
return new QueueSuccessResponse(request.getActionType(), request.getId());
|
||||
}
|
||||
|
||||
private void throwValidate(IAction<?> iAction) {
|
||||
Collection<EnumMessage> validationErrors = iAction.validate();
|
||||
if (validationErrors.size() > 0) {
|
||||
throw new ActionValidationException(validationErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
1=This is error example 1.
|
||||
3000=Validation error field: %s
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
1=Пример ошибки с идентификатором 1.
|
||||
3000=Ошибка валидации, поле: %s
|
||||
|
|
@ -1 +0,0 @@
|
|||
backend-api.response.test1=This is response example 1.
|
||||
|
|
@ -1 +0,0 @@
|
|||
backend-api.response.test1=Это пример ответа 1.
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
package ru.spcex.platform.imdg.iml.hazelcast.adapter;
|
||||
|
||||
import com.hazelcast.core.IdGenerator;
|
||||
import ru.spcex.platform.imdg.api.ImdgId;
|
||||
|
||||
public class ImdgIdGeneratorHazelcast implements ImdgId {
|
||||
private IdGenerator idGenerator;
|
||||
|
||||
public IdGenerator getIdGenerator() {
|
||||
return idGenerator;
|
||||
}
|
||||
|
||||
public void setIdGenerator(IdGenerator idGenerator) {
|
||||
this.idGenerator = idGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long nextId() {
|
||||
return idGenerator.newId();
|
||||
}
|
||||
}
|
||||
|
|
@ -12,8 +12,10 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
|
|||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.platform.classes.base.SpcexObjectBase;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgId;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgHazelcast;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.adapter.ImdgIdGeneratorHazelcast;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.config.HazelcastClientParams;
|
||||
import ru.spcex.platform.imdg.iml.hazelcast.util.HazelcastHelper;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
|
|
@ -231,6 +233,23 @@ public abstract class HazelcastServiceBase
|
|||
return imdg;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImdgId getImdgIdGenerator() {
|
||||
ImdgIdGeneratorHazelcast imdgId = new ImdgIdGeneratorHazelcast();
|
||||
statusSubscribe(new IHazelcastClusterStatus() {
|
||||
@Override
|
||||
public void getAvailable(HazelcastInstance hazelcastNotInited) {
|
||||
IdGenerator generator = hazelcastInstance.getIdGenerator(IMDGDistributedNames.MAP_SEQUENCE_NAME);
|
||||
imdgId.setIdGenerator(generator);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getUnavailable(HazelcastInstance hazelcastNotInited) {
|
||||
}
|
||||
});
|
||||
return imdgId;
|
||||
}
|
||||
|
||||
// @Override
|
||||
public void waitTillReadyState() throws InterruptedException {
|
||||
boolean done = false;
|
||||
|
|
|
|||
|
|
@ -0,0 +1,5 @@
|
|||
package ru.spcex.platform.imdg.api;
|
||||
|
||||
public interface ImdgId {
|
||||
Long nextId();
|
||||
}
|
||||
|
|
@ -8,4 +8,6 @@ public interface ImdgProvider {
|
|||
*/
|
||||
public <T extends SpcexObjectBase> Imdg<T> getImdg(String key, Class<T> clazz);
|
||||
|
||||
public ImdgId getImdgIdGenerator();
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,11 @@
|
|||
<artifactId>platform-utils</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ru.spcex.platform</groupId>
|
||||
<artifactId>platform-classes-base</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
</project>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package ru.spcex.clearing.platform.messaging.domain;
|
||||
|
||||
public enum ActionType {
|
||||
NEW
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package ru.spcex.clearing.platform.messaging.domain;
|
||||
|
||||
import ru.spcex.platform.classes.base.interfaces.WithId;
|
||||
|
||||
public interface BaseRequest extends WithId {
|
||||
void setId(Long id);
|
||||
ActionType getActionType();
|
||||
}
|
||||
|
|
@ -3,12 +3,16 @@ package ru.spcex.clearing.platform.messaging.domain.cud.securitites;
|
|||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
|
||||
import ru.spcex.clearing.platform.messaging.domain.ActionType;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.json.deserialize.InstantDeserializer;
|
||||
import ru.spcex.clearing.platform.messaging.domain.json.serialize.InstantSerializer;
|
||||
|
||||
import java.time.Instant;
|
||||
|
||||
public class MoneyMarketSecurityNewRequest {
|
||||
public class MoneyMarketSecurityNewRequest implements BaseRequest {
|
||||
@JsonProperty
|
||||
public Long id;
|
||||
@JsonProperty
|
||||
@JsonSerialize(using = InstantSerializer.class)
|
||||
@JsonDeserialize(using = InstantDeserializer.class)
|
||||
|
|
@ -30,6 +34,21 @@ public class MoneyMarketSecurityNewRequest {
|
|||
@JsonProperty
|
||||
public Double lotSize;
|
||||
|
||||
@Override
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionType getActionType() {
|
||||
return ActionType.NEW;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Instant getStartDate() {
|
||||
return startDate;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
package ru.spcex.platform.utils.enumeration;
|
||||
|
||||
import java.util.Collections;
|
||||
|
||||
public class EnumMessage {
|
||||
private final IEnumId subject;
|
||||
/**
|
||||
* Параметры для подстановки в текст сообщения. Все Serializable.
|
||||
* args not null.
|
||||
*/
|
||||
private Object[] args;
|
||||
|
||||
public EnumMessage(IEnumId subject) {
|
||||
this.subject = subject;
|
||||
this.args = Collections.emptyList().toArray(new Object[0]);
|
||||
}
|
||||
|
||||
|
||||
public EnumMessage(IEnumId subject, Object... args) {
|
||||
this.subject = subject;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
public IEnumId getSubject() {
|
||||
return subject;
|
||||
}
|
||||
|
||||
public Object[] getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
public void setArgs(Object[] args) {
|
||||
this.args = args;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
package ru.spcex.platform.utils.enumeration;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Objects;
|
||||
|
||||
public interface IEnumId extends Serializable {
|
||||
Long getId();
|
||||
|
||||
default boolean equalsById(Long id) {
|
||||
return id != null && getId().equals(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет что среди данного набора Enum, присутствует элемент с данным id
|
||||
* id может быть null
|
||||
*/
|
||||
static <T extends Enum<T> & IEnumId> boolean contains(java.lang.Long id, T... enumSet) {
|
||||
for (T e : enumSet) {
|
||||
if (Objects.equals(id, e.getId()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static <T extends Enum<T> & IEnumId> boolean contains(T e, T... enumSet) {
|
||||
for (T enumEl : enumSet) {
|
||||
if (enumEl.equals(e))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Проверяет что среди всех Enum данного класса, присутствует элемент с данным id
|
||||
* id может быть null
|
||||
*/
|
||||
static <T extends Enum<T> & IEnumId> boolean contains(Class<T> enumClass, Long id) {
|
||||
for (T e : enumClass.getEnumConstants()) {
|
||||
if (Objects.equals(id, e.getId()))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Возвращает Enum по id, если в заданном классе такой определен
|
||||
* id может быть null
|
||||
*
|
||||
* @return Enum если нашел, иначе <tt>null</tt>
|
||||
*/
|
||||
static <T extends Enum<T> & IEnumId> T getEnumById(Class<T> enumClass, Long id) {
|
||||
for (T e : enumClass.getEnumConstants()) {
|
||||
if (Objects.equals(id, e.getId()))
|
||||
return e;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
static Long getIdOrNull(IEnumId enumVal) {
|
||||
return enumVal == null ? null : enumVal.getId();
|
||||
}
|
||||
|
||||
Long UNDEFINED_VALUE = Long.MIN_VALUE;
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package ru.spcex.platform.utils.enumeration;
|
||||
|
||||
public interface IMessageResolver {
|
||||
String resolve(EnumMessage errorMessage);
|
||||
}
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
#!/bin/sh
|
||||
docker build -t securities-service:1.0.0 ../modules/securities-service/
|
||||
docker run -p 8050:8080 -v /opt/clearing/logs:/opt/clearing/bin/logs securities-service:1.0.0 &
|
||||
docker run -v /opt/clearing/logs:/opt/clearing/bin/logs securities-service:1.0.0 &
|
||||
Loading…
Add table
Reference in a new issue