メインコンテンツまでスキップ

ルータープログラム

プログラムの用途実装するJavaインターフェース注意事項
ルータープログラムRouteBuilderFlow Management > Router Information
ルータープログラムRouterProcessorRouter Information > Processing Program ID

基本ルーター以外に、新規ルーターを追加する場合に使用する。 ルータープログラム、およびルータープログラムを一緒に開発する必要がある。

開発方法

ルーター処理プログラムは、RouterProcessorを継承してprocessメソッドを実装する必要がある。下記の例は、対内システムで受信された電文が、Dummy電文かどうかを判断するルーターを開発し、当該ルーターを呼び出すルーター処理プログラムの例である。

caution

ルータープログラムは、開発後Flow Management > Router Informationに登録して使用する必要がある。 ルータープログラムは、動的に追加することはできるが、変更はできないため、ルータープログラムを変更した場合には、BXIを再実行する必要がある。

ルータープログラム

Apache camelのRouteBuilderを実装する。

public class InternalResponseDistinctRouter extends RouteBuilder {

/** Router process bean name */
private final String beanName;

/**
* Constructor
*
* @param beanName
*/
public InternalResponseDistinctRouter(String beanName) {
this.beanName = beanName;
}

/**
* Let's configure the Camel routing rules using Java code...
*/
@Override
public void configure() {
Processor nameProcess = RouterUtil.routerTemporaryProcess(beanName);

interceptFrom().setHeader(CamelHeader.ROUTER_ID, constant("internalResponseDistinctRouter"))
.routeId("internalResponseDistinctRouter").process("loggingPreProcessor");
from("direct:internalResponseDistinct").routeId("internalResponseDistinctRouter")
.process(nameProcess)
.process("routerBeanCallProcessor")
.end().process("loggingPostProcessor");
}
}

1. ルーターで処理するプログラムを入力

