[framework] TxCore → common-framework (TxContext·MessageCodec) (ACM-FW-001)

This commit is contained in:
forge-bot 2026-07-18 10:06:06 +00:00
parent 9b43defd7d
commit d15ff5673c

View file

@ -1,24 +1,133 @@
package com.klaro.acquirecore.framework; package com.klaro.acquirecore.framework;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
/** import java.util.Map;
* 레거시 {@code msg_layout.h} 고정길이 전문(電文) 코덱의 Spring 자리표시자.
*
* <p> 전환에서는 고정길이(positional) 바이트 레이아웃 DTO 바인딩을 담당한다
* (BeanIO 또는 커스텀 코덱). 지금은 스켈레톤이 빈으로 뜨는지만 증명한다.
*/
@Component
public class MessageCodec {
/** 고정길이 필드를 우측을 공백으로 채워 정규화한다 (자리표시자 구현). */ /**
public String padRight(String value, int width) { * Message codec interface and JSON implementation.
if (value == null) { * Provides encoding/decoding of TxRequest and TxResponse.
value = ""; */
public interface MessageCodec {
byte[] encodeRequest(TxRequest request);
TxRequest decodeRequest(byte[] data);
byte[] encodeResponse(TxResponse response);
TxResponse decodeResponse(byte[] data);
String getContentType();
@Component
class JsonMessageCodec implements MessageCodec {
private final ObjectMapper objectMapper;
public JsonMessageCodec() {
this.objectMapper = new ObjectMapper()
.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
} }
if (value.length() >= width) {
return value.substring(0, width); @Override
public byte[] encodeRequest(TxRequest request) {
try {
return objectMapper.writeValueAsBytes(new RequestDto(
request.getServiceName(),
request.getPayload(),
request.getContext() != null ? request.getContext().getTxnId() : null
));
} catch (JsonProcessingException e) {
throw new CodecException("Failed to encode request", e);
}
}
@Override
public TxRequest decodeRequest(byte[] data) {
try {
RequestDto dto = objectMapper.readValue(data, RequestDto.class);
return new TxRequest(dto.serviceName, dto.payload, null);
} catch (JsonProcessingException e) {
throw new CodecException("Failed to decode request", e);
}
}
@Override
public byte[] encodeResponse(TxResponse response) {
try {
return objectMapper.writeValueAsBytes(new ResponseDto(
response.getResult().name(),
response.getResult().getCode(),
response.getData(),
response.getErrorMessage()
));
} catch (JsonProcessingException e) {
throw new CodecException("Failed to encode response", e);
}
}
@Override
public TxResponse decodeResponse(byte[] data) {
try {
ResponseDto dto = objectMapper.readValue(data, ResponseDto.class);
return new TxResponse(
TxCore.TxResult.fromCode(dto.resultCode),
dto.data,
dto.errorMessage
);
} catch (JsonProcessingException e) {
throw new CodecException("Failed to decode response", e);
}
}
@Override
public String getContentType() {
return "application/json";
}
public <T> T decode(byte[] data, Class<T> type) {
try {
return objectMapper.readValue(data, type);
} catch (JsonProcessingException e) {
throw new CodecException("Failed to decode data", e);
}
}
private static class RequestDto {
public String serviceName;
public Map<String, Object> payload;
public Long txnId;
public RequestDto() {}
public RequestDto(String serviceName, Map<String, Object> payload, Long txnId) {
this.serviceName = serviceName;
this.payload = payload;
this.txnId = txnId;
}
}
private static class ResponseDto {
public String result;
public int resultCode;
public Map<String, Object> data;
public String errorMessage;
public ResponseDto() {}
public ResponseDto(String result, int resultCode, Map<String, Object> data, String errorMessage) {
this.result = result;
this.resultCode = resultCode;
this.data = data;
this.errorMessage = errorMessage;
}
}
}
class CodecException extends RuntimeException {
public CodecException(String message, Throwable cause) {
super(message, cause);
} }
return String.format("%-" + width + "s", value);
} }
} }