G'day,

While working with payment processors I came across a dilemma that must have
been solved before so here I am. Let's say there's a 3rd party payment
processing component (stateless session bean for the sake of this example)
that participates in a transaction. This component sends XML messages over
HTTP to the bank and the bank replies back in XML.

If a method called on the payment bean completes successfully but another
method called later in the same transaction fails and throws a system
exception, the application has make sure the owner's account balance is not
affected.

The best way to do this would be to make another call to the payment bean
using the amount in the failed transaction but with the opposite sign. In
banking, this is usually referred to as a 'reversal adjustment' -- you don't
delete an incorrect entry, you merely credit the account and post another
entry. (In my hypothetical example above posting another entry is not
necessary). This is also a classic example of 'undo' (Command design
pattern).

Alternatives: 1) Make sure the payment is the last step in the transaction
(lame!) 2) Do authorization and settlement separately (ok but more hassle)
3) Delegate the responsibility to operations (if the customer calls about
his bill, credit the account manually)

The $64,000 question: how do I write an 'undo' in the context of a
transaction? I want the entire transaction to fail if the payment bean
throws an exception but I also want the application to request an undo if
the steps following the payment processing fail.

An answer that I am not happy with: use try/catch at the top level (calling
component), catch the exception and request an undo. The problem with this
approach is that if the payment is encapsulated in the method that activates
the service this payment is supposed to be for then interfaces have to be
modified to expose the payment details (good: via Command, bad: via a
parameter, ugly: directly).

Before: ISPCustomer.startService(Service s), ISPMerchant.buyGoods(Goods g),
ISPPartner.startRelationship(Contract c)

After: ISPCustomer.startService(Service s, Command c) or
startService(Service s, boolean undo) or startService(Service s) and
undoStartService(Service s)

An answer that I want but can't find in the spec (1.1 or 2.0): the component
is allowed to register a custom rollback mechanism (factory, Method
instance, whatever) with the container that will then be called if the
transaction fails. Seems to me this would be a very useful feature...does it
not exist in some form?

Alex Smith
Insight LLC
_________________________________________________________________
Get your FREE download of MSN Explorer at http://explorer.msn.com

===========================================================================
To unsubscribe, send email to [EMAIL PROTECTED] and include in the body
of the message "signoff EJB-INTEREST".  For general help, send email to
[EMAIL PROTECTED] and include in the body of the message "help".

Reply via email to