diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/AnyKafkaMessageAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/AnyKafkaMessageAction.java new file mode 100644 index 000000000..cd0f8aaf1 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/AnyKafkaMessageAction.java @@ -0,0 +1,60 @@ +package ru.spcex.clearing.backendapi.controller.test; + +import io.swagger.annotations.ApiModelProperty; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRawValue; +import com.fasterxml.jackson.databind.JsonNode; +import ru.spcex.clearing.backendapi.domain.actions.IAction; +import ru.spcex.clearing.platform.messaging.domain.ActionType; +import ru.spcex.clearing.platform.messaging.domain.cud.registry.TradingClearingRegistryNewRequest; + +public class AnyKafkaMessageAction implements IAction { + @ApiModelProperty(value = "полное имя класса payload для BaseRequest", example = "ru.spcex.clearing.platform.messaging.domain.cud.schedule.LauncherCommandRequest") + @JsonProperty + private String fullClassName; + @JsonProperty + private String topicName; + @JsonRawValue + public String json; + + @JsonProperty("json") + private void unpackRawJson(JsonNode json) { + this.json = json.toString(); + } + + @Override + public TradingClearingRegistryNewRequest toRequest() { + var req = new TradingClearingRegistryNewRequest(); + return req; + } + + @ApiModelProperty(hidden = true) + @Override + public ActionType getActionType() { + return ActionType.SYSTEM; + } + + public String getFullClassName() { + return fullClassName; + } + + public void setFullClassName(String fullClassName) { + this.fullClassName = fullClassName; + } + + public String getTopicName() { + return topicName; + } + + public void setTopicName(String topicName) { + this.topicName = topicName; + } + + public String getJson() { + return json; + } + + public void setJson(String json) { + this.json = json; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/KafkaApiController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/KafkaApiController.java new file mode 100644 index 000000000..ffd706d01 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/KafkaApiController.java @@ -0,0 +1,67 @@ +package ru.spcex.clearing.backendapi.controller.test; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JavaType; +import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.util.ClassUtils; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import ru.spcex.clearing.backendapi.errors.BackEndError; +import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender; +import ru.spcex.platform.utils.enumeration.EnumMessage; +import ru.spcex.platform.utils.error.ValidationException; +import ru.spcex.platform.utils.text.TextUtil; + +@Profile("dev") +@Controller +@RequestMapping("/anonymous/kafka-api") +public class KafkaApiController { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final KafkaSender kafkaSender; + private static final ObjectMapper json = new ObjectMapper(); + + @Autowired + public KafkaApiController(KafkaSender kafkaSender) { + this.kafkaSender = kafkaSender; + } + + @ApiOperation(value = "Test backend-api availability.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = String.class)}) + @RequestMapping(method = RequestMethod.POST, path = "/any/message", produces = MediaType.TEXT_PLAIN_VALUE) + @ResponseBody + public String processGet(@ApiParam(value = "Параметры команды в JSON формате.", required = true) + @RequestBody AnyKafkaMessageAction bankAccountNewAction) throws ClassNotFoundException, ValidationException, JsonProcessingException { + log.info("Call test method for backend-api controller"); + validate(bankAccountNewAction); + Class parameterType = ClassUtils.forName(bankAccountNewAction.getFullClassName(), ClassUtils.getDefaultClassLoader()); + JavaType requestType = json.getTypeFactory().constructSimpleType(parameterType, null); + Object obj = json.readValue(bankAccountNewAction.getJson(), requestType); + Long idOfBaseRequestMessage = kafkaSender.sendRequestToQueue(bankAccountNewAction.getTopicName(), obj); + return "success: baseRequest.id = " + idOfBaseRequestMessage; + } + + private void validate(AnyKafkaMessageAction bankAccountNewAction) throws ValidationException { + if (TextUtil.isEmpty(bankAccountNewAction.getTopicName())) { + throw new ValidationException(new EnumMessage(BackEndError.ValidationError, "topicName")); + } + if (TextUtil.isEmpty(bankAccountNewAction.getFullClassName())) { + throw new ValidationException(new EnumMessage(BackEndError.ValidationError, "fullClassName")); + } + if (TextUtil.isEmpty(bankAccountNewAction.getJson())) { + throw new ValidationException(new EnumMessage(BackEndError.ValidationError, "json")); + } + } + +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/RevalMapAction.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/RevalMapAction.java new file mode 100644 index 000000000..a2bd32a54 --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/RevalMapAction.java @@ -0,0 +1,22 @@ +package ru.spcex.clearing.backendapi.controller.test; + +import io.swagger.annotations.ApiModelProperty; +import java.util.List; +import com.fasterxml.jackson.annotation.JsonProperty; + +public class RevalMapAction { + @ApiModelProperty( + value = "мапы для перезагрузки", + example = "Map_Registry" + ) + @JsonProperty + private List maps; + + public List getMaps() { + return maps; + } + + public void setMaps(List maps) { + this.maps = maps; + } +} diff --git a/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/RevalMapController.java b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/RevalMapController.java new file mode 100644 index 000000000..2e17f90ce --- /dev/null +++ b/clearing-parent/backend-api/src/main/java/ru/spcex/clearing/backendapi/controller/test/RevalMapController.java @@ -0,0 +1,69 @@ +package ru.spcex.clearing.backendapi.controller.test; + +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import java.util.List; +import java.util.concurrent.atomic.AtomicLong; +import com.hazelcast.core.IMap; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.bind.annotation.ResponseBody; +import ru.spcex.platform.imdg.api.ImdgProvider; +import ru.spcex.platform.imdg.iml.hazelcast.service.HazelcastService; +import ru.spcex.platform.utils.error.ValidationException; + +@Profile("dev") +@Controller +@RequestMapping("/anonymous/reval") +public class RevalMapController implements InitializingBean { + private final Logger log = LoggerFactory.getLogger(getClass()); + private final ImdgProvider imdgProvider; + private IMap revalMap; + + @Autowired + public RevalMapController(ImdgProvider imdgProvider) { + this.imdgProvider = imdgProvider; + } + + @Override + public void afterPropertiesSet() throws Exception { + imdgProvider.waitAvailable(); + this.revalMap = ((HazelcastService) imdgProvider).getHazelcast().getMap("REVAL"); + } + + private final AtomicLong l = new AtomicLong( + 1L + ); + + @ApiOperation(value = "Test backend-api availability.") + @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = String.class)}) + @RequestMapping(method = RequestMethod.POST, path = "/", produces = MediaType.TEXT_PLAIN_VALUE) + @ResponseBody + public String processPost( + @ApiParam(value = "Параметры команды в JSON формате.", required = true) + @RequestBody + RevalMapAction revalCommand) throws ClassNotFoundException, ValidationException { + log.info("Call test method for backend-api reval maps"); + List maps = revalCommand.getMaps(); + if (maps.isEmpty()) { + throw new IllegalArgumentException("must be at least one map"); + } + for (String map : maps) { + revalMap.put( + l.getAndIncrement(), + map + ); + } + return "success"; + } +} diff --git a/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/services/RevalMapService.java b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/services/RevalMapService.java new file mode 100644 index 000000000..cb09245ff --- /dev/null +++ b/clearing-parent/imdg/src/main/java/ru/spcex/clearing/imdg/services/RevalMapService.java @@ -0,0 +1,44 @@ +package ru.spcex.clearing.imdg.services; + +import com.hazelcast.core.EntryEvent; +import com.hazelcast.core.HazelcastInstance; +import com.hazelcast.core.IMap; +import com.hazelcast.query.Predicates; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Profile; +import org.springframework.stereotype.Service; + +@Profile("dev") +@Service +public class RevalMapService extends AbstractUpdateMapService { + private final Logger log = LoggerFactory.getLogger(this.getClass()); + + @Autowired + public RevalMapService(HazelcastInstance hazelcastServerInstance) { + super(hazelcastServerInstance); + } + + @Override + public void addingListenersToCards() { + hazelcastServerInstance.getMap("REVAL") + .addLocalEntryListener(this, Predicates.alwaysTrue(), true); + } + + @Override + protected void entryModified(EntryEvent event, String eventType) { + log.debug("{} {}", event, eventType); + String mapName = (String) (EVENT_DELETE.equals(eventType) ? event.getOldValue() : event.getValue()); + + IMap map = hazelcastServerInstance.getMap(mapName); + if (map.isEmpty()) { + log.warn("no values in " + mapName); + return; + } + map.evictAll(); + log.info("cleared {}", mapName); + map.loadAll(true); + log.info("loaded {} keys for {}", map.size(), mapName); + } +}