5 Replies Latest reply on Mar 27, 2015 9:24 AM by gytis

    Possible improvements to Compensations API

    gytis

      I'm posting here to discuss possible improvements to Compensations API to make it more usable in different cases.

       

      I think two items should be considered:

      • Exposing public API to register handlers. Currently the only supported way to register the handler is to use annotations. However, this is limited to having one handler per java method.
      • Providing a way to pass data to the specific handler. We have a way to store compensation scoped data. However, it is accessible by every handler. It would be beneficial to pass some specific data to the particular handler, e.g. updated mongo document, which might have to be compensated.

       

      I would appreciated any suggestions of other functionality that might be good to add and/or remove.

       

      Thanks,

      Gytis

        • 1. Re: Possible improvements to Compensations API
          tomjenkinson

          Gytis Trikleris wrote:

           

          Exposing public API to register handlers. Currently the only supported way to register the handler is to use annotations. However, this is limited to having one handler per java method.

           

          Good observation -  maybe this will be a less of an issue with https://docs.oracle.com/javase/tutorial/java/annotations/repeating.html

           

          I agree being able to set more than one behavior per business logic would be useful. Would these all execute in the same compensating transaction - I imagine they would.

           

          For JSE <8 we can either go the route of the public API (where would propose adding the method) or we could go down supporting @TxCompensate with a class[], e.g.:

          @TxCompensate(handlers={UndoCredit.class,UndoDebit.class})

           

          I rather prefer the public API as it might be nice to add handlers at runtime?

          • 2. Re: Possible improvements to Compensations API
            tomjenkinson

            Gytis Trikleris wrote:

             

             

            • Providing a way to pass data to the specific handler. We have a way to store compensation scoped data. However, it is accessible by every handler. It would be beneficial to pass some specific data to the particular handler, e.g. updated mongo document, which might have to be compensated.

             

            This also seems like a good idea. I guess at the moment you could do this with multiple javabeans that wrap smaller abouts of data.

             

            In the business logic:

            @Inject

            DocumentNameHolder documentNameHolder;

             

            The compensation scoped object

            @CompensationScoped

            public class DocumentNameHolder {

                public String documentName;

            }

             

            Maybe you could do something like.

             

            In the business logic:

            @CompensationScopedData(id="DocumentNameHolder")

            String documentName;

             

            Then refer to it in in the compensation handler:

            @CompensationScopedData(id="DocumentNameHolder")

            String documentName;


            That might be quite usable. At the moment the struct-like @CompensationScoped does seem like it could be a bit clunky.

            • 3. Re: Possible improvements to Compensations API
              gytis

              Repeatable @TxCompensate would certainly be useful.

               

               

              However, this wouldn't solve all the problems. Imagine scenario with mongo from the patent:

               

              @Compensatable

              @TxCompensate(SharedCompensationHandler.class)

              @TxConfirm(SharedConfirmationHandler.class)

              public void transferMoney(String fromAccount, String toAccount, Double amount) {

                  ...

                  accountsCollection.updateOne(debitUpdateFilter, debitDocument);

                  accountsCollection.updateOne(creditUpdateFilter, creditDocument);

                  ...

              }

               

               

              In this case you'd have to options. The one displayed is having one compensation/confirmation handler for both update operations. Or if the operations are more complicated you could move each operation to separate methods and assign separate handlers.

               

              However, with additional API this could be possible:

               

              @Compensatable

              public void transferMoney(String fromAccount, String toAccount, Double amount) {

                  ...

                  accountsCollection.updateOne(debitUpdateFilter, debitDocument);

                  compensations.addCompensationHandler(DebitCompensationHandler.class)

                  compensations.addCompensationHandler(DebitConfirmationHandler.class)

               

                  accountsCollection.updateOne(creditUpdateFilter, creditDocument);

                  compensations.addCompensationHandler(CreditCompensationHandler.class)

                  compensations.addCompensationHandler(CreditConfirmationHandler.class)

                  ...

              }

               

               

              Additionally, could be useful to pass same extra data to each add* method for that handler.

              • 4. Re: Possible improvements to Compensations API
                tomjenkinson

                Gytis Trikleris wrote:

                 

                Repeatable @TxCompensate would certainly be useful.

                 

                 

                However, this wouldn't solve all the problems. Imagine scenario with mongo from the patent:

                 

                @Compensatable

                @TxCompensate(SharedCompensationHandler.class)

                @TxConfirm(SharedConfirmationHandler.class)

                public void transferMoney(String fromAccount, String toAccount, Double amount) {

                    ...

                    accountsCollection.updateOne(debitUpdateFilter, debitDocument);

                    accountsCollection.updateOne(creditUpdateFilter, creditDocument);

                    ...

                }

                 

                 

                In this case you'd have to options. The one displayed is having one compensation/confirmation handler for both update operations. Or if the operations are more complicated you could move each operation to separate methods and assign separate handlers.

                 

                However, with additional API this could be possible:

                 

                @Compensatable

                public void transferMoney(String fromAccount, String toAccount, Double amount) {

                    ...

                    accountsCollection.updateOne(debitUpdateFilter, debitDocument);

                    compensations.addCompensationHandler(DebitCompensationHandler.class)

                    compensations.addCompensationHandler(DebitConfirmationHandler.class)

                 

                    accountsCollection.updateOne(creditUpdateFilter, creditDocument);

                    compensations.addCompensationHandler(CreditCompensationHandler.class)

                    compensations.addCompensationHandler(CreditConfirmationHandler.class)

                    ...

                }

                 

                 

                Additionally, could be useful to pass same extra data to each add* method for that handler.

                 

                Personally, I think you were right in that scenario to recommend moving the debit and crediting to separate business logics with separate handlers. But I an open  to adding via an API being useful in some circumstances.

                 

                As a side note, in your example above "accountsCollection" is not linked in any way to "compensations.addCompensationHandler(DebitCompensationHandler.class)" that I can see.

                • 5. Re: Possible improvements to Compensations API
                  gytis

                  I understand that in this case the best way to go would be to split the logic, but I wanted to make a simple example. Actually, we spoke about this splitting with paul.robinson a couple of weeks ago, maybe he'll contribute some ideas to here too.

                   

                  In the example accountsCollection is an instance of MongoCollection. However, debitDocument and creditDocument should be liked somehow with the respective handlers.