Threads, Channels, ISOServers and Sessions: Design issue

98 views
Skip to first unread message

Jonathan

unread,
Oct 16, 2009, 9:20:35 AM10/16/09
to jPOS Users
Hi,
I'm writing an ATM Controller, and my ISOServer accepts connections
from ATMs, creating a Session for each ATM that connects. The Session
then does the usual loop: receive message, send it to the
RequestListener, and normally, send ack a response message. However,
sometimes, I want to send messages to the ATM that are not responses,
e.g. Go in/out of Service, or Get ATM Status.

What's the right approach for this? Should I have separate threads
receiving and sending on the channel? After drawing a state diagram,
it looks as if I need my own sub-classed Session run() method, created
by an overridden ISOServer.createSession() method.

Does this make sense, or am I missing something obvious?
Thanks,
Jonathan O'Connor

Mark Salter

unread,
Oct 16, 2009, 9:56:51 AM10/16/09
to jpos-...@googlegroups.com
Jonathan wrote:
> Hi,
> I'm writing an ATM Controller, and my ISOServer accepts connections
> from ATMs, creating a Session for each ATM that connects. The Session
> then does the usual loop: receive message, send it to the
> RequestListener, and normally, send ack a response message. However,
> sometimes, I want to send messages to the ATM that are not responses,
> e.g. Go in/out of Service, or Get ATM Status.
>
> What's the right approach for this? Should I have separate threads
> receiving and sending on the channel? After drawing a state diagram,
> it looks as if I need my own sub-classed Session run() method, created
> by an overridden ISOServer.createSession() method.
The right approach is to a greater degree going to be dictated by the
devices themselves.

>
> Does this make sense, or am I missing something obvious?

So you are allowed to make additional use of the connection the device
initiates to send instructions? If so, can you use the ISOSource given
to your RequestListener to send out instructions ahead of (or
immediately after) sending the response?

Reusing the inbound connection would mean the device needing to be able
to accept/handle messages coming out of your system which were not
responses to it's request.

Perhaps the response (to the request) can incorporate instructions?


--
Mark

Jonathan

unread,
Oct 16, 2009, 10:03:32 AM10/16/09
to jPOS Users
Hi,
further to this discussion, it is not so easy to create useful
ISOServers because most of the attributes in ISOServer are package
private. What I did was create MyISOServer class, with its own
createSession method. I copied the MySession.run() from Session.run(),
and unfortunately it is impossible (without reflection) to access the
listeners, the lastTxn timer, and ignoreISOExceptions.

Would it harm anyone if I made these attributes protected?

@Alejandro: I know that many classes can be subclassed, and the
reasons for doing this are given in the guide. But, as far as I can
see, ISOServer has no such advice. I'll add it to the Wiki when I
figure it all out myself. You might want to then include it in the
Guide.
Jonathan O'Connor

Jonathan

unread,
Oct 16, 2009, 10:14:26 AM10/16/09
to jPOS Users
Mark,

On Oct 16, 2:56 pm, Mark Salter <marksal...@talktalk.net> wrote:
> Jonathan wrote:
> > Hi,
> > I'm writing an ATM Controller, and my ISOServer accepts connections
> > from ATMs, creating a Session for each ATM that connects. The Session
> > then does the usual loop: receive message, send it to the
> > RequestListener, and normally, send ack a response message. However,
> > sometimes, I want to send messages to the ATM that are not responses,
> > e.g. Go in/out of Service, or Get ATM Status.
>
> > What's the right approach for this? Should I have separate threads
> > receiving and sending on the channel? After drawing a state diagram,
> > it looks as if I need my own sub-classed Session run() method, created
> > by an overridden ISOServer.createSession() method.
>
> The right approach is to a greater degree going to be dictated by the
> devices themselves.
>
>
>
> > Does this make sense, or am I missing something obvious?
>
> So you are allowed to make additional use of the connection the device
> initiates to send instructions?  If so, can you use the ISOSource given
> to your RequestListener to send out instructions ahead of (or
> immediately after) sending the response?
Yes, I suppose I could do many ISOSource.sends back, but then these
sends generate their own response from the ATM, so I then have to
solve a MUX-type problem matching response to request. I presume that
the order of the responses will be the same as the order of the
requests, although the ATM could generate some of its own unsolicited
messages, as well as Transaction requests.

