/* * 著作権表記 TODO 要否をお客様に確認 */ package com.pgf.mqspring.service.impl; import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.text.MessageFormat; import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Objects; import javax.jms.BytesMessage; import javax.jms.CompletionListener; import javax.jms.Destination; import javax.jms.JMSContext; import javax.jms.JMSException; import javax.jms.JMSProducer; import javax.jms.Message; import javax.xml.bind.DatatypeConverter; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.ConfigurableBeanFactory; import org.springframework.context.annotation.Scope; import org.springframework.http.HttpStatus; import org.springframework.jms.core.JmsTemplate; import org.springframework.stereotype.Service; import com.ibm.mq.constants.CMQC; import com.ibm.mq.headers.MQCIH; import com.pgf.mqspring.component.CharacterCodeConverterComponent; import com.pgf.mqspring.component.MqSpringMessageSourceComponent; import com.pgf.mqspring.component.TelegramInfoComponent; import com.pgf.mqspring.constant.BytesMessageKey; import com.pgf.mqspring.constant.MqSpringConst; import com.pgf.mqspring.constant.MqSpringMessageId; import com.pgf.mqspring.exception.MqSpringException; import com.pgf.mqspring.model.ReceiveMapVectorRequestModel; import com.pgf.mqspring.model.ReplyRequestModel; import com.pgf.mqspring.model.TelegramInfoModel; import com.pgf.mqspring.model.TestModel; import com.pgf.mqspring.service.MqSendService; /** * MQ送信用サービス実装クラス *

* 指定されたキューに対しメッセージを送信する。 */ @Service @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) public class MqSendServiceImpl implements MqSendService { /** JMSテンプレート */ private JmsTemplate jmsTemplate = null; /** キュー */ private String queue = MqSpringConst.BLANK; /** メッセージID */ private String messageId = MqSpringConst.BLANK; /** キューフォーマット */ private static final String QUE_FORMAT = "queue:///{0}?targetClient=1"; /** ロガー */ private static final Logger logger = LogManager.getLogger(); /** 電文情報クラス */ @Autowired private TelegramInfoComponent telegramInfoComponent; /** 文字コード変換クラス */ @Autowired private CharacterCodeConverterComponent characterCodeConverter; /** MqSpringメッセージソースクラス */ @Autowired private MqSpringMessageSourceComponent messageSource; /** 受信キュー名 */ @Value("${ibm.mq.queueName.receive}") private String receiveQueueName; /** JMS_X_ユーザーID */ @Value("${ibm.mq.user}") private String jmsXUserId; /** * MQ送信用サービス実装クラスのコンストラクタ * * @param template Jmsテンプレート * @param commonService コード変換サービスクラス */ public MqSendServiceImpl(JmsTemplate template) { this.jmsTemplate = template; } // TODO ITa後削除対象(テスト時の問題切り分け用) public String sendRawData(TestModel model) { // final String msgId = "20220912093247445184"; final String correId = "AMQ!NEW_SESSION_CORRELID"; try { JMSProducer jmsProducer = jmsTemplate.getConnectionFactory().createContext().createProducer(); jmsProducer.setAsync(new CompletionListener() { @Override public void onCompletion(Message msg) { try { messageId = msg.getJMSMessageID(); logger.info("Send Message ID=" + messageId); } catch (JMSException e) { e.printStackTrace(); } System.out.println(messageId); } @Override public void onException(Message msg, Exception e) { System.out.println(e.getMessage()); } }); Destination dest = jmsTemplate.getConnectionFactory().createContext().createQueue(queue); Destination reply = jmsTemplate.getConnectionFactory().createContext().createQueue("QL.MDH01.REPLY"); BytesMessage bm = jmsTemplate.getConnectionFactory().createContext().createBytesMessage(); bm.writeBytes(createRawDataMessage(model)); bm.setStringProperty("JMS_IBM_Format", CMQC.MQFMT_CICS); bm.setIntProperty("JMS_IBM_Encoding", CMQC.MQENC_NATIVE); bm.setIntProperty("JMS_IBM_Character_Set", 932); //bm.setJMSMessageID(msgId); bm.setJMSCorrelationID(correId); bm.setJMSReplyTo(reply); bm.setStringProperty("JMSXUserID", "GETS"); jmsProducer.send(dest, bm); return "200"; } catch (Exception ex) { ex.printStackTrace(); return "500"; } } /** * Mqメッセージ送信処理 *

* 送信用キューにメッセージを送信する。
* リクエストパラメーターの画面コードチェックを行う。
* MQCIHの電文組立処理を行う。 * MQCIHの電文組立処理にて例外が発生した場合
*  エラーログを出力する
*   ・メッセージID:SYS7070E
*   ・発生した例外:Exception
*  MqSpringExceptionの例外をスローする。以下引数
*   ・メッセージID:SYS7070E
*   ・HttpStatus:BAD_REQUEST
* MQCIHの書き込み処理を行う。 * MQCIHの書き込み処理にて例外が発生した場合
*  エラーログを出力する
*   ・メッセージID:SYS7070EE
*   ・発生した例外:IOException
*  MqSpringExceptionの例外をスローする。以下引数
*   ・メッセージID:SYS7070E
*   ・HttpStatus:INTERNAL_SERVER_ERROR
* 送信メッセージの文字コードをSJISからEBCDICに変換する。
* 文字コードの変換処理にて例外が発生した場合
*  エラーログを出力する
*   ・メッセージID:SYS7070E
*   ・発生した例外:Exception
*  MqSpringExceptionの例外をスローする。以下引数
*   ・メッセージID:SYS7070E
*   ・HttpStatus:BAD_REQUEST
* メッセージ送信イベント処理(非同期)を指定します。
*  メッセージが正常に送信された場合
*   メッセージ送信後に採番されたJMSメッセージIDを取得する。
*   JMSメッセージIDを設定する際に例外が発生した場合
*    エラーログを出力する
*     ・メッセージID:SYS7070E
*     ・発生した例外:Exception
*  確認応答が受信されない場合
*   エラーログを出力する
*    ・メッセージID:SYS7007E
*    ・発生した例外:Exception
* 編集した電文をログ出力し、指定されたキューへ送信する。
* 送信用キューへのメッセージ送信処理にて例外が発生した場合
*  エラーログを出力する
*   ・メッセージID:SYS7005E
*   ・発生した例外:Exception
*  MqSpringExceptionの例外をスローする。以下引数
*   ・メッセージID:SYS7005E
*   ・HttpStatus:BAD_REQUEST
* * @param model 送信リクエスト格納用モデルクラス * @return なし */ public void sendMqMessage(ReplyRequestModel model) { logger.debug("sendMqMessage start"); ReceiveMapVectorRequestModel recMapVecModel = model.getSendMessage().getReceiveMapVector(); String ads = model.getSendMessage().getAds(); String transactionId = model.getMqcih().getTransactionId(); logger.debug("Ads encode前:" + ads); // 画面コードチェック checkDisplayCode(transactionId); MQCIH cih = new MQCIH(); try { cih.setUOWControl(Integer.parseInt(model.getMqcih().getUowControl())); cih.setGetWaitInterval(Integer.parseInt(model.getMqcih().getGetWaitInterval())); cih.setLinkType(Integer.parseInt(model.getMqcih().getLinkType())); cih.setFacilityKeepTime(Integer.parseInt(model.getMqcih().getFacilityKeepTime())); cih.setConversationalTask(Integer.parseInt(model.getMqcih().getConversationalTask())); cih.setFacility(DatatypeConverter.parseHexBinary(model.getMqcih().getFacility())); cih.setAuthenticator(model.getMqcih().getAutherticator()); cih.setTransactionId(transactionId); } catch (Exception e) { logger.error(messageSource.getMessage(MqSpringMessageId.SYS7070E), e); throw new MqSpringException(MqSpringMessageId.SYS7070E, HttpStatus.BAD_REQUEST); } byte[] header = null; try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { cih.write(new DataOutputStream(out), CMQC.MQENC_NATIVE, 932); header = out.toByteArray(); } catch (IOException e) { logger.error(messageSource.getMessage(MqSpringMessageId.SYS7070E), e); throw new MqSpringException(MqSpringMessageId.SYS7070E, HttpStatus.INTERNAL_SERVER_ERROR); } byte[] convRecMapVec = null; byte[] convAds = null; try { if (recMapVecModel != null) { convRecMapVec = characterCodeConverter.encodeVectorData(transactionId, recMapVecModel, 48); } if (!ads.isEmpty()) { convAds = characterCodeConverter.encodeAdsData(transactionId, ads); } } catch (Exception e) { logger.error(messageSource.getMessage(MqSpringMessageId.SYS7070E), e); throw new MqSpringException(MqSpringMessageId.SYS7070E, HttpStatus.BAD_REQUEST); } logger.debug("Mqcih encode結果:" + Arrays.toString(header)); logger.debug("RecMapVec encode結果:" + Arrays.toString(convRecMapVec)); logger.debug("Ads encode結果:" + Arrays.toString(convAds)); try (JMSContext jmsContext = jmsTemplate.getConnectionFactory().createContext()) { JMSProducer jmsProducer = jmsContext.createProducer(); jmsProducer.setAsync(new CompletionListener() { /** * メッセージ送信完了時処理 *

* メッセージ送信後に採番されたJMSメッセージIDを取得する。 * メッセージID取得処理で例外が発生した場合
*  エラーログを出力する。以下引数
*   ・メッセージID:SYS7073E
*   ・発生した例外:JMSException
* * @param msg メッセージ */ @Override public void onCompletion(Message msg) { try { messageId = msg.getJMSMessageID(); logger.info("Send Message ID=" + messageId); } catch (JMSException e) { logger.error(messageSource.getMessage(MqSpringMessageId.SYS7073E), e); } } /** * 例外発生時処理 *

* エラーログを出力する。以下引数
*  ・メッセージID:SYS7007E
*  ・発生した例外:Exception
* * @param msg JMSメッセージ * @param e Exception */ @Override public void onException(Message msg, Exception e) { logger.error(messageSource.getMessage(MqSpringMessageId.SYS7007E), e); } }); try (ByteArrayOutputStream out = new ByteArrayOutputStream()) { Destination dest = jmsContext.createQueue(queue); Destination reply = jmsContext.createQueue(receiveQueueName); BytesMessage bm = jmsContext.createBytesMessage(); bm.writeBytes(header); out.write(header); if (convRecMapVec != null) { bm.writeBytes(convRecMapVec); out.write(convRecMapVec); } if (convAds != null) { bm.writeBytes(convAds); out.write(convAds); } bm.setStringProperty(BytesMessageKey.JMS_IBM_Format.name(), CMQC.MQFMT_CICS); bm.setIntProperty(BytesMessageKey.JMS_IBM_Encoding.name(), CMQC.MQENC_NATIVE); bm.setIntProperty(BytesMessageKey.JMS_IBM_Character_Set.name(), 943); bm.setJMSCorrelationID(model.getMqmd().getCorrelId()); bm.setJMSReplyTo(reply); bm.setStringProperty(BytesMessageKey.JMSXUserID.name(), jmsXUserId); logger.info("(" + transactionId + ")MQPUT >>"); logger.info(DatatypeConverter.printHexBinary(out.toByteArray())); jmsProducer.send(dest, bm); } logger.debug("sendMqMessage end"); } catch (Exception ex) { logger.error(messageSource.getMessage(MqSpringMessageId.SYS7005E), ex); throw new MqSpringException(MqSpringMessageId.SYS7005E, HttpStatus.INTERNAL_SERVER_ERROR); } } /** * キュー取得 *

* キューを返却する * * @return キュー */ public String getQueue() { return queue; } /** * キュー設定 *

* メッセージフォーマットを行い、フォーマット結果をキューに設定する。以下引数
*  ・キューフォーマット
*  ・キュー
* * @param que キュー * @return 無し */ public void setQueue(String que) { // example "queue:///QL.POC01.TEST2?targetClient=1" queue = MessageFormat.format(QUE_FORMAT, que); } /** * メッセージID取得 *

* メッセージIDを返却する * * @return メッセージID */ public String getMessageId() { return messageId; } /** * メッセージID設定 *

* メッセージIDを設定する * * @param messageId メッセージID * @return 無し */ public void setMessageId(String messageId) { this.messageId = messageId; } // TODO ITa後削除対象(テスト時の問題切り分け用) private byte[] createRawDataMessage(TestModel model) { final String mqcih1 = "4349482000000002000000b40000000000000000202020202020202000000000000000000000000000000000000001110002bf2000000002ffffffff000000b4000000000000000000000000" + model.getFacility()/*"0000000000000000"*/ + "202020202020202047455453333333332020202020202020202020202020202020202020202020204745303120202020202020202020202020202020202020202020202020202020202020202020202000000000000000000000000000000000"; final String mqcih2 = "4349482000000002000000b40000000000000000202020202020202000000000000000000000000000000000000001110002bf2000000002ffffffff000000b4000000000000000000000000" + model.getFacility()/*"0138000100000001"*/ + "202020202020202047455453333333332020202020202020202020202020202020202020202020204745303120202020202020202020202020202020202020202020202020202020202020202020202000000000000000000000000000000000"; final String mqcih3 = "4349482000000002000000b40000000000000000202020202020202000000000000000000000000000000000000001110002bf2000000002ffffffff000000b4000000000000000000000000" + model.getFacility()/*"0138000100000001"*/ + "202020202020202047455453333333332020202020202020202020202020202020202020202020204745303220202020202020202020202020202020202020202020202020202020202020202020202000000000000000000000000000000000"; final String mqcih4 = "4349482000000002000000b40000000000000000202020202020202000000000000000000000000000000000000001110002bf2000000002ffffffff000000b4000000000000000000000000" + model.getFacility()/*"0138000100000001"*/ + "202020202020202047455453333333332020202020202020202020202020202020202020202020204745303220202020202020202020202020202020202020202020202020202020202020202020202000000000000000000000000000000000"; final String mqcih5 = "4349482000000002000000b40000000000000000202020202020202000000000000000000000000000000000000001110002bf2000000002ffffffff000000b4000000000000000000000000" + model.getFacility()/*"0138000100000001"*/ + "20202020202020204745545333333333202020202020202020202020202020202020202020202020454d303420202020202020202020202020202020202020202020202020202020202020202020202000000000000000000000000000000000"; final String mqcih6 = "4349482000000002000000b40000000000000000202020202020202000000000000000000000000000000000000001110002bf2000000002ffffffff000000b4000000000000000000000000" + model.getFacility()/*"0138000100000001"*/ + "20202020202020204745545333333333202020202020202020202020202020202020202020202020454d303420202020202020202020202020202020202020202020202020202020202020202020202000000000000000000000000000000000"; final String vecAds2 = "000000ecf1f8f0f2c9404040f0f0f0f0e8404040d4c7c5f0f1f0f040d4c7c5f0f1f0f0407d40404000000000000000bb0000000000000000000000000000cc0000d4c7c5f0f1f0f0400000cc0000" + model.getDate()/*"f0f961f1f261f2f2"*/ + "0000cc0000" + model.getTime()/*"f0f97af3f27af4f4"*/ + "0000cc0000c7c5e3e2404040400000cc0000c7c5e3e2f3f3f3f30000cc000040404040404040400000cc000040404040404040400000cc00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; final String vecAds4 = "000000f8f1f8f0f2c9404040f0f0f0f0e8404040d4c7c5f0f2f0f040d4c7c5f0f2f0f0407d40404000000000000000c60000000000000000000000000000cc000040404040404040400000cc0000" + model.getDate()/*"f0f961f1f261f2f2"*/ + "0000cc0000c5d4f0f40000cc00004040404040404040404040404040404040404040404040404040404040404040404040404040404040400000cc0000f0f97af3f27af4f40000cc000040400000cc0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000"; final String vecAds6 = "000009ccf1f8f0f2c9404040f0f0f0f0e8404040d4c5d4f0f4f0f040d4c5d4f0f4f0f0407d404040000000000000099a0000000000000000000000000000cc0000c5d4f0f4404040400000cc000040404040404040400000cc000040404040404040404040400000cc000040404040404040400000cc000040404040404040404040400000cc000040404040404040404040400000cc0000f8f3f0f0f9f4f3f2f9f30000cc0000f2f0f2f3f0f3f1f60000cc000040404040404040400000cc0000400000cc0000400000cc0000404040404040400000cc00004040404040400000cc000040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040400000cc000040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040404040404040404040404040404040404040404040400000cc00004040404040404040404040400000cc000040404040404040404040400000cc000040404040404040404040400000cc000040404040404040400000cc00004040404040400000cc000040404040404040404040400000cc00004040404040404040404040400000cc00004040404040404040404040400000cc0000404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040404040400000"; logger.info("Send Destination=" + queue); logger.info("msgKind = " + model.getMsgKind()); logger.info("facility = " + model.getFacility()); logger.info("date = " + model.getDate()); logger.info("time = " + model.getTime()); byte[] bytes = null; switch (model.getMsgKind()) { case "1": bytes = DatatypeConverter.parseHexBinary(mqcih1); break; case "2": bytes = DatatypeConverter.parseHexBinary(mqcih2 + vecAds2); break; case "3": bytes = DatatypeConverter.parseHexBinary(mqcih3); break; case "4": bytes = DatatypeConverter.parseHexBinary(mqcih4 + vecAds4); break; case "5": bytes = DatatypeConverter.parseHexBinary(mqcih5); break; case "6": bytes = DatatypeConverter.parseHexBinary(mqcih6 + vecAds6); break; default: bytes = DatatypeConverter.parseHexBinary(mqcih1); break; } return bytes; } /** * 画面コードチェック *

* トランザクションIDがnull または トランザクションIDが空の場合
*  メッセージID:SYS7027Eのエラーメッセージを出力する。
*  MqSpringExceptionの例外をスローする。以下引数
*   ・メッセージID:SYS7027E
*   ・HttpStatus:BAD_REQUEST
* 電文情報マップを取得する
* トランザクションIDのキーが電文情報マップに存在しない場合
*  メッセージID:SYS7063Eのエラーメッセージを出力する。
*  MqSpringExceptionの例外をスローする。以下引数
*   ・メッセージID:SYS7063E
*   ・HttpStatus:BAD_REQUEST
* * @param transactionId トランザクションID * @return 無し */ private void checkDisplayCode(String transactionId) { // 画面コードがセットされていない場合 if (Objects.isNull(transactionId) || transactionId.isEmpty()) { logger.error(messageSource.getMessage(MqSpringMessageId.SYS7027E)); throw new MqSpringException(MqSpringMessageId.SYS7027E, HttpStatus.BAD_REQUEST); } // 画面コードに対するIBM電文定義マスタが存在しない場合 Map> TelegramInfoMap = telegramInfoComponent.getTelegramInfoMap(); if (!TelegramInfoMap.containsKey(transactionId)) { logger.error(messageSource.getMessage(MqSpringMessageId.SYS7063E)); throw new MqSpringException(MqSpringMessageId.SYS7063E, HttpStatus.BAD_REQUEST); } } }