jpos / jPOS

jPOS Project
http://jpos.org
GNU Affero General Public License v3.0
607 stars 460 forks source link

QMUX not able to work with FSDMsg without MTI #428

Open nalasra opened 3 years ago

nalasra commented 3 years ago

Hey Folks,

Not sure if this has been discussed before, but I went through jpos-user forums etc. But still I am not sure if this supported by jPOS or not.

I am working with Thales integration. And for some reason I am using QMUX+FSDChannel in order to send/receive HSM commands. I am trying to use thales header as a unique key element for my QMUX.

My configurations look like this: _mux.xml

<mux class="org.jpos.q2.iso.QMUX" logger="Q2" name="thales-primary-mux">
    <key>header</key>
    <in>thales-primary-receive</in>
    <out>thales-primary-send</out>
    <ready>thales-primary-channeladaptor.ready</ready>
</mux>

_channel.xml

<?xml version="1.0" ?>
<channel-adaptor name="thales-primary-channeladaptor" class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2">

    <channel  class="org.jpos.hsm.channel.ThalesChannel" logger="Q2"
              realm="thales-primary-channel" timeout="600000"
              packager="org.jpos.iso.packager.DummyPackager">

        <property name="schema" value="file:cfg/thales/thales-resp-"/>
        <property name="host" value="10.10.10.56"/>
        <property name="port" value="1500" />
        <property name="packager-realm" value="debug"/>
        <property name="keep-alive" value="true"/>
    </channel>

    <in>thales-primary-send</in>
    <out>thales-primary-receive</out>
    <reconnect-delay>5000</reconnect-delay>
</channel-adaptor>

thales-base.xml

<?xml version='1.0' encoding='utf-8'?>
<schema>
<field id='header' type='N' length='4'/>
<field id='command' type='A' length='2' key='true'/>
</schema>

thales-JA.xml

<?xml version='1.0' encoding='UTF-8'?>
<schema id='JA'>
<field id='account-number' type='A' length='12'/>
<field id='pin-length' type='A' length='2'/>
</schema>
FSDMsg f = new FSDMsg("file:cfg/thales-");
f.set("header", "1234");
f.set("command", "JA");
f.set("account-number", "123456789012");
f.set("pin-length", "04");

Exception:

        <info>
          prepare exception in org.jpos.hsm.participant.QueryHSM
          <exception name="null">
          java.lang.NullPointerException
    at org.jpos.q2.iso.QMUX.getKey(QMUX.java:258)
    at org.jpos.q2.iso.QMUX.request(QMUX.java:183)
    at org.jpos.q2.iso.MUXPool.request(MUXPool.java:138)
    at org.jpos.hsm.participant.QueryHSM.doPrepare(QueryHSM.java:31)
    at org.jpos.transaction.TxnSupport.prepare(TxnSupport.java:44)
    at org.jpos.transaction.TransactionManager.prepare(TransactionManager.java:579)
    at org.jpos.transaction.TransactionManager.prepare(TransactionManager.java:645)
    at org.jpos.transaction.TransactionManager.run(TransactionManager.java:318)
    at java.lang.Thread.run(Thread.java:748)
          </exception>
          SS_RESPONSE not present
        </info>

I can't pass through the QMUX exception with above configs. I can see that there is no way for QMUX to operate on a ISOMsg if there is no MTI set. https://github.com/jpos/jPOS/blob/master/jpos/src/main/java/org/jpos/q2/iso/QMUX.java#L258

I just wanted to know if this is how we intend to use QMUX? Or the MTI must be set? I tried a possibility to bypass the exception by setting f.setMTI("2100");

But the MTI now starts to appear in the log dumps and doesn't look really pretty.

       <fsdmsg schema='file:cfg/thales/thales-base'>
         header: '34'
         0: '2100'
         command: 'JA'
         pin-length: '04'
         account-number: '025701953012'
       </fsdmsg>

Now a new exception of key fields not found

      <info>
          prepare exception in org.jpos.hsm.participant.QueryHSM
          <iso-exception>
            Key fields not found - not sending thales-primary-send.210
            org.jpos.iso.ISOException: Key fields not found - not sending thales-primary-send.210
    at org.jpos.q2.iso.QMUX.getKey(QMUX.java:276)
    at org.jpos.q2.iso.QMUX.request(QMUX.java:183)
    at org.jpos.q2.iso.MUXPool.request(MUXPool.java:138)
    at org.jpos.hsm.participant.QueryHSM.doPrepare(QueryHSM.java:31)
    at org.jpos.transaction.TxnSupport.prepare(TxnSupport.java:44)
    at org.jpos.transaction.TransactionManager.prepare(TransactionManager.java:579)
    at org.jpos.transaction.TransactionManager.prepare(TransactionManager.java:645)
    at org.jpos.transaction.TransactionManager.run(TransactionManager.java:318)
    at java.lang.Thread.run(Thread.java:748)
          </iso-exception>
        </info>

I know if I use <key>0</key> along with f.setMTI("2100"); in my mux config it may go through, but is it really how it is suppose to work?

I can't seem to get headerIsKey to work as well. The code is expecting any fields defined in <key>header</key> to be present in the field map. Possible missing handling for header? https://github.com/jpos/jPOS/blob/master/jpos/src/main/java/org/jpos/q2/iso/QMUX.java#L257

   if (headerIsKey && m.getHeader()!=null) {
            log.error("headerIsKey=" + headerIsKey);
            sb.append ('.');
            sb.append(ISOUtil.hexString(m.getHeader()));
            sb.append ('.');
            hasFields=true; //header is key, so we have found fields
        }

Lastly, why we are doing substring(2) while dumping the header of FSDMsg? https://github.com/jpos/jPOS/blob/849b2dc95ebf0ddf779de0d8ea8f2155ee2d4050/jpos/src/main/java/org/jpos/util/FSDMsg.java#L562

Thanks for all the awesome work done by jPOS team. :)

ar commented 3 years ago

You need a field named "0", that can even be zero length field used as a placeholder. I guess FSDISOMsg could take care of providing such a field, if not present (feel free to send a PR if you wish).

-- @apr http://twitter.com/apr

On Wed, Jun 9, 2021 at 8:23 AM Arsalan Khan @.***> wrote:

Hey Folks,

Not sure if this has been discussed before, but I went through jpos-user forums etc. But still I am not sure if this supported by jPOS or not.

I am working with Thales integration. And for some reason I am using QMUX+FSDChannel in order to send/receive HSM commands. I am trying to use thales header as a unique key element for my QMUX.

My configurations look like this: _mux.xml

header thales-primary-receive thales-primary-send thales-primary-channeladaptor.ready

_channel.xml

<?xml version="1.0" ?>

thales-primary-send thales-primary-receive 5000

thales-base.xml

<?xml version='1.0' encoding='utf-8'?>

thales-JA.xml

<?xml version='1.0' encoding='UTF-8'?>

FSDMsg f = new FSDMsg("file:cfg/thales-"); f.set("command", "JA"); f.set("account-number", "123456789012"); f.set("pin-length", "04");

Exception:

    <info>
      prepare exception in org.jpos.hsm.participant.QueryHSM
      <exception name="null">
      java.lang.NullPointerException

at org.jpos.q2.iso.QMUX.getKey(QMUX.java:258) at org.jpos.q2.iso.QMUX.request(QMUX.java:183) at org.jpos.q2.iso.MUXPool.request(MUXPool.java:138) at org.jpos.hsm.participant.QueryHSM.doPrepare(QueryHSM.java:31) at org.jpos.transaction.TxnSupport.prepare(TxnSupport.java:44) at org.jpos.transaction.TransactionManager.prepare(TransactionManager.java:579) at org.jpos.transaction.TransactionManager.prepare(TransactionManager.java:645) at org.jpos.transaction.TransactionManager.run(TransactionManager.java:318) at java.lang.Thread.run(Thread.java:748) SS_RESPONSE not present

I can't pass through the QMUX exception with above configs. I can see that there is no way for QMUX to operate on a ISOMsg if there is no MTI set. https://github.com/jpos/jPOS/blob/master/jpos/src/main/java/org/jpos/q2/iso/QMUX.java#L258

I just wanted to know if this is how we intend to use QMUX? Or the MTI must be set? I tried a possibility to bypass the exception by setting f.setMTI("2100");

But the MTI now starts to appear in the log dumps and doesn't look really pretty.

   <fsdmsg schema='file:cfg/thales/thales-base'>
     header: '345678'
     0: '2100'
     command: 'JA'
     pin-length: '04'
     account-number: '025701953012'
   </fsdmsg>

Now a new exception of key fields not found

  <info>
      prepare exception in org.jpos.hsm.participant.QueryHSM
      <iso-exception>
        Key fields not found - not sending thales-primary-send.210
        org.jpos.iso.ISOException: Key fields not found - not sending thales-primary-send.210

at org.jpos.q2.iso.QMUX.getKey(QMUX.java:276) at org.jpos.q2.iso.QMUX.request(QMUX.java:183) at org.jpos.q2.iso.MUXPool.request(MUXPool.java:138) at org.jpos.hsm.participant.QueryHSM.doPrepare(QueryHSM.java:31) at org.jpos.transaction.TxnSupport.prepare(TxnSupport.java:44) at org.jpos.transaction.TransactionManager.prepare(TransactionManager.java:579) at org.jpos.transaction.TransactionManager.prepare(TransactionManager.java:645) at org.jpos.transaction.TransactionManager.run(TransactionManager.java:318) at java.lang.Thread.run(Thread.java:748)

I know if I use 0 along with f.setMTI("2100"); in my mux config it may go through, but is it really how it is suppose to work?

Lastly, why we are doing substring(2) while dumping the header of FSDMsg?

https://github.com/jpos/jPOS/blob/849b2dc95ebf0ddf779de0d8ea8f2155ee2d4050/jpos/src/main/java/org/jpos/util/FSDMsg.java#L562

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/jpos/jPOS/issues/428, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAYQAQHJ3ZMRCA75IW5KWLTR5FL5ANCNFSM46L2WGGQ .

mchhil-incomm commented 3 years ago

We use the header to match request response.

We use field "request" for sending requests, e.g. A6 And we use field "response" on receiving the A7.

A class that extends the FSDISOMsg overrides getMTI to get the MTI from the request message and response message by looking for the field command (in requests), looking for a field "response" in the response message.

    @Override
    public String getMTI() {
        String command = getFSDMsg().get("command");
        if (command==null){
            return getFSDMsg().get("response");
        }
        return command;

    }

The thales-base for requests is

<?xml version="1.0" encoding="UTF-8"?>
<schema>
<field id="stan" type="N" length="4"/> // this is the header where we put a rolling counter
 <field id="command" type="A" length="2" key="true" />
</schema>

The Thales base for responses is

<?xml version="1.0" encoding="UTF-8"?>
<schema>
<field id="stan" type="N" length="4" />
 <field id="response" type="A" length="2" key="true" />
 <field id="error"    type="A" length="2" />
</schema>

The mux is configured as

<mux class="org.jpos.q2.iso.QMUX" logger="Q2" name="thales-mux">
 <in>thales-receive</in>
 <out>thales-send</out>
 <key>stan</key>
 <ready>thales-adaptor-channel.ready</ready> 
 <unhandled>thales-unhandled</unhandled>
</mux>

The trick is to use an extended channels createMSG (this gets called at the time of receiving the response), to pass in the response schema via the channel configuration. So add a property to the channel

 @Override
    public ISOMsg createMsg() {
        FSDMsg fsdmsg = new FSDMsg (schema);

        return new ThalesFSDISOMsg (fsdmsg);
    }

    @Override
    public void setConfiguration (Configuration cfg)
        throws ConfigurationException
    {
        super.setConfiguration (cfg);
        schema = cfg.get ("schema");
    }

And when you create the FSD request and set fields, pass in the request schema in.

This matches request <->responses in the mux based on the header (what I call stan).

This was done way back, so I am sure there is a more elegant way to do this. It works for me, and I haven't bothered to change it.