public class InternalResponseDistinctRouter extends RouteBuilder {

/** Router process bean name */
private final String beanName;

/**
* Constructor
*
* @param beanName
*/
public InternalResponseDistinctRouter(String beanName) {
this.beanName = beanName;
}

Router ProgramのConstructorを通じて処理プログラムの入力を受ける。入力される処理プログラムは、必ずSpring Beanプログラムでなければならない。

2. ルーター処理Configure

@Override
public void configure() {

RouteBuilderのconfigureメソッドを実装する。

configureメソッドは、ルーターがメッセージを受け取って処理する部分について順序どおりに記述する部分である。 configureメソッドに記述するルーターIDは、ルーターを識別するIDでUniqueでなければならない。 また、from句のURLは、外部から当該ルーターを呼び出す際に使用するURLとしてUniqueでなければならない。

3. ルーター処理プログラム伝達準備

Processor nameProcess = RouterUtil.routerTemporaryProcess(beanName);

入力で受け取ったプログラムを、直接.process()の因子として渡すことはできない。 そのため、Processor interfaceのinnerオブジェクトを1つ作成し、入力されたプログラムを、Exchangeのin領域のヘッダーを通じて伝達する。

このようにする理由は、.process()で呼び出されるすべての処理プログラムの因子は、常にExchangeであるからである。 1つのルーターから他のルーターを呼び出す際に入力で伝達されるメッセージは、Exchange in領域に伝達し、Exchange inやout領域で結果を受け取る。

4. ルーター入力ロギング

interceptFrom().setHeader(CamelHeader.ROUTER_ID, constant("internalResponseDistinctRouter"))
.routeId("internalResponseDistinctRouter").process("loggingPreProcessor");

ルータープログラムの処理は、常にfromから始まる。

BXIのルーターは、ルーター入力と出力に対してロギングできるが、これを処理するために、fromをインターセプターして、先に入力に対するロギングを行う。loggingPreProcessorに入力で伝達される因子は、fromから受けるExchangeである。

5. ルーター処理プログラムの呼び出し

from("direct:internalResponseDistinct").routeId("internalResponseDistinctRouter")
.process(nameProcess)
.process("routerBeanCallProcessor")

外部からルーターを呼び出すURLは、from句に記述したdirect:internalResponseDistinctである。

つまり、ルーターを代表するURLでも、重複するとエラーが発生するため、ルーターごとにUniqueなURLを付与する必要がある。 BXIは、ルーター情報を登録する際に、ルーターのURLも一緒に登録してフローを作成する際に使用する。

外部からdirect:requestHeaderMappingでルーターを呼び出すと、まずルーター処理プログラム伝達準備のプロセスを先に実行し、入力で受け取ったプログラムをExchangeのin領域のヘッダーに保存する。

次にrouterBeanCallProcessorプログラムは、Exchangeを入力で受け取り、in領域のヘッダーからルーター処理プログラムを照会してプログラムを呼び出す。 routerBeanCallProcessorは、BXIからルーター処理プログラムを呼び出すUtilityである。

ルーター処理プログラムを呼び出す際の入力としてはfromから受け取ったExchangeである。

6. ルーター出力ロギング

.end().process("loggingPostProcessor");

ルーターのすべての処理が終わったら、最後にルーターの出力に対するロギングを処理する。 出力をロギングするloggingPostProcessorは、Exchangeを入力で受け取ってロギングする。

ルーター処理プログラム

bxi.api-{version}.jarRouterProcessorを実装する。

@Component
public class InternalResponseDistinctProcessor extends RouterProcessor {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

/**
* Processes the message exchange
*
* @param exchange
* @throws Exception
*/
@Override
public void process(ProcessorExchange exchange) throws Exception {
ExchangeMessage bxiMessage = exchange.getBxiMessage();
logger.debug("Input getBody : {}", bxiMessage);

// TODO : Writing the program for the router function

RequestResponseKindEnum rqstRspsDscd = RequestResponseKindEnum.getByCode(
bxiMessage.getRqstRspsDscd());
if (RequestResponseKindEnum.REQUEST == rqstRspsDscd) {
return;
}

Map<String, Object> header = ObjectUtil.isEmpty(bxiMessage.getStdHeader())
? bxiMessage.getComHeader() : bxiMessage.getStdHeader();
logger.debug("header : {}", header);

if ("DMY".equals(header.get("rspsCd"))) {
logger.info("Skip message. Dummy response. guid : {}", bxiMessage.getGuid());
// 次のRouter Stop処理のためにHeader Set
exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
}
}
}

1. ルーター処理プログラム開始

@Override
public void process(ProcessorExchange exchange) throws Exception {
ExchangeMessage bxiMessage = exchange.getBxiMessage();
logger.debug("Input getBody : {}", bxiMessage);

processメソッドはパラメータでProcessorExchangeを受け取る。

2. ルーター処理プログラム開発

RequestResponseKindEnum rqstRspsDscd = RequestResponseKindEnum.getByCode(
bxiMessage.getRqstRspsDscd());
if (RequestResponseKindEnum.REQUEST == rqstRspsDscd) {
return;
}

Map<String, Object> header = ObjectUtil.isEmpty(bxiMessage.getStdHeader())
? bxiMessage.getComHeader() : bxiMessage.getStdHeader();
logger.debug("header : {}", header);

if ("DMY".equals(header.get("rspsCd"))) {
logger.info("Skip message. Dummy response. guid : {}", bxiMessage.getGuid());
// 次のRouter Stop処理のためにHeader Set
exchange.setProperty(Exchange.ROUTE_STOP, Boolean.TRUE);
}

この部分にルーターの機能に適するプログラムを開発する。 上記の例は、当該電文が要求電文でありながらDummy電文である場合に処理を中断する例である。

전체 예제

헤더부 전문 Unmarshal 프로그램

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.nexacro17.xapi.data.DataSet;
import com.nexacro17.xapi.data.PlatformData;
import com.nexacro17.xapi.tx.HttpPlatformRequest;

import bxi.common.constant.CamelHeader;
import bxi.common.context.ErrorLogger;
import bxi.common.dao.dto.BxiIntrnlSysBizIO;
import bxi.common.dao.dto.BxiMsgLayoutIO;
import bxi.common.dao.dto.BxiMsgLayoutMngIO;
import bxi.common.enums.JavaTypeEnum;
import bxi.common.exception.BxiException;
import bxi.common.model.BxiMessage;
import bxi.common.model.XmlTypeInfo;
import bxi.common.utility.ObjectUtil;
import bxi.common.utility.StringUtil;
import bxi.extension.customizing.constant.FieldName;
import bxi.parser.base.LayoutUtil;

@Component
public class NexacroHeaderUnmarshalProcessor implements Processor {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Override
public void process(Exchange exchange) {
Message in = exchange.getIn();
BxiMessage bxiMessage = in.getBody(BxiMessage.class);

// Check input parameter
if (ObjectUtil.isEmpty(bxiMessage)) {
return;
}
logger.debug("Input getBody : {}", bxiMessage);

// The message received from the Nexacro terminal is received via getMessage()
String message = bxiMessage.getMessage(String.class);
if (StringUtil.isEmpty(message)) {
ErrorLogger.errorLogging(bxiMessage, "BXIE02144");
throw new BxiException("BXIE02144");
}
logger.debug("message : {}", message);

/** Query header layout information of system where Nexacro terminal is defined.
* The header layout uses the information registered in the common header layout
* of the system-specific business information
*/
BxiIntrnlSysBizIO intrnlSysBizInfo = getHeader(CamelHeader.INTERNAL_SYS_BIZ_INFO,
BxiIntrnlSysBizIO.class);

// Query message layout
String headerLayout = intrnlSysBizInfo.getStdMsgHdrLayout();
BxiMsgLayoutMngIO msgTrnsfrmInfo = LayoutUtil.selectMessageManagement(headerLayout);
if (ObjectUtil.isEmpty(msgTrnsfrmInfo)) {
ErrorLogger.errorLogging(bxiMessage, "BXIE02113", headerLayout);
throw new BxiException("BXIE02113", headerLayout);
}
Map<String, BxiMsgLayoutIO> layoutMap = LayoutUtil.selectBxiMsgLayout(headerLayout);

// Extract data received from Nexacro terminal
InputStream inStream = new ByteArrayInputStream(message.getBytes());
HttpPlatformRequest xrequest = new HttpPlatformRequest(inStream);
xrequest.receiveData();

// Extract XML data from Request for Nexacro
PlatformData xdata = xrequest.getData();
logger.debug("request input xml data = [{}]", xdata.saveXml());

// Extract the header data from the extracted layout data
// and store it in Unmarshal and comHeader
Map<String, Object> header = new LinkedHashMap<String, Object>();
DataSet ds = xdata.getDataSet(FieldName.HEADER_DATASET_NAME);
if (ds != null) {
// Nexacro header unmarshal
unmarshalHeader(ds, layoutMap, headerLayout, header);
} else {
ErrorLogger.errorLogging(bxiMessage, "BXIE02113", "nexacro");
throw new BxiException("BXIE02113", "nexacro");
}

if (ObjectUtil.isEmpty(header)) {
ErrorLogger.errorLogging(bxiMessage, "BXIE02113", headerLayout);
throw new BxiException("BXIE02113", headerLayout);
}
bxiMessage.setComHeader(header);
logger.debug("header : {}", header);

// Save layout information
XmlTypeInfo xmlInfo = LayoutUtil.makeXmlTypeInfo(msgTrnsfrmInfo, 0);
bxiMessage.setComHeaderMsgInfo(xmlInfo);

// Originally, we had to separate the header message from the whole message.
// but Nexacro can not be detached, so you can save the entire message as Body Message
bxiMessage.setBodyMessage(message);
}

/**
* Nexacro header unmarshal
*
* The layout field data is a field name defined in the layout
* and is retrieved from the dataset and stored in the map.
* If you are in a Sub layout, create a Map for the Sub layout and unmarshal it in the same way.
*
* @param ds
* @param layoutMap
* @param headerLayout
* @param colData
*/
private void unmarshalHeader(DataSet ds, Map<String, BxiMsgLayoutIO> layoutMap,
String headerLayout, Map<String, Object> colData) {

if (ObjectUtil.isEmpty(layoutMap)) {
// Inquiry message layout details
layoutMap = LayoutUtil.selectBxiMsgLayout(headerLayout);
if (ObjectUtil.isEmpty(layoutMap)) {
ErrorLogger.errorLogging("BXIE02158", headerLayout);
throw new BxiException("BXIE02158", headerLayout);
}
}

for (Entry<String, BxiMsgLayoutIO> entry : layoutMap.entrySet()) {
BxiMsgLayoutIO layout = entry.getValue();

JavaTypeEnum type = JavaTypeEnum.getByCode(layout.getFldTypeCd());
if (type == JavaTypeEnum.OMM) {
Map<String, Object> sub = new LinkedHashMap<String, Object>();
unmarshalHeader(ds, null, layout.getFldFormat(), sub);
colData.put(layout.getFldNm(), sub);
} else {
colData.put(layout.getFldNm(), ds.getObject(0, layout.getFldNm()));
}
}
}
}

전문 형식이 다른 경우 개별부 전문 Unmarshal 프로그램

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import com.nexacro17.xapi.data.DataSet;
import com.nexacro17.xapi.data.PlatformData;
import com.nexacro17.xapi.tx.HttpPlatformRequest;
import com.nexacro17.xapi.tx.PlatformException;

import bxi.common.constant.CamelHeader;
import bxi.common.context.ErrorLogger;
import bxi.common.dao.dto.BxiMsgLayoutIO;
import bxi.common.dao.dto.BxiMsgLayoutMngIO;
import bxi.common.dao.dto.BxiOnlineIntrfcIO;
import bxi.common.enums.JavaTypeEnum;
import bxi.common.enums.RequestResponseKindEnum;
import bxi.common.exception.BxiException;
import bxi.common.model.BxiMessage;
import bxi.common.model.XmlTypeInfo;
import bxi.common.utility.ObjectUtil;
import bxi.common.utility.StringUtil;
import bxi.extension.customizing.constant.FieldName;
import bxi.parser.base.LayoutUtil;

@Component
public class NexacroBodyUnmarshalProcessor implements Processor {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Override
public void process(Exchange exchange) {
Message in = exchange.getIn();
BxiMessage bxiMessage = in.getBody(BxiMessage.class);

// Check input parameter
if (ObjectUtil.isEmpty(bxiMessage)) {
return;
}
logger.debug("Input getBody : {}", bxiMessage);

// The message received from the Nexacro terminal is received via getMessage()
String message = bxiMessage.getMessage(String.class);
if (StringUtil.isEmpty(message)) {
ErrorLogger.errorLogging(bxiMessage, "BXIE02144");
throw new BxiException("BXIE02144");
}
logger.debug("message : {}", message);

// Do not marshall the body unless transaction specific information is registered.
BxiOnlineIntrfcIO onlIntrfcInfo = getHeader(CamelHeader.ONLINE_INTERFACE_INFO,
BxiOnlineIntrfcIO.class);
String msgBodyLayout = bodyMsgLayout(onlIntrfcInfo, bxiMessage.getRqstRspsDscd());
if (StringUtil.isEmpty(msgBodyLayout)) {
return;
}

// Body message unmarshal
if (unmarshalBody(bxiMessage, msgBodyLayout)) {
throw new BxiException("BXIE02109");
}
}

/**
* Body message unmarshal
*
* @param bxiMessage
* @param msgBodyLayout
* @return
* @throws Exception
*/
private boolean unmarshalBody(BxiMessage bxiMessage, String msgBodyLayout)
throws Exception {

logger.debug("msgBodyLayout : {}", msgBodyLayout);

// Inquiry message layout
BxiMsgLayoutMngIO msgTrnsfrmInfo = LayoutUtil.selectMessageManagement(msgBodyLayout);
if (ObjectUtil.isEmpty(msgTrnsfrmInfo)) {
ErrorLogger.errorLogging(bxiMessage, "BXIE02109", msgBodyLayout);
return true;
}
Map<String, BxiMsgLayoutIO> layoutMap = LayoutUtil.selectBxiMsgLayout(msgBodyLayout);

// Extract data received from Nexacro terminal
PlatformData xdata = getNexacroXmlData(bxiMessage);

// Extract individual data from the extracted layout data
// and store it in body by Unmarshal
Map<String, Object> body = new LinkedHashMap<String, Object>();
setNexacroXmlToMap(body, layoutMap, xdata);
bxiMessage.setBody(body);

logger.debug("InternalBody : {}", body);

// Save layout information
XmlTypeInfo xmlInfo = LayoutUtil.makeXmlTypeInfo(msgTrnsfrmInfo, 0);
bxiMessage.setBodyMsgInfo(xmlInfo);

return false;
}

/**
* Extract data received from Nexacro terminal
*
* @param bxiMessage
* @return PltformData
* @throws PlatformException
* @throws UnsupportedEncodingException
*/
private PlatformData getNexacroXmlData(BxiMessage bxiMessage)
throws PlatformException, UnsupportedEncodingException {

// Request Extraction for Nexacro
byte[] byteMessage = ((String) bxiMessage.getMessage()).getBytes();
InputStream inStream = new ByteArrayInputStream(byteMessage);
HttpPlatformRequest xrequest = new HttpPlatformRequest(inStream);
xrequest.receiveData();

// Extract XML data from Request for Nexacro
logger.debug("request body input xml data = [{}]", xrequest.getData().saveXml());
return xrequest.getData();
}

/**
* Change Nexacro Xml data to Map
*
* @param body
* @param layoutMap
* @param xdata
*/
private void setNexacroXmlToMap(Map<String, Object> body, Map<String, BxiMsgLayoutIO> layoutMap,
PlatformData xdata) {

// All fields in the top-level layout are passed to the Root DataSet
DataSet dsRoot = xdata.getDataSet(FieldName.ROOT_DATASET_NAME);

// Parses Nexacro Xml data to Map to a defined layout
for (Entry<String, BxiMsgLayoutIO> entry : layoutMap.entrySet()) {
BxiMsgLayoutIO layout = entry.getValue();

JavaTypeEnum type = JavaTypeEnum.getByCode(layout.getFldTypeCd());
// List
if (!StringUtil.isEmpty(layout.getArrayRefNm())) {
List<Map<String, Object>> listMap = new ArrayList<Map<String, Object>>();
DataSet dsTemp = xdata.getDataSet(layout.getFldNm());
if (!ObjectUtil.isEmpty(dsTemp)) {
for (int i = 0; i < dsTemp.getRowCount(); i++) {
Map<String, Object> row = new LinkedHashMap<String, Object>();
unmarshalNexacro(i, dsTemp, null, layout.getFldFormat(), row);

listMap.add(row);
}
body.put(layout.getFldNm(), listMap);
}
}
// OMM
else if (type == JavaTypeEnum.OMM) {
DataSet dsTemp = xdata.getDataSet(layout.getFldNm());
if (!ObjectUtil.isEmpty(dsTemp)) {
Map<String, Object> sub = new LinkedHashMap<String, Object>();
unmarshalNexacro(0, dsTemp, null, layout.getFldFormat(), sub);

body.put(layout.getFldNm(), sub);
}
}
// Field
else {
body.put(layout.getFldNm(), dsRoot.getObject(0, layout.getFldNm()));
}
}
}

/**
* Nexacro bidy unmarshal
*
* @param ds
* @param layoutMap
* @param colData
*/
private void unmarshalNexacro(int crow, DataSet ds, Map<String, BxiMsgLayoutIO> layoutMap,
String msgBodyLayout, Map<String, Object> colData) {

if (ObjectUtil.isEmpty(layoutMap)) {
// Inquiry message layout details
layoutMap = LayoutUtil.selectBxiMsgLayout(msgBodyLayout);

if (ObjectUtil.isEmpty(layoutMap)) {
ErrorLogger.errorLogging("BXIE02158", msgBodyLayout);
throw new BxiException("BXIE02158", msgBodyLayout);
}
}

for (Entry<String, BxiMsgLayoutIO> entry : layoutMap.entrySet()) {
BxiMsgLayoutIO layout = entry.getValue();

JavaTypeEnum type = JavaTypeEnum.getByCode(layout.getFldTypeCd());
if (type == JavaTypeEnum.OMM) {
Map<String, Object> sub = new LinkedHashMap<String, Object>();
unmarshalNexacro(crow, ds, null, layout.getFldFormat(), sub);
colData.put(layout.getFldNm(), sub);
} else {
colData.put(layout.getFldNm(), ds.getObject(crow, layout.getFldNm()));
}
}
}

/**
* Body DtoName Lookup
*
* @param onlIntrfcInfo
* @param rqstRspsDscd
*/
private String bodyMsgLayout(BxiOnlineIntrfcIO onlIntrfcInfo, String rqstRspsDscd) {
if (StringUtil.isEmpty(rqstRspsDscd)) {
return null;
}

RequestResponseKindEnum rqstRsps = RequestResponseKindEnum.getByCode(rqstRspsDscd);
if (rqstRsps == RequestResponseKindEnum.REQUEST) {
return onlIntrfcInfo.getRqstMsgLayout();
} else {
return onlIntrfcInfo.getRspsMsgLayout();
}
}
}

전문 구조가 다른 경우 개별부 전문 Unmarshal 프로그램

import java.util.Map;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import bxi.common.constant.CamelHeader;
import bxi.common.constant.Constant;
import bxi.common.context.ErrorLogger;
import bxi.common.dao.dto.BxiIntrnlSysBizIO;
import bxi.common.dao.dto.BxiMsgLayoutMngIO;
import bxi.common.dao.dto.BxiOnlineIntrfcIO;
import bxi.common.enums.RequestResponseKindEnum;
import bxi.common.exception.BxiException;
import bxi.common.model.BxiMessage;
import bxi.common.model.XmlTypeInfo;
import bxi.common.utility.ObjectUtil;
import bxi.common.utility.StringUtil;
import bxi.extension.customizing.constant.FieldName;
import bxi.parser.Unmarshaller;
import bxi.parser.base.LayoutUtil;

@Component
public class BcMciBodyUnmarshalProcessor implements Processor {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Override
public void process(Exchange exchange) {
Message in = exchange.getIn();
BxiMessage bxiMessage = in.getBody(BxiMessage.class);

// Check input parameter
if (ObjectUtil.isEmpty(bxiMessage)) {
return;
}
logger.debug("Input getBody : {}", bxiMessage);

// Verification of individual part except header part
if (ObjectUtil.isEmpty(bxiMessage.getBodyMessage())) {
logger.debug("BodyMessage is Null Or Space");
return;
}

// Online interface information inquiry
BxiOnlineIntrfcIO onlIntrfcInfo = getHeader(CamelHeader.ONLINE_INTERFACE_INFO,
BxiOnlineIntrfcIO.class);

// Unmarshal the message part only for the response
RequestResponseKindEnum rqstRsps = RequestResponseKindEnum.getByCode(
bxiMessage.getRqstRspsDscd());
if (rqstRsps == RequestResponseKindEnum.RESPONSE) {
// Message part unmarshal
BxiIntrnlSysBizIO intrnlSysBizInfo = getHeader(CamelHeader.INTERNAL_SYS_BIZ_INFO,
BxiIntrnlSysBizIO.class);
unmarshalResponseMessage(intrnlSysBizInfo, bxiMessage);
}

// Individual layout inquiry
String msgBodyLayout = bodyMsgLayout(onlIntrfcInfo, bxiMessage.getRqstRspsDscd());
if (StringUtil.isEmpty(msgBodyLayout)) {
return;
}

// Body message unmarshal
if (unmarshalBody(bxiMessage, msgBodyLayout)) {
throw new BxiException("BXIE02109");
}
}

/**
* Message part unmarshal
*
* @param intrnlSysBizInfo
* @param bxiMessage
* @return
* @throws Exception
*/
private Map<String, Object> unmarshalResponseMessage(BxiIntrnlSysBizIO intrnlSysBizInfo,
BxiMessage bxiMessage) throws Exception {

// Unmarshal message part
Map<String, Object> messageMap = Unmarshaller.unmarshal(intrnlSysBizInfo.getChlMsgTypeCd(),
FieldName.MESSAGE_LAYOUT_NAME, bxiMessage.getBodyMessage(),
intrnlSysBizInfo.getMsgCharSetCd(), false, null);

logger.debug("messageMap: {}", messageMap);

// Returns if there is no message part data
if (ObjectUtil.isEmpty(messageMap)) {
return null;
}

int length = (int) messageMap.get(Constant.MESSAGE_LENGTH_NAME);
messageMap.remove(Constant.MESSAGE_LENGTH_NAME);
bxiMessage.setErrMessage(messageMap);

// Save layout information
BxiMsgLayoutMngIO msgTrnsfrmInfo = LayoutUtil.selectMessageManagement(
FieldName.ADD_MESSAGE_LAYOUT_NAME);
XmlTypeInfo xmlInfo = LayoutUtil.makeXmlTypeInfo(msgTrnsfrmInfo, length);
bxiMessage.setErrMsgInfo(xmlInfo);

return messageMap;
}

/**
* Body message unmarshal
*
* @param bxiMessage
* @param msgBodyLayout
* @return
*/
private boolean unmarshalBody(BxiMessage bxiMessage, String msgBodyLayout) {
// System business information
BxiIntrnlSysBizIO intrnlSysBizInfo = getHeader(CamelHeader.INTERNAL_SYS_BIZ_INFO,
BxiIntrnlSysBizIO.class);

if (logger.isDebugEnabled()) {
logger.debug("messageType : {}", intrnlSysBizInfo.getChlMsgTypeCd());
logger.debug("msgBodyLayout : {}", msgBodyLayout);
logger.debug("bodyMessage : {}", bxiMessage.getBodyMessage());
}

// Query layout information
BxiMsgLayoutMngIO msgTrnsfrmInfo = LayoutUtil.selectMessageManagement(msgBodyLayout);
if (ObjectUtil.isEmpty(msgTrnsfrmInfo)) {
ErrorLogger.errorLogging(bxiMessage, "BXIE02109", msgBodyLayout);
return true;
}

// Unmarshal
Map<String, Object> body = Unmarshaller.unmarshal(intrnlSysBizInfo.getChlMsgTypeCd(),
msgBodyLayout, bxiMessage.getBodyMessage(), intrnlSysBizInfo.getMsgCharSetCd(),
false, null);
if (ObjectUtil.isEmpty(body)) {
ErrorLogger.errorLogging(bxiMessage, "BXIE02109", msgBodyLayout);
return true;
}
int length = (int) body.get(Constant.MESSAGE_LENGTH_NAME);
body.remove(Constant.MESSAGE_LENGTH_NAME);

// Save layout information
XmlTypeInfo xmlInfo = LayoutUtil.makeXmlTypeInfo(msgTrnsfrmInfo, length);
bxiMessage.setBodyMsgInfo(xmlInfo);

logger.debug("InternalBody : {}", body);

bxiMessage.setBodyMessage(null);
bxiMessage.setBody(body);

return false;
}

/**
* Body DtoName Lookup
*
* @param onlIntrfcInfo
* @param rqstRspsDscd
*/
private String bodyMsgLayout(BxiOnlineIntrfcIO onlIntrfcInfo, String rqstRspsDscd) {
if (StringUtil.isEmpty(rqstRspsDscd)) {
return null;
}

RequestResponseKindEnum rqstRsps = RequestResponseKindEnum.getByCode(rqstRspsDscd);
if (rqstRsps == RequestResponseKindEnum.REQUEST) {
return onlIntrfcInfo.getRqstMsgLayout();
} else {
return onlIntrfcInfo.getRspsMsgLayout();
}
}
}

전문 Marshal 프로그램

import java.io.ByteArrayOutputStream;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.nexacro17.xapi.data.DataSet;
import com.nexacro17.xapi.data.DataTypes;
import com.nexacro17.xapi.data.PlatformData;
import com.nexacro17.xapi.data.VariableList;
import com.nexacro17.xapi.tx.PlatformResponse;

import bxi.common.constant.CamelHeader;
import bxi.common.context.ErrorLogger;
import bxi.common.dao.dto.BxiIntrnlSysBizIO;
import bxi.common.dao.dto.BxiMsgLayoutIO;
import bxi.common.dao.dto.BxiOnlineIntrfcIO;
import bxi.common.enums.JavaTypeEnum;
import bxi.common.exception.BxiException;
import bxi.common.model.BxiMessage;
import bxi.common.utility.CharsetUtil;
import bxi.common.utility.ObjectUtil;
import bxi.common.utility.StringUtil;
import bxi.extension.customizing.constant.FieldName;
import bxi.online.common.DaoProcess;
import bxi.parser.base.LayoutUtil;

@Component
public class NexacroMarshalProcessor implements Processor {
private final Logger logger = LoggerFactory.getLogger(this.getClass());

@Autowired
private DaoProcess daoProcess;

@Override
public void process(Exchange exchange) {
Message in = exchange.getIn();
BxiMessage bxiMessage = in.getBody(BxiMessage.class);

// Check input parameter
if (ObjectUtil.isEmpty(bxiMessage)) {
return;
}
logger.debug("Input getBody : {}", bxiMessage);

// System business information inquiry
BxiIntrnlSysBizIO intrnlSysBizInfo = internalSystemBizInfo(bxiMessage);

// Preparing to generate Nexacro Xml data
DataSet headerDS = new DataSet(FieldName.HEADER_DATASET_NAME);
PlatformData xdata = new PlatformData();
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
PlatformResponse xresponse = new PlatformResponse(outStream);

// Convert header part to Nexacro layout format
marshalNexacroHeader(bxiMessage, intrnlSysBizInfo.getStdMsgHdrLayout(), headerDS, xdata);
xdata.addDataSet(headerDS);

// Convert message part to Nexacro layout format if message part exists
if (!ObjectUtil.isEmpty(bxiMessage.getErrMessage())) {
marshalNexacroMessage(bxiMessage.getComHeader(), bxiMessage.getErrMessage(), xdata);
}

// Convert individual parts to Nexacro layout format if separate parts exist
if (!ObjectUtil.isEmpty(bxiMessage.getBody())) {
BxiOnlineIntrfcIO onlIntrfcInfo = getHeader(CamelHeader.ONLINE_INTERFACE_INFO,
BxiOnlineIntrfcIO.class);
marshalNexacroBody(bxiMessage.getBody(), onlIntrfcInfo.getRspsMsgLayout(), xdata);
}

logger.debug("NexacroMarshal result : {}", xdata.saveXml());

// Save Nexacro Response Data
xresponse.setData(xdata);
xresponse.sendData();

logger.debug("Send Message : {}", outStream.toString());

// Setting Nexacro Response Data in BXI
bxiMessage.setMessage(outStream.toString().getBytes(CharsetUtil.DEFAULT_CHARSET));
}

/**
* Convert header part to Nexacro layout format
*
* @param bxiMessage
* @param headerLayout
* @param headerDS
* @param xdata
*/
private void marshalNexacroHeader(BxiMessage bxiMessage, String headerLayout,
DataSet headerDS, PlatformData xdata) {

// Query header layout information
Map<String, BxiMsgLayoutIO> layoutMap = LayoutUtil.selectBxiMsgLayout(headerLayout);

// Header data
Map<String, Object> mapHeader = bxiMessage.getComHeader();

// Generate Nexacro DataSet Column data for a defined layout layout
for (Entry<String, BxiMsgLayoutIO> entry : layoutMap.entrySet()) {
BxiMsgLayoutIO layout = entry.getValue();
int xformType = convertTypeDescriptor(layout.getFldTypeCd());
headerDS.addColumn(layout.getFldNm(), xformType, layout.getFldLen());
}

// Generate Nexacro DataSet Row data for a defined layout layout
int rowNumHeader = headerDS.newRow();
for (Entry<String, BxiMsgLayoutIO> entry : layoutMap.entrySet()) {
BxiMsgLayoutIO layout = entry.getValue();
int xformType = convertTypeDescriptor(layout.getFldTypeCd());
if (xformType == DataTypes.UNDEFINED) {
continue;
}

headerDS.set(rowNumHeader, layout.getFldNm(), mapHeader.get(layout.getFldNm()));
}
}

/**
* Convert message part to Nexacro layout format
*
* @param headerMap
* @param messageMap
* @param xdata
*/
private void marshalNexacroMessage(Map<String, Object> headerMap, Map<String, Object> messageMap,
PlatformData xdata) {

// Query message layout information
Map<String, BxiMsgLayoutIO> msgLayoutMap = LayoutUtil.selectBxiMsgLayout(
FieldName.MESSAGE_LAYOUT_NAME);

// Query message detail layout information
Map<String, BxiMsgLayoutIO> msgDetailLayoutMap = LayoutUtil.selectBxiMsgLayout(
FieldName.ADD_MESSAGE_LAYOUT_NAME);

DataSet dsMsg = new DataSet(FieldName.MESSAGE_DATASET_NAME);
addColumnMessageDataSet(dsMsg, msgLayoutMap, msgDetailLayoutMap, messageMap);

@SuppressWarnings("unchecked")
List<Map<String, Object>> list = (List<Map<String, Object>>) messageMap.get(
FieldName.ADD_MESSAGE_FIELD_NAME);

for (Map<String, Object> map : list) {
int rowNum = dsMsg.newRow();
for (Entry<String, BxiMsgLayoutIO> entryDetail : msgDetailLayoutMap.entrySet()) {
BxiMsgLayoutIO layoutDetail = entryDetail.getValue();
dsMsg.set(rowNum, layoutDetail.getFldNm(), map.get(layoutDetail.getFldNm()));
}
}
xdata.addDataSet(dsMsg);

// Insert ErrorCode value -1 in Nexacro Parameter if error response
// 1: System error, 2: Business error, 3: DB error
if ("1".equals(headerMap.get(FieldName.RESPONSE_DIVISION_CODE))
|| "2".equals(headerMap.get(FieldName.RESPONSE_DIVISION_CODE))
|| "3".equals(headerMap.get(FieldName.RESPONSE_DIVISION_CODE))) {

VariableList varList = xdata.getVariableList();
varList.add(FieldName.NEXACRO_ERR_CD, -1);
varList.add(FieldName.NEXACRO_ERR_MSG, dsMsg.saveXml());
}
}

/**
* Convert individual part to Nexacro layout format
*
* @param bodyMap
* @param msgBodyLayout
* @param xdata
*/
@SuppressWarnings("unchecked")
private void marshalNexacroBody(Map<String, Object> bodyMap, String msgBodyLayout,
PlatformData xdata) {

// Query individual layout information
Map<String, BxiMsgLayoutIO> bodyLayoutMap = LayoutUtil.selectBxiMsgLayout(msgBodyLayout);

DataSet dsRoot = new DataSet(FieldName.ROOT_DATASET_NAME);
addColumnDataSet(dsRoot, bodyLayoutMap, null);
int rootRowNum = dsRoot.newRow();

List<Map<String, Object>> list = null;
for (Entry<String, BxiMsgLayoutIO> entry : bodyLayoutMap.entrySet()) {
BxiMsgLayoutIO layout = entry.getValue();

JavaTypeEnum type = JavaTypeEnum.getByCode(layout.getFldTypeCd());
// List
if (!StringUtil.isEmpty(layout.getArrayRefNm())) {
DataSet dsTemp = new DataSet(layout.getFldNm());
addColumnDataSet(dsTemp, null, layout.getFldFormat());

list = (List<Map<String, Object>>) bodyMap.get(layout.getFldNm());
if (list != null) {
for (Map<String, Object> map : list) {
int rowNum = dsTemp.newRow();
addRowDataSet(rowNum, dsTemp, layout.getFldFormat(), map);
}
}
xdata.addDataSet(dsTemp);
}
// OMM
else if (type == JavaTypeEnum.OMM) {
Map<String, Object> sub = (Map<String, Object>) bodyMap.get(layout.getFldNm());
DataSet dsTemp = new DataSet(layout.getFldNm());
addColumnDataSet(dsTemp, null, layout.getFldFormat());

int rowNum = dsTemp.newRow();
addRowDataSet(rowNum, dsTemp, layout.getFldFormat(), sub);
xdata.addDataSet(dsTemp);
}
// Field
else {
dsRoot.set(rootRowNum, layout.getFldNm(), bodyMap.get(layout.getFldNm()));
}
}

logger.debug("NexacroMarshal result : {}", xdata.saveXml());
xdata.addDataSet(dsRoot);
}

/**
* Generate column information of message part DataSet
*
* @param dsTemp
* @param layoutMap
* @param layoutDetailMap
* @param messageMap
*/
private void addColumnMessageDataSet(DataSet dsTemp, Map<String, BxiMsgLayoutIO> layoutMap,
Map<String, BxiMsgLayoutIO> layoutDetailMap, Map<String, Object> messageMap) {

for (Entry<String, BxiMsgLayoutIO> entry : layoutMap.entrySet()) {
BxiMsgLayoutIO layout = entry.getValue();

if (!StringUtil.isEmpty(layout.getArrayRefNm())) {
for (Entry<String, BxiMsgLayoutIO> detailEntry : layoutDetailMap.entrySet()) {
BxiMsgLayoutIO layoutDetail = detailEntry.getValue();
int xformType = convertTypeDescriptor(layoutDetail.getFldTypeCd());
if (xformType == DataTypes.UNDEFINED) {
continue;
}
dsTemp.addColumn(layoutDetail.getFldNm(), xformType, layoutDetail.getFldLen());
}
} else {
dsTemp.addConstantColumn(layout.getFldNm(), messageMap.get(layout.getFldNm()));
}
}
}

/**
* Generate column information of individual part DataSet
*
* @param dsTemp
* @param layoutMap
* @param msgBodyLayout
*/
private void addColumnDataSet(DataSet dsTemp, Map<String, BxiMsgLayoutIO> layoutMap,
String msgBodyLayout) {

if (layoutMap == null) {
// Query message detail layout information
layoutMap = LayoutUtil.selectBxiMsgLayout(msgBodyLayout);
}

for (Entry<String, BxiMsgLayoutIO> entry : layoutMap.entrySet()) {
BxiMsgLayoutIO layout = entry.getValue();

int xformType = convertTypeDescriptor(layout.getFldTypeCd());
if (xformType == DataTypes.UNDEFINED) {
continue;
}
dsTemp.addColumn(layout.getFldNm(), xformType, layout.getFldLen());
}
}

/**
* Generate Row information of individual part DataSet
*
* @param rowNum
* @param dsTemp
* @param msgBodyLayout
* @param sub
*/
private void addRowDataSet(int rowNum, DataSet dsTemp, String msgBodyLayout,
Map<String, Object> sub) {

// Query message detail layout information
Map<String, BxiMsgLayoutIO> layoutMap = LayoutUtil.selectBxiMsgLayout(msgBodyLayout);

for (Entry<String, BxiMsgLayoutIO> entry : layoutMap.entrySet()) {
BxiMsgLayoutIO layout = entry.getValue();
dsTemp.set(rowNum, layout.getFldNm(), sub.get(layout.getFldNm()));
}
}

/**
* Extracting the field type for the DataSet
*
* @param type
* @return
*/
private int convertTypeDescriptor(String type) {
if (type.toUpperCase().equals("STRING")) {
return DataTypes.STRING;
} else if (type.toUpperCase().equals("BOOLEAN")) {
return DataTypes.BOOLEAN;
} else if (type.toUpperCase().equals("DOUBLE")) {
return DataTypes.DOUBLE;
} else if (type.toUpperCase().equals("FLOAT")) {
return DataTypes.FLOAT;
} else if (type.toUpperCase().equals("INTEGER")) {
return DataTypes.INT;
} else if (type.toUpperCase().equals("LONG")) {
return DataTypes.LONG;
} else if (type.toUpperCase().equals("DATE")) {
return DataTypes.DATE_TIME;
} else if (type.toUpperCase().equals("BIGDECIMAL")) {
return DataTypes.BIG_DECIMAL;
} else {
return DataTypes.UNDEFINED;
}
}

/**
* System business information inquiry
*
* @param bxiMessage
* @return
*/
private BxiIntrnlSysBizIO internalSystemBizInfo(BxiMessage bxiMessage) {
BxiIntrnlSysBizIO intrnlSysBizInfo = null;
String sysId = null;

if (bxiMessage.isErrorResponseFlag()) {
intrnlSysBizInfo = getHeader(CamelHeader.INTERNAL_SYS_BIZ_INFO,
BxiIntrnlSysBizIO.class);
sysId = bxiMessage.getSysId();
} else {
intrnlSysBizInfo = getHeader(CamelHeader.SEND_SYS_BIZ_INFO,
BxiIntrnlSysBizIO.class);
sysId = bxiMessage.getSendSysId();
}
if (!ObjectUtil.isEmpty(intrnlSysBizInfo)) {
return intrnlSysBizInfo;
}

intrnlSysBizInfo = daoProcess.selectInternalSystemBizInfo(bxiMessage, sysId,
bxiMessage.getBizCd());
if (ObjectUtil.isEmpty(intrnlSysBizInfo)) {
ErrorLogger.errorLogging(bxiMessage, "BXIE02025",
bxiMessage.getSendSysId(), bxiMessage.getBizCd());
throw new BxiException("BXIE02025",
bxiMessage.getSendSysId(), bxiMessage.getBizCd());
}

if (bxiMessage.isErrorResponseFlag()) {
setHeader(CamelHeader.INTERNAL_SYS_BIZ_INFO, intrnlSysBizInfo);
} else {
setHeader(CamelHeader.SEND_SYS_BIZ_INFO, intrnlSysBizInfo);
}

return intrnlSysBizInfo;
}
}