[ASK] Best Practice with XML Server

137 views
Skip to first unread message

Meldri Asan

unread,
May 17, 2017, 4:10:27 AM5/17/17
to jPOS Users
Hi everyone,

i've create 2 java project using JPos library (Client & Server). I want execute server and client at different place but it must connected each other. This Project was developed using jpos-gateaway tutorial. This project already run smoothly, client send message and get response. But i think something going wrong. Client side is using Q2,but at server side i think Q2 didnt work properly.

this is Client structure code
ClientISOQ2
- src
- com
- client
- iso
- ClientIso.java
- Deploy
- 00_logger.xml
- 10_channel_jpos.xml
- 20_mux.xml
- 99_sysmon.xml
- Log
- iso8583.xml


Server Structure Code
ServerISOQ2
- src
- com
- server
- iso
- ServerIso.java
- Deploy
- 00_logger.xml
- 50_xml_server.xml
- 99_sysmon.xml
- Log
- iso8583.xml

10_channel_jpos.xml
<channel-adaptor name='jpos-channel' class="org.jpos.q2.iso.ChannelAdaptor"
logger="Q2">
<channel name="ServerA-Channel"  
logger="Q2" realm="ServerA-Channel" 
class="org.jpos.iso.channel.XMLChannel"
packager="org.jpos.iso.packager.XMLPackager">
    <property name="host" value="localhost" />
<property name="port" value="8000" />
    </channel>
<in>jpos-send</in>
<out>jpos-receive</out>
<reconnect-delay>10000</reconnect-delay>
</channel-adaptor>


20_mux.xml
<mux class="org.jpos.q2.iso.QMUX" logger="Q2" name="mymux">
   <in>jpos-receive</in>
   <out>jpos-send</out>
   <ready>ServerA-Channel.ready</ready>
</mux>

50_server.xml
<server class="org.jpos.q2.iso.QServer" logger="Q2"
name="xml-server-8000" realm="xml-server-8000">
<attr name="port" type="java.lang.Integer">8000</attr>
<channel class="org.jpos.iso.channel.XMLChannel"
packager="org.jpos.iso.packager.XMLPackager"
type="server"
logger="Q2"
realm="xml-server-8000">
<property name="timeout" value="180000"/>
</channel>
<request-listener class="com.server.iso.ServerIso" logger="Q2">
<property name="queue" value="TXNMGR" />
<property name="destination" value="dest" />
</request-listener>
</server>

ClientIso.java
public class ClientIso {
    public static void main(String[] args) throws InterruptedException {
     Q2 q2 = new Q2();
        q2.start();
        
        Thread.sleep(5000);
        try {
            QMUX qmux = (QMUX) NameRegistrar.getIfExists("mux.mymux");
            
            try {           
             ISOMsg reply = qmux.request(createReqMsg(), 1000);
             System.out.println(new String(reply.pack()));
} catch (Exception e) {
e.printStackTrace();
System.out.println("Gagal Koneksi");
}

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
   
public static ISOMsg createReqMsg(){
     ISOMsg reqMsg = new ISOMsg();
        //reqMsg.setHeader("ISO011000017".getBytes());
        try {
            reqMsg.setMTI("0800");
            reqMsg.set(11, String.valueOf(System.currentTimeMillis() % 1000000));
            reqMsg.set(41, "12345678");
            reqMsg.set(70, "301");

        } catch (ISOException e) {
            e.printStackTrace();
        }
        return reqMsg;
    }
}


ServerIso.java
public class ServerIso implements ISORequestListener{
public static void main(String[] args) throws IOException, ISOException {
Logger logger = new Logger ();
logger.addListener (new SimpleLogListener (System.out));
XMLChannel channel = new XMLChannel(new XMLPackager());
((LogSource)channel).setLogger (logger, "channel");
ISOServer server = new ISOServer (8000, channel, null);
server.setLogger (logger, "server");
server.addISORequestListener(new ServerIso());
new Thread (server).start ();
}
@Override
public boolean process(ISOSource source, ISOMsg m) {
try {
System.out.println("server get data");
m.setResponseMTI ();
m.set (39, "00");
source.send (m);
} catch (ISOException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
  }
  return true;
}
}


Log at Client Side
<log realm="Q2.system" at="2017-05-17T14:59:40.892">
  <info>
    Q2 started, deployDir=C:\Users\Acer\workspace\ClientISOQ2\deploy
  </info>
</log>
<log realm="Q2.system" at="2017-05-17T14:59:42.049" lifespan="1127ms">
  <version>
    jPOS 2.1.0-SNAPSHOT master/07c4c14 (2017-05-14 01:19:30 UTC) 

-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

jPOS Community Edition, licensed under GNU AGPL v3.0.
This software is probably not suitable for commercial use.
Please see http://jpos.org/license for details.

-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.9 (Darwin)

iQEcBAEBAgAGBQJMolHDAAoJEOQyeO71nYtFv74H/3OgehDGEy1VXp2U3/GcAobg
HH2eZjPUz53r38ARPiU3pzm9LwDa3WZgJJaa/b9VrJwKvbPwe9+0kY3gScDE1skT
ladHt+KHHmGQArEutkzHlpZa73RbroFEIa1qmN6MaDEHGoxZqDh0Sv2cpvOaVYGO
St8ZaddLBPC17bSjAPWo9sWbvL7FgPFOHhnPmbeux8SLtnfWxXWsgo5hLBanKmO1
1z+I/w/6DL6ZYZU6bAJUk+eyVVImJqw0x3IEElI07Nh9MC6BA4iJ77ejobj8HI2r
q9ulRPEqH9NR79619lNKVUkE206dVlXo7xHmJS1QZy5v/GT66xBxyDVfTduPFXk=
=oP+v
-----END PGP SIGNATURE-----

  </version>
</log>
<log realm="Q2.system" at="2017-05-17T14:59:42.080" lifespan="18ms">
  <info>
    deploy: C:\Users\Acer\workspace\ClientISOQ2\Deploy\10_channel_jpos.xml
  </info>
</log>
<log realm="Q2.system" at="2017-05-17T14:59:42.119" lifespan="37ms">
  <info>
    deploy: C:\Users\Acer\workspace\ClientISOQ2\Deploy\20_mux.xml
  </info>
</log>
<log realm="Q2.system" at="2017-05-17T14:59:42.132" lifespan="11ms">
  <info>
    deploy: C:\Users\Acer\workspace\ClientISOQ2\Deploy\99_sysmon.xml
  </info>
</log>
<log realm="org.jpos.q2.qbean.SystemMonitor" at="2017-05-17T14:59:42.187">
  <info>
    Starting SystemMonitor
  </info>
</log>
<log realm="org.jpos.q2.qbean.SystemMonitor" at="2017-05-17T14:59:42.191">
  <info>
               OS: Windows 7 (6.1)
     process name: 6888@temp33rd-meldri
             host: temp33rd-meldri/192.168.43.215
              cwd: C:\Users\Acer\workspace\ClientISOQ2
       free space: 30.6 GiB
          version: 2.1.0-SNAPSHOT (07c4c14)
         instance: 706a3702-9e36-43c1-a304-785f0e312c24
           uptime: 00:00:02.798 (-1.000000)
       processors: 2
           drift : 0
    memory(t/u/f): 15/9/5
         encoding: windows-1252
         timezone: Asia/Bangkok (Indochina Time) +07:00
    watch service: sun.nio.fs.WindowsWatchService
            clock: 1495007982 2017-05-17T07:59:42.211Z
     thread count: 12
     peak threads: 12
     user threads: 8
            Thread[Reference Handler,10,system]
            Thread[Finalizer,8,system]
            Thread[Signal Dispatcher,9,system]
            Thread[Attach Listener,5,system]
            Thread[main,5,main]
            Thread[pool-1-thread-1,5,main]
            Thread[Q2-706a3702-9e36-43c1-a304-785f0e312c24,5,main]
            Thread[Thread-1,5,main]
            Thread[Timer-0,5,main]
            Thread[channel-sender-jpos-send,5,main]
            Thread[channel-receiver-jpos-receive,5,main]
            Thread[SystemMonitor,5,main]
    name-registrar:
      tspace:default: org.jpos.space.TSpace
         key-count: 0
            gcinfo: 0,0
      Q2: org.jpos.q2.Q2
      jpos-channel: org.jpos.q2.iso.ChannelAdaptor
        tx=0, rx=0, connects=0, last=0
      channel.jpos-channel: org.jpos.iso.channel.XMLChannel
      logger.Q2: org.jpos.util.Logger
      mux.mymux: org.jpos.q2.iso.QMUX
        tx=0, rx=0, tx_expired=0, tx_pending=0, rx_expired=0, rx_pending=0, rx_unhandled=0, rx_forwarded=0, connected=false, last=0
      logger.Q2.buffered: org.jpos.util.BufferedLogListener
  </info>
</log>
<log realm="ServerA-Channel/127.0.0.1:8000" at="2017-05-17T14:59:42.396" lifespan="210ms">
  <connect>
    Try 0 localhost:8000
  </connect>
</log>
<log realm="ServerA-Channel/127.0.0.1:8000" at="2017-05-17T14:59:45.371" lifespan="2ms">
  <send>
    <isomsg>
      <!-- org.jpos.iso.packager.XMLPackager -->
      <field id="0" value="0800"/>
      <field id="11" value="985366"/>
      <field id="41" value="12345678"/>
      <field id="70" value="301"/>
    </isomsg>
  </send>
</log>
<log realm="ServerA-Channel/127.0.0.1:8000" at="2017-05-17T14:59:45.431" lifespan="3031ms">
  <receive>
    <isomsg direction="incoming">
      <!-- org.jpos.iso.packager.XMLPackager -->
      <field id="0" value="0810"/>
      <field id="11" value="985366"/>
      <field id="39" value="00"/>
      <field id="41" value="12345678"/>
      <field id="70" value="301"/>
    </isomsg>
  </receive>
</log>


Log at Server Side
<log realm="server" at="2017-05-17T14:59:34.645" lifespan="1ms">
  <iso-server>
    listening on port 8000
  </iso-server>
</log>
<log realm="server.session/127.0.0.1:4869" at="2017-05-17T14:59:42.201">
  <session-start/>
</log>
<log realm="channel/127.0.0.1:4869" at="2017-05-17T14:59:45.394" lifespan="3192ms">
  <receive>
    <isomsg direction="incoming">
      <!-- org.jpos.iso.packager.XMLPackager -->
      <field id="0" value="0800"/>
      <field id="11" value="985366"/>
      <field id="41" value="12345678"/>
      <field id="70" value="301"/>
    </isomsg>
  </receive>
</log>
server get data
<log realm="channel/127.0.0.1:4869" at="2017-05-17T14:59:45.427" lifespan="2ms">
  <send>
    <isomsg>
      <!-- org.jpos.iso.packager.XMLPackager -->
      <field id="0" value="0810"/>
      <field id="11" value="985366"/>
      <field id="39" value="00"/>
      <field id="41" value="12345678"/>
      <field id="70" value="301"/>
    </isomsg>
  </send>
</log>

Did i do something wrong? or it was best practice?
Thank you.

Regards,
Meldri

Andrés Alcarraz

unread,
May 17, 2017, 6:43:33 AM5/17/17
to jpos-...@googlegroups.com

Hi Meldri, I can point you to a couple of things I think that are not best practices.

First of all Q2 is here to make your live easier, so you don't need to start it in your main class, but the other way around. So the idea is that Q2 starts all of the components and you just need to point it to the deploy directory. In your client the best practice would be that it was a QBean the responsible to fire up messages, but as a proof of concept if you are merely trying to test your server is a good starting point.

On a second but most important thing is your server, there you have something wrong, or at least unnecessary code, I don't know how you are starting it, but if you are starting it by the main entry point of ypour ServerISO class you are not using Q2 at all, and the server xml is not being referenced anywhere. On the other hand if you are starting the project by calling Q2 all the code in the main is never called. Any way in both cases you are defining the server, channel and packager twice, one by code in your class and another in the xml. Point is the idea of Q2 is to use reusable components (called QBeans) that do a lot of work for you by reading the xml file descriptors. In this case the QBean Qserver defined in your server.xml would instantiate the packager, channel and ISOServer so that you don't need o do it youself.

You just have to worry about writing the RequestListener implementation, that is your process method. Q2 and Qserver are the ones that will instantiate a logger,, server and the rest of the needed objects and wire them up.

I hope I'm pointing you in the right direction.

Best regards.

Andrés

P.S. I wonder how you got there starting from the jpos gateway tutorial since the approach seams very different to me.
El 17/05/17 a las 05:10, Meldri Asan escribió:
--
--
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 Google Groups "jPOS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jpos-users+...@googlegroups.com.
To post to this group, send email to jpos-...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/jpos-users/01586e9a-aa61-46eb-b425-62f3bb036dcb%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Meldri Asan

unread,
May 17, 2017, 10:16:11 PM5/17/17
to jPOS Users
Hi Andrés ,

Thanks for the advice, but i still confused at some point.

First of all Q2 is here to make your live easier, so you don't need to start it in your main class, but the other way around. So the idea is that Q2 starts all of the components and you just need to point it to the deploy directory.
If i don't need start Q2 in main class, then how run Q2 in client side? 

In your client the best practice would be that it was a QBean the responsible to fire up messages, but as a proof of concept if you are merely trying to test your server is a good starting point
What is mean of  QBean the responsible to fire up messages? i didn't get it.

On the other hand if you are starting the project by calling Q2 all the code in the main is never called. Any way in both cases you are defining the server, channel and packager twice, one by code in your class and another in the xml. Point is the idea of Q2 is to use reusable components (called QBeans) that do a lot of work for you by reading the xml file descriptors. In this case the QBean Qserver defined in your server.xml would instantiate the packager, channel and ISOServer so that you don't need o do it youself.
i already re-write my ServerIso.java code into this
public class ServerIso implements ISORequestListener{
public static void main(String[] args) throws IOException, ISOException {
Q2 q2 = new Q2();
q2.start();
}
@Override
public boolean process(ISOSource source, ISOMsg m) {
try {
System.out.println("server get data");
m.setResponseMTI ();
m.set (38, "11");
m.set (39, "00");
source.send (m);
} catch (ISOException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
  }
  return true;
}
}

is this what you mean define server at Q2? i already run this code and it work properly. This time, Server get configuration from 50_xml_server.xml.


P.S. I wonder how you got there starting from the jpos gateway tutorial since the approach seams very different to me.
 I just want make a simulator between client and server. How client and server communicate each other, but client and server must at different place. With some tutorial from google and jpos gateaway. I develop this code. No
 wonder if you feel it seems different.

Thanks.
Meldri 

Alejandro Revilla

unread,
May 17, 2017, 10:22:59 PM5/17/17
to jPOS Users


--
--
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 Google Groups "jPOS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jpos-users+unsubscribe@googlegroups.com.

To post to this group, send email to jpos-...@googlegroups.com.

Meldri Asan

unread,
May 18, 2017, 9:53:48 PM5/18/17
to jPOS Users
Thank Alejandro for the advice.

Regards,
Meldri

Barzilai Spinak

unread,
May 20, 2017, 2:14:50 PM5/20/17
to jpos-...@googlegroups.com
First, I couldn't notice what you deemed as "wrong" in your original logs.
I saw a message being sent form the client, the message being received in the server, a response being sent from the server, and the response being received in the client...

What Andrés was trying to say is that you don't need that main() method in ServerIso creating the Q2 object explicitly.

You just start the bin/q2 launch script, which will instantiate and run the Q2 class.
Q2 will read your deploy directory and it will deploy whatever is configured in the xml files (such as 50_server.xml)
So it will create an instance of QServer, and an XMLChannel, and an XMLPackager, and an ServerIso (acting as a request listener) and will connect all of them in the correct way.

As for the client, what you did works because you need someone to trigger the sending of the messages

Barzilai
--
--
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 Google Groups "jPOS Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to jpos-users+...@googlegroups.com.
To post to this group, send email to jpos-...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.


-- 
Barzilai Spinak
Transactility, Inc.
www.transactility.com
"Commercial licensing and support for the jPOS.org project"
Message has been deleted

Meldri Asan

unread,
May 22, 2017, 12:00:19 AM5/22/17
to jPOS Users
Hi Barzilai,
 
You just start the bin/q2 launch script, which will instantiate and run the Q2 class.
Q2 will read your deploy directory and it will deploy whatever is configured in the xml files (such as 50_server.xml)
So it will create an instance of QServer, and an XMLChannel, and an XMLPackager, and an ServerIso (acting as a request listener) and will connect all of them in the correct way.

If i do that, i got some error. Class not found and couldnt load MBean at ServerIso.java

Caused by: java.lang.ClassNotFoundException: com.server.iso.IncomingListener
        at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:348)
        at com.sun.jmx.mbeanserver.MBeanInstantiator.loadClass(MBeanInstantiator
.java:649)
        ... 31 more
      </nested-exception>
      org.jpos.core.ConfigurationException: com.server.iso.IncomingListener (jav
ax.management.ReflectionException: The MBean class could not be loaded)

So, i didn't execute this file using bin\q2 launch script. As alternative, i use q2.start() at main class ServerIso.java.
How q2 can recognize my own java class?
 
Reply all
Reply to author
Forward
0 new messages