>
> Reusing the inbound connection would mean the device needing to be able
> to accept/handle messages coming out of your system which were not
> responses to it's request.
The only connection to the ATM I can use is this inbound connection,
so I don't have any choice.

>
> Perhaps the response (to the request) can incorporate instructions?
No the response in general, can't have nested instructions in it.

I think I'll try the simple approach of sending any extra messages
after my response, and I'll see how far that gets me.

Thanks,
Jonathan

Mark Salter

unread,
Oct 16, 2009, 10:31:42 AM10/16/09
to jpos-...@googlegroups.com
Jonathan wrote:
> Yes, I suppose I could do many ISOSource.sends back, but then these
> sends generate their own response from the ATM, so I then have to
> solve a MUX-type problem matching response to request. I presume that
> the order of the responses will be the same as the order of the
> requests, although the ATM could generate some of its own unsolicited
> messages, as well as Transaction requests.

They would all pass through your ISORequestListener, so you get the
chance to do this needed matching. I don't think you can do anything
like spawning a mux for each connection, this could cause a conflict on
the channel.receive.

I do like the thought of a pool of atm connections - named per device
made available via a space, a pool of ChannelAdaptors perhaps?

>
>> Reusing the inbound connection would mean the device needing to be able
>> to accept/handle messages coming out of your system which were not
>> responses to it's request.
> The only connection to the ATM I can use is this inbound connection,
> so I don't have any choice.

Ok.

>
>> Perhaps the response (to the request) can incorporate instructions?
> No the response in general, can't have nested instructions in it.

Ok, two down, one to go 8).

>
> I think I'll try the simple approach of sending any extra messages
> after my response, and I'll see how far that gets me.

Is the inbound connection long lived, or does the ATM disconnect after
getting it's response?

I would probably try sending detail ahead of the response first, but
might also try and locate the manual for the ATM devices - which I think
should provide a 'how-to' for the exchange protocol you are after.

8)


--
Mark

Alejandro Revilla

unread,
Oct 16, 2009, 11:04:58 AM10/16/09
to jpos-...@googlegroups.com
I don't have any problem changing that to protected, go ahead at your convenience.

Just curious, are you go-in-service messages ISO-8583 or they use proprietary protocols?

In my implementation of an ATM server I ended up creating my own server tied to a finite state machine implementation.

Jonathan

unread,
Oct 16, 2009, 11:35:02 AM10/16/09
to jPOS Users
Mark,
the inbound connection is long-lived. Luckily, I have 2 manuals, a
guide and a reference manual, that are fairly comprehensive.
The devil, as they say, is in the details!
Ciao,
Jonathan

Jonathan

unread,
Oct 16, 2009, 11:37:07 AM10/16/09
to jPOS Users
Alejandro,
My ATMs speak NDC+, hence my previous questions about FSDMsg.

As to writing my own server, I may end up doing that, but I'm trying
to use Q2 and jPos as much as possible. As the Borg say, "RESISTANCE
IS FUTILE" :-)
Ciao,
Jonathan

On Oct 16, 4:04 pm, Alejandro Revilla <a...@jpos.org> wrote:
> I don't have any problem changing that to protected, go ahead at your
> convenience.
>
> Just curious, are you go-in-service messages ISO-8583 or they use
> proprietary protocols?
>
> In my implementation of an ATM server I ended up creating my own server tied
> to a finite state machine implementation.
>

chhil

unread,
Oct 16, 2009, 11:37:50 AM10/16/09
to jpos-...@googlegroups.com
The sending of commands to the atm by the controller is independent
of the requests the controller receives so piggy backing is not a good
idea.

-chhil

Mark Salter

