[framework] TxCore → common-framework (TxContext·MessageCodec) (ACM-FW-001)
This commit is contained in:
parent
9b43defd7d
commit
d15ff5673c
1 changed files with 124 additions and 15 deletions
|
|
@ -1,24 +1,133 @@
|
|||
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;
|
||||
|
||||
/**
|
||||
* 레거시 {@code msg_layout.h} 고정길이 전문(電文) 코덱의 Spring 빈 자리표시자.
|
||||
*
|
||||
* <p>실 전환에서는 고정길이(positional) 바이트 레이아웃 ↔ DTO 바인딩을 담당한다
|
||||
* (BeanIO 또는 커스텀 코덱). 지금은 스켈레톤이 빈으로 뜨는지만 증명한다.
|
||||
*/
|
||||
@Component
|
||||
public class MessageCodec {
|
||||
import java.util.Map;
|
||||
|
||||
/** 고정길이 필드를 우측을 공백으로 채워 정규화한다 (자리표시자 구현). */
|
||||
public String padRight(String value, int width) {
|
||||
if (value == null) {
|
||||
value = "";
|
||||
/**
|
||||
* Message codec interface and JSON implementation.
|
||||
* Provides encoding/decoding of TxRequest and TxResponse.
|
||||
*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Reference in a new issue