== Assembly Line

It's easier to understand the TM if we imagine an *assembly line*.

Here is an example of a typical transaction (in this case taken from
the jCard system):

The TransactionManager encourages and allows developers to write reusable
and configurable components called _Participants_. Here is a short
description of a typical Balance Inquiry transaction, splitted into many
small (easy to develop, easy to reuse, easy to maintain) participants:

.AssemblyLine
[cols="3,8", options="header"]
|===============
|Name|Description
|PrepareContext
|We prepare the context with some handy objects, such
 as a transaction +TIMESTAMP+, a +Profiler+ and optional
 user specific data required by all participants down
 the execution line.
|CheckVersion
|We usually receive messages using a specific version. In this case,
 jCard uses the link:http://jpos.org/doc/jPOS-CMF.pdf[jPOS-CMF] which
 has a specific field indicating the interchange version. This participant
 just check that and early aborts the transaction if it doesn't match our
 expectations
|Open
|If version is OK, we probably want to log the message in a database.
 The +Open+ participant gets a JDBC connection and starts a JDBC Transaction.
|Switch
|We'll explain later the +GroupSelectors+ that allows us to put together
 groups of participants in the XML configuration. In this example, the 
 selector returns a String with the following content:
    +"balanceinquiry prepareresponse logit close sendresponse"+
 indicating that the TM needs to execute the participants defined
 in those groups.
|CheckFields
|Different transactions require the presence of different ISO8583 fields
 in the incoming message. Some are mandatory, some are optional, this
 reusable participant takes care of that. For example, in the case of
 a balance inquiry, we want to make sure that we have fields that allows
 us to identify the card, transaction amount, etc.
|CreateTranLog
|If we reach this participant it means the incoming message is kinda OK,
 it has the proper version, it has the required mandatory fields, so we
 create a TranLog record. This is specific to jCard, but your implementation
 is likely to require some kind of transaction log record.
|CheckCard
|In order to compute the balance of a given account, we first need to locate
 the card. This involves getting the card by different means, could be track1
 data, track2 data, token, etc. The +CheckCard+ participant takes care of that,
 and will place a handy Card object in the Context using a well known constant
 name (in the case of jCard, that constant is called +CARD+ and is defined in
 the +org.jpos.ee.Constants+ interface, but you can define it elsewhere, probably 
 in an +enum+).
|CheckTerminal
|We need to check that the client terminal is valid, active, and perhaps check
 its capabilities in order to provide responses in different formats (i.e. for
 printing purposes)
|CheckAcquirer
|We need to know the acquirer, perhaps to validate fees involved in this
 transaction.
|SelectAccount
|We know the Card, so we know the CardHolder, depending on the transaction type
 and processing code, we may choose a different account (i.e. checking versus
 saving)
|ComputeBalances
|Now we know the account, so we compute its balances (available, accounting) 
 and place it in the Context
|PrepareResponse
|We have the balances in the Context in +BigDecimal+ objects under well
 known contant keys (i.e. +AVAILABLE_BALANCE+, +ACCOUNTING_BALANCE+), but
 we need to place those in the ISO8583 response, probably in field 54 (additional
 amounts).
|LogIt
|Remember we've created a +TranLog+ record in the +CreateTranLog+ participant above,
 now we need to pick some of the data we have been gathering in the Context and
 place it there, so that it gets persisted in a database row.
|Close
|Before we send a response, we need to commit the JDBC transaction and return the
 JDBC session to the pool.
|SendResponse
|Now we send the response back to the network
|ProtectDebugInfo
|The following participant (_Debug_) dumps the Context's content to the jPOS log,
 something very useful for debugging purposes, but there's some sensitive data
 in the Context, so this little participant take care of masking it.
|Debug
|Dumps the Context to the jPOS log.
|===============

Here is the sample log:

----------
     prepare: org.jpos.jcard.PrepareContext NO_JOIN
     prepare: org.jpos.jcard.CheckVersion READONLY NO_JOIN
     prepare: org.jpos.transaction.Open READONLY NO_JOIN
     prepare: org.jpos.jcard.Switch READONLY NO_JOIN
    selector: balanceinquiry prepareresponse logit close sendresponse
     prepare: org.jpos.jcard.CheckFields NO_JOIN
     prepare: org.jpos.jcard.CreateTranLog NO_JOIN
     prepare: org.jpos.jcard.CheckCard NO_JOIN
     prepare: org.jpos.jcard.CheckTerminal NO_JOIN
     prepare: org.jpos.jcard.CheckAcquirer NO_JOIN
     prepare: org.jpos.jcard.SelectAccount NO_JOIN
     prepare: org.jpos.jcard.ComputeBalances NO_JOIN
     prepare: org.jpos.jcard.PrepareResponse NO_JOIN
     prepare: org.jpos.jcard.LogIt READONLY NO_JOIN
     prepare: org.jpos.transaction.Close READONLY
     prepare: org.jpos.jcard.SendResponse READONLY
     prepare: org.jpos.jcard.ProtectDebugInfo READONLY
     prepare: org.jpos.transaction.Debug READONLY
      commit: org.jpos.transaction.Close
      commit: org.jpos.jcard.SendResponse
      commit: org.jpos.jcard.ProtectDebugInfo
      commit: org.jpos.transaction.Debug
----------

In a blue sky scenario like the previous one, the TM calls all participant's
`prepare` method, which return PREPARED, and then the `commit` method on
those that have joined the transaction (by not returning the `NO_JOIN`
modifier).

Here is a diagram for a situation where all participants return just `PREPARED`
(meaning they DO want to join the transaction, so commit gets called).

image:images/tm_prepared.png[width="400px",alt="PREPARED"]

When a participant adds the `NO_JOIN` modifier (by returning 
`PREPARED | NO_JOIN`), then the TM skips calling that participant's
`commit` method as shown in the following diagram.

image:images/tm_no_join.png[width="400px",alt="PREPARED | NO_JOIN"]

If a participant returns `ABORT`, then the TM calls the `abort` operation
in those participants already called that where `PREPARED` and did not return
the `NO_JOIN` modifier so that they can take corrective action if required.

image:images/tm_abort.png[width="400px",alt="ABORTED"]