unread,
Oct 16, 2009, 12:06:15 PM10/16/09
to jpos-...@googlegroups.com
chhil wrote:
> The sending of commands to the atm by the controller is independent
> of the requests the controller receives so piggy backing is not a good
> idea.
Thanks Chhil.

I was only wondering if such an exchange might be possible.

Supporting the addition of commands to a response seemed like a nice
idea, until Jonathan indicated that responses were required.

(Which would mean piggy backing responses onto any new request.)

It might work, but would be messy and hardly real-time.

Please forget I even suggested such a thing.

;?)

--
Mark

chhil

unread,
Oct 16, 2009, 12:08:34 PM10/16/09
to jpos-...@googlegroups.com
Just adding my few cents in lower case alphabets :-)

Aissa.Slimani

unread,
Oct 16, 2009, 12:18:19 PM10/16/09
to jpos-...@googlegroups.com
Jonathan,

I think u should create a separate thread that handle the Service Messages
(Go In service, Out of service, Send Config...) using the same channel of
your Server. Responses got from the ATM should come to the same
RequestListener that handles the TransactionRequests, as the response itself
will be a Solicited Message (ready most of cases) you should manage
different cases by a TransactionManager for example.

Does it make sens?

-----Message d'origine-----
De : jpos-...@googlegroups.com [mailto:jpos-...@googlegroups.com] De la
part de Jonathan
Envoyé : vendredi 16 octobre 2009 15:37
À : jPOS Users
Objet : [jpos-users] Re: Threads, Channels, ISOServers and Sessions: Design
issue

Alejandro Revilla

unread,
Oct 16, 2009, 12:38:01 PM10/16/09
to jpos-...@googlegroups.com
Well... my server is a Q2 citizen and so is the FSM implementation.

Jonathan

unread,
Oct 16, 2009, 1:04:41 PM10/16/09
to jPOS Users
Aissa,
I'll have to check the thread safeness of the channel and underlying
socket implementations.

I already wrote a message interceptor that has a reading and writing
thread per channel. There were two channels, one from the host to the
interceptor, and one from the interceptor to the ATM. The receiving
thread of the host to interceptor channel put its message on a queue,
and the sending thread of the interceptor to ATM took this message and
sent it on to the ATM. The communications in the other direction
worked similarly.

The difficulty with that code (admittedly, throw-away) was the making
and breaking the connections was error prone.
So, that's why I wanted to take advantage of the ISOServer code to
make the connections more resilient.

I'll let everyone know what I get working in the end.

Ciao,
Jonathan

Aissa.Slimani

unread,
Oct 16, 2009, 1:46:52 PM10/16/09
to jpos-...@googlegroups.com
Your communication HOST/Interceptor is ISO based? do you have only 1 HOST or
multi-clients as HOST?


+---------+ +---------+
| | | |
| ISO | | |
| SERVER | | |
| (ATM) | | |
+---------+ +---------+
-----Message d'origine-----
De : jpos-...@googlegroups.com [mailto:jpos-...@googlegroups.com] De la
part de Jonathan
Envoyé : vendredi 16 octobre 2009 17:05

Alan Honczar

unread,
Oct 16, 2009, 6:06:27 PM10/16/09
to jpos-...@googlegroups.com
Hi, I hope you do not mind if I join this thread...
I'd like to contribute and also test my knowledge about the components...
 
As I know, The ISOServer creates Sessions as requests arrives in form of connections.
Those Sessions receives the Channel from ISOServer in creation time.
This Channel holds communication to specific Client.
Each Session will run in specific thread from ThreadPool.
Session is designed to keep the channel alive until your RequestListener or the Client not stop the channel.
 
So, as I understand, we can use ISOServer/Sessions to hold transient or persistent connections.
 
Transient connections are the most easy.
Persistent connections are a little bit more complicated.
 
I could not understand wich approach is better for you, but I believe that if you can hold the channel you can make any use of it without touching ISOServer/Session code.
 
If your communication to the ATM is sequential, you are free to send()/receive() the many times you want.
If your communication is not sequential, you may attach a MUX (reverse mux) to that channel and flow messages in server->client direction too.
 
