FSDMsg Reply Unpacking

610 views
Skip to first unread message

Pieter Botha

unread,
Aug 10, 2012, 11:48:34 AM8/10/12
to jpos-...@googlegroups.com
Hi everyone,

I'm using the FSDMsg to talk to a non-iso endpoint (using qmux) and I'm experiencing 2 problems. The first is that the message sent does not conform to the layout and the second problem is the unpacking of the reply.

The first problem first. The log below does not conform to the XML schema below.  The only 2 variables being shown are the 2 being set in the java code, though I've done a pack() test and the XML file is being used. Any tips?
Log:
<send>
    <fsdmsg schema='file:cfg/tsm149-base'>
      parentKey: 'C700D2E075BA4B92B6974EE5DCE51CC0'
      2: '1'
    </fsdmsg>
  </send>

XML:
<schema>
<!--   <field id="msgLength" type="B" length="2"/> This should be calculated by the Channel-->
   <field id="magicVersion" type="BK" length="2">EDF1</field>
   <field id="target" type="BK" length="1">20</field>
   <field id="flags" type="BK" length="1">01</field>
   <field id="requestCode" type="BK" length="2">3801</field>
   <field id="2" type="N" length="4"/><!-- echoToken -->
   <field id="crc" type="BK" length="2">0000</field>
   <field id="messageCode" type="BK" length="1">95</field>
   <field id="keyspaceId" type="K" length="1" >0</field>
   <field id="parentKey" type="B" length="16" />
   <field id="parentKeyParity" type="B" length="1" />
   <field id="parentKeyCheckValue" type="B" length="4" />
   <field id="parentDecryptionMode" type="BK" length="1">00</field>
   <field id="keyType" type="B" length="1"/>
   <field id="keyUnderParent" type="B" length="16"/>
   <field id="keyCheckDigits" type="B" length="3"/>
   <field id="keyParity" type="B" length="1"/>
</schema>

Java:
         //create a new FSDMsg using cfg/tsm149-base.xml
         fsdMsg = new FSDMsg("file:cfg/tsm149-", "base");


         fsdMsg.set("parentKey", new String(theKeyStore.getKey(keyId).getKeyBytes()));
         fsdMsg.set("2" /*echo token*/, new Long(theTicketGenerator.getTicket()).toString());

         info( fsdMsg.pack() );
         ctx.put (cfg.get ("reqTsmMsgCtxRef"), new FSDISOMsg(fsdMsg));
         info("Put fsdMsg in context", ctx);

The second problem relating to the replies. When a reply FSD message is received, the log usually shows it nice parsed etc at channel level. Though it is somewhat difficult to tell an FSD channel that the reply it is receiving will be conforming to this very unique very special format that is not used in any other reply message. Any suggestions on how I can get the reply to be correctly interpreted?

Thanks,
  Pieter

Alejandro Revilla

unread,
Aug 14, 2012, 7:34:55 PM8/14/12
to jpos-...@googlegroups.com

The first problem first. The log below does not conform to the XML schema below.  The only 2 variables being shown are the 2 being set in the java code, though I've done a pack() test and the XML file is being used. Any tips?

The log just shows you the entries that you've set in the map, the rest will get default values at pack time, but you don't see those unless they are set in the FSDMsg.


The second problem relating to the replies. When a reply FSD message is received, the log usually shows it nice parsed etc at channel level. Though it is somewhat difficult to tell an FSD channel that the reply it is receiving will be conforming to this very unique very special format that is not used in any other reply message. Any suggestions on how I can get the reply to be correctly interpreted?

I don't think I understand the issue.

AAO

unread,
Aug 14, 2012, 10:03:40 PM8/14/12
to jpos-...@googlegroups.com
I, too, am not understanding what you're saying in that 2nd problem.

Andy


--
--
jPOS is licensed under AGPL - free for community usage for your open-source project. Licenses are also available for commercial usage.
Please support jPOS, contact: sa...@jpos.org
 
You received this message because you are subscribed to the "jPOS Users" group.
Please see http://jpos.org/wiki/JPOS_Mailing_List_Readme_first
To post to this group, send email to jpos-...@googlegroups.com
To unsubscribe, send email to jpos-users+...@googlegroups.com
For more options, visit this group at http://groups.google.com/group/jpos-users
 
 
 

Pieter Botha

unread,
Aug 15, 2012, 3:04:14 AM8/15/12
to jpos-...@googlegroups.com
Hi guys,

Sorry about the confusion. What I meant in the 2nd question is that the FSD message is a proprietary message of some sort which just happens to cast to FSDIsoMsg. The problem is that the layout is not ISO/standard based which makes it difficult to match up a reply on the Mux. Luckily the first few elements are the same across the request/reply messages. How would the mux match up a reply in this regard if it doesn't know about the reply layout expected / or how would I make it aware of a possible reply layout (even if it is just the first few elements)?

Example(key highlighted in red):
Request tsm149-base.xml:
<schema id="149">
<!--   <field id="msgLength" type="B" length="2"/> message length, done by channel -->
   <field id="magicVersion" type="BK" length="2">EDF1</field>
   <field id="target" type="BK" length="1">20</field>
   <field id="flags" type="BK" length="1">01</field>
   <field id="requestCode" type="BK" length="2">3801</field>
   <field id="2" type="N" length="4"/><!-- echo data long int-->
   <field id="crc" type="BK" length="2">0000</field>
   <field id="messageCode" type="BK" length="1">95</field> <!-- the message ID such as 95,5,2 etc -->
   <field id="keyspaceId" type="K" length="1" >0</field>
   <field id="parentKey" type="B" length="16" />
   <field id="parentKeyParity" type="B" length="1" />
</schema

Reply tsm150-base.xml:
<schema id="150" />
<!--  <field id="msgLength"   type="B"    length="2"  /> interpreted by channel -->
   <field id="magicVersion"   type="BK"   length="2"   >EDF1</field>
   <field id="target"         type="BK"   length="1"   >20</field>
   <field id="flags"          type="BK"   length="1"   >01</field>
   <field id="requestCode"    type="BK"   length="2"   >3801</field>
   <field id="2"              type="N"    length="4"  /><!-- echo data - long int-->
   <field id="CRC"            type="B"    length="2"   >0000</field>
   <field id="messageCode"    type="BK"   length="1"   >96</field>
   <field id="status"         type="B"    length="1"  />
</schema>

Mux:
<mux class="org.jpos.q2.iso.QMUX" name="tsmMux" logger="tsmLog" realm="tsmMux" >
  <ready>tsm1.ready</ready>
  <in>from-tsm</in>
  <out>to-tsm</out>
  <key>2</key>
  <property name="debug" value="true" />
  <property name="trace" value="true" />
</mux>

AAO

unread,
Aug 15, 2012, 9:01:38 AM8/15/12
to jpos-...@googlegroups.com
Hi Pieter -

Just checking - I assume you read this post?


Key (pun intended) passages:

Here's the linchpin of the approach:  The QMUX key fields have to be named with their ISO equivalents.  You can see below that we have two fields that equate directly to 41 and 11 (QMUX's default key - the TID and STAN respectively), so we named them as such in the XML structure.  Anything you put in the mux key you need to tie in here.

The field that designates ‘tran-type’ we named as ‘0’ (not mandatory) so that we could note that it’s the MTI-like equivalent

We named the Response Code-like field “39” so as not to break some OLS.Switch (our jPOS-based implementation) internals on response logging and origin-side formatting of replies.

-----------------

ALSO - not in the piece, but important:  

Our "QueryAuthHost" for this interface does this:

    protected String getResultCode(ISOMsg m) throws ISOException {
        return m.getString(39);
    }

Here's the req + resp in one of our relatively thin FSDISO implementations:

<?xml version="1.0" encoding="UTF-8"?>
<schema>
 <field id="header"             type="K"   length="7" >OLSPSID</field>  
 <field id="0"                  type="N"   length="2" />      
 <field id="41"                 type="A"   length="5" />      
 <field id="46"                 type="N"   length="19" />     <!-- from OLS.Switch's tranlog id (our Mux key) -->
 <field id="psid-trans-info"    type="AFS" length="43" />     
</schema>

<?xml version="1.0" encoding="UTF-8"?>
<schema>
 <field id="header"             type="K" length="7" >OLSPSID</field>
 <field id="0"                  type="N" length="2" />      
 <field id="41"                 type="A" length="5" />      
 <field id="46"                 type="N" length="19" />     
 <field id="39"               type="A" length="2"/>       
 <field id="psid-trans-reply"   type="AFS" length="255" /> 
</schema>

Andy 


Alejandro Revilla

unread,
Aug 15, 2012, 1:41:50 PM8/15/12
to jpos-...@googlegroups.com
I would just add a note of warning here, it's easy to get the MUX key matching wrong when using FSDMsg and pass initial single message tests, but if the keys used are not unique, you could mix up the responses, which is a total chaos situation.

Pieter Botha

unread,
Aug 16, 2012, 4:47:06 AM8/16/12
to jpos-...@googlegroups.com
Hi Andy, Alejandro,

Thanks for the replies. Yes I've read the howto on the blog which is how I came to designate the "key" mux fields. I think the best way to describe the problem is a log dump (below). How would I describe a "base.xml" to the FSD packager if the request/reply tends to differ in structure? 

The channel config is included for reference as well. Thanks for the assistance :)

Log:
log realm="tsmChannel/ ballas-bak :500" at="Thu Aug 16 10:22:44 SAST 2012.477" lifespan="4141ms">
<receive>
<iso-exception>
java.net.MalformedURLException: no protocol: base.xml
<nested-exception>
java.net.MalformedURLException: no protocol: base.xml
at java.net.URL.<init>(URL.java:567)
at java.net.URL.<init>(URL.java:464)
at java.net.URL.<init>(URL.java:413)
at org.jpos.util.FSDMsg.getSchema(FSDMsg.java:588)
at org.jpos.util.FSDMsg.getSchema(FSDMsg.java:573)
at org.jpos.util.FSDMsg.unpack(FSDMsg.java:193)
at org.jpos.util.FSDMsg.unpack(FSDMsg.java:210)
at org.jpos.iso.FSDISOMsg.unpack(FSDISOMsg.java:49)
at org.jpos.iso.BaseChannel.unpack(BaseChannel.java:902)
at org.jpos.iso.BaseChannel.receive(BaseChannel.java:670)
at org.jpos.q2.iso.ChannelAdaptor$Receiver.run(ChannelAdaptor.java:285)
at java.lang.Thread.run(Thread.java:662)
</nested-exception>
org.jpos.iso.ISOException: java.net.MalformedURLException: no protocol: base.xml (java.net.MalformedURLException: no protocol: base.xml)
at org.jpos.iso.FSDISOMsg.unpack(FSDISOMsg.java:52)
at org.jpos.iso.BaseChannel.unpack(BaseChannel.java:902)
at org.jpos.iso.BaseChannel.receive(BaseChannel.java:670)
at org.jpos.q2.iso.ChannelAdaptor$Receiver.run(ChannelAdaptor.java:285)
at java.lang.Thread.run(Thread.java:662)
Nested:java.net.MalformedURLException: no protocol: base.xml
at java.net.URL.<init>(URL.java:567)
at java.net.URL.<init>(URL.java:464)
at java.net.URL.<init>(URL.java:413)
at org.jpos.util.FSDMsg.getSchema(FSDMsg.java:588)
at org.jpos.util.FSDMsg.getSchema(FSDMsg.java:573)
at org.jpos.util.FSDMsg.unpack(FSDMsg.java:193)
at org.jpos.util.FSDMsg.unpack(FSDMsg.java:210)
at org.jpos.iso.FSDISOMsg.unpack(FSDISOMsg.java:49)
at org.jpos.iso.BaseChannel.unpack(BaseChannel.java:902)
at org.jpos.iso.BaseChannel.receive(BaseChannel.java:670)
at org.jpos.q2.iso.ChannelAdaptor$Receiver.run(ChannelAdaptor.java:285)
at java.lang.Thread.run(Thread.java:662)
</iso-exception>
--- data ---
0000 ED F1 20 01 00 00 30 30 30 31 00 00 96 0F 00 00 .. ...0001......
0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
0020 00 00 ..

Channel:
<?xml version="1.0" encoding="UTF-8"?>
<channel-adaptor name="tsm1" class="org.jpos.q2.iso.ChannelAdaptor" logger="tsmLog" realm="tsmChannel">
   <channel class="org.jpos.iso.channel.FSDChannel" logger="tsmLog" packager="org.jpos.iso.packager.FSDPackager" realm="tsmChannel">
      <property name="packager-logger" value="tsmLog"/>
      <property name="host" value="ballas-bak"/>
      <property name="port" value="5000"/>
      <property name="packager-config" value="cfg/tsm150-base.xml" />
    <property name="packager-realm" value="tsmChannel" />
   </channel>
   <in>to-tsm</in>
   <out>from-tsm</out>
   <reconnect-delay>10000</reconnect-delay>
   <property name="debug" value="true" />
   <property name="trace" value="true" />
</channel-adaptor>


On Friday, August 10, 2012 5:48:34 PM UTC+2, Pieter Botha wrote:

chhil

unread,
Aug 16, 2012, 5:01:29 AM8/16/12
to jpos-...@googlegroups.com

Is there a field that indicates a response to a corresponding request.
e.g. a field has a value of 'A ' indicating a request type of 'A' and a response comes back with a 'B'.
Then you could be your and probably have this as the key and individual schemas per key.
-chhil

Pieter Botha

unread,
Aug 16, 2012, 5:17:53 AM8/16/12
to jpos-...@googlegroups.com
Hi Chhil,

The "messagecode" field follows the following convention and always resides at the same place/offset in the message:
Request: 140
Reply: 141
Request: 149
Reply: 150

The reply message code is always 1 larger than the request code and the request code can be different depending on the type of request.

Pieter


On Friday, August 10, 2012 5:48:34 PM UTC+2, Pieter Botha wrote:

AAO

unread,
Aug 16, 2012, 9:20:27 AM8/16/12
to jpos-...@googlegroups.com
 You've not defined/properly-located the response schema in your definition (why you're getting those butt-ugly errors).  See example that follows.  Note that in the channel definition you define the *response* schema.  You handle the request separately in-line in your code like so:

    protected ISOMsg createISOMsg(Context ctx) throws Exception {
        Date now = (Date) ctx.get (TIMESTAMP);
        FSDMsg fsd = new FSDMsg ("file:cfg/verizon-");
        FSDMsg msg = (FSDMsg) ctx.tget (REQUEST);
        assertNotNull (msg, APPLERR_BADDATA,  "CreateVerizonRequest: invalid VG2 request");

        fsd.set ("0", mti);
        fsd.set ("request-source", "0");

        String storeNumber = msg.get ("store-number");
        fsd.set ("store-number", storeNumber);

        [snip]

        return new FSDISOMsg (fsd);
  
...which allows the definitions to be different.  [Which they almost always are in FSD implementations.]

Reinforcing two other points:

1) I, too, question whether the single echo field '2' is enough (4 positions).  Hell to pay if there's a chance of the same value being emitted.

2) See Chhill's advice on how to use key values to define different schema layouts based on keys.  Here's one example of me doing it:


That particular model consists of about 150 different layout options in total.

Your channel:

<?xml version="1.0" encoding="UTF-8"?>
<channel-adaptor name="tsm1" class="org.jpos.q2.iso.ChannelAdaptor" logger="tsmLog" realm="tsmChannel">
   <channel class="org.jpos.iso.channel.FSDChannel" logger="tsmLog" packager="org.jpos.iso.packager.FSDPackager" realm="tsmChannel">
      <property name="packager-logger" value="tsmLog"/>
      <property name="host" value="ballas-bak"/>
      <property name="port" value="5000"/>
      <property name="packager-config" value="cfg/tsm150-base.xml" />
    <property name="packager-realm" value="tsmChannel" />
   </channel>
   <in>to-tsm</in>
   <out>from-tsm</out>
   <reconnect-delay>10000</reconnect-delay>
   <property name="debug" value="true" />
   <property name="trace" value="true" />
</channel-adaptor>

My channel (pre-variable substitition):

<channel-adaptor name='verizon' 
    class="org.jpos.q2.iso.ChannelAdaptor" logger="Q2">
 <channel class="org.jpos.iso.channel.FSDChannel" logger="Q2" 
       realm="verizon-channel"
       packager="org.jpos.iso.packager.DummyPackager">
  <property name="host" value="@verizon0.host@" />
  <property name="port" value="@verizon0.port@" />
  <property name="schema" value="file:cfg/verizon-resp-" />
  <property name="timeout" value="1200000" />
  <property name="keep-alive" value="true" />    
  <filter class="org.jpos.iso.filter.ChannelInfoFilter" direction="outgoing">
      <property name="channel-name" value="1000" />
  </filter> 
 </channel>
 <in>verizon-send</in>
 <out>verizon-receive</out>
 <reconnect-delay>10000</reconnect-delay>
</channel-adaptor>

Andy Orrock

chhil

unread,
Aug 16, 2012, 10:29:18 AM8/16/12
to jpos-...@googlegroups.com
Andy thanks for the screencast, pictures say it better :)

-chhil

chhil

unread,
Aug 16, 2012, 10:43:02 AM8/16/12
to jpos-...@googlegroups.com
Pieter,

You could use the messagecode as a key and use that as your base and have separate schemas for your different message code requests and responses.
See Andys snapshot on how to do define them.

-chhil

Pieter Botha

unread,
Aug 22, 2012, 9:38:39 AM8/22/12
to jpos-...@googlegroups.com
Thanks for the help guys. It is now fully working :)


On Friday, August 10, 2012 5:48:34 PM UTC+2, Pieter Botha wrote:

chhil

unread,
Aug 22, 2012, 11:14:25 AM8/22/12
to jpos-...@googlegroups.com
Thats great!!!
What approach did you take?

-chhil

Pieter Botha

unread,
Aug 23, 2012, 4:00:26 AM8/23/12
to jpos-...@googlegroups.com
Hi Chhil,

I used the message code as the key with a xml file per request/reply with a schema id="my-message-code". It turned out to work quite well.
The echo data being a long int can be recycled as it only needs to be unique for a few seconds and the echo-data is being generated by a bean instance/single-ton instance which means no duplicate echo data numbers :)

Pieter

chhil

unread,
Aug 23, 2012, 4:25:39 AM8/23/12
to jpos-...@googlegroups.com
Thanks Pieter.


Pieter

--
Reply all
Reply to author
Forward
0 new messages