Transaction Manager is new for me, but I think it may be bound somewhere...
I do not know how much I lied to you, but I expect comments.... :^)
 
wish you luck.
Alan
2009/10/16 Aissa.Slimani <aissa....@gmail.com>

Alejandro Revilla

unread,
Oct 17, 2009, 5:18:57 PM10/17/09
to jpos-...@googlegroups.com
I wonder if it could help if we add support for a ConnectionListener at the ISOServer level, i.e:

  public interface ConnectionListener {
       public void connected (ISOSource source);
       public void disconnected (ISOSource source);
  }

Jonathan

unread,
Oct 22, 2009, 4:43:19 AM10/22/09
to jPOS Users
Alejandro,
the connection listener interface might well help. especially
registering Channel objects and associating them with specific LUNOs
(ATM ids).

Anyway, I finally got the finger out, and wrote some code, and am now
testing this. <rant>It is so hard to write automated tests for this
code. JUnit has no support for creating threads, or routing assert
failures to a TestRunner. </rant>

Anyway, I have defined 2 ISOServers. One for the ATM connections, and
one for the Client connections. The client connects to the Client
ISOServer, and sends a message. The message has the LUNO inside it, so
I know which ATM should get the message. All the ATM Channels are
registered in the NameRegistrar with their matching LUNO. Calling
BaseChannel.send() is thread safe because the channel writing is
synchronized. The ATM Channel has a queue of Conversations which are
similar to Future<ISOMsg>. When the client sends a message, it also
creates a new Conversation object on the channel queue. This solves
the MUX problem between Client and ATM.

The ATMRequestListener knows that only one sort of message coming from
the ATM is a response to messages from the client. When that happens,
the ATM Channel gets the head conversation, and sets its reply object
and returns. Setting the reply object wakes up the client thread and
returns the reply message.

If the ATMRequestListener gets an unsolicited message from the ATM,
then that goes to a configurable dispatcher, that processes the
message, and sends back a reply message (if needed).
Ciao,
Jonathan

chhil

unread,
Oct 22, 2009, 4:56:58 AM10/22/09
to jpos-...@googlegroups.com
Good stuff Jonathan.

just an FYI

We have never relied on lunos as  think its optional (I could be wrong dont have a spec in front of me).

We differentiate atms based on ip or ip,port for leased lines ATMs and terminal ids for dialup.
IP: When we have direct connections from the atm.
IP,Port: When the Atms connect to a box (like Inetco) and traffic comes to us from a single IP but we differentiate based on the local port the connection comes from.

-chhil

Jonathan

unread,
Oct 22, 2009, 7:13:02 AM10/22/09
to jPOS Users
Chhil,
yes, I did think about that. There are 3 ways an ATM can be
identified: a LUNO set in the ATM local configuration, a fixed IP
address set by the network, or a specific incoming port. I think all
of them require an operator to physically interact with the ATM before
putting into production. It looks like I will have to extend my code
that finds a channel.
Thanks,
Jonathan

On Oct 22, 9:56 am, chhil <chil...@gmail.com> wrote:
> Good stuff Jonathan.
> just an FYI
>
> We have never relied on lunos as think its optional (I could be wrong dont
> have a spec in front of me).
>
> We differentiate atms based on ip or ip,port for leased lines ATMs and
> terminal ids for dialup.
> IP: When we have direct connections from the atm.
> IP,Port: When the Atms connect to a box (like Inetco) and traffic comes to
> us from a single IP but we differentiate based on the local port the
> connection comes from.
>
> -chhil
>

chhil

unread,
Oct 22, 2009, 7:33:09 AM10/22/09
to jpos-...@googlegroups.com
I see one problem with the LUNO approach..if a processor is running atms for multiple clients/banks you now need to worry about the uniqueness of terminal ids across various organizations. usally these terminal ids will be used to as keys for KWPs etc.



-chhil 
Reply all
Reply to author
Forward
0 new messages