11

architecture

We have three layers in our application. Service layer to provide an external API. BO layer for our business logic, and a DAO layer for our database connection.

Let's say every time we update a File, we also want to change something in the Folder, for example 'last modified date'. This needs to be done in a transaction. Either it succeeds and both File and Folder are edited. Or there's a failure and the transaction gets rolled back so both objects are in the previous state.

The "Edit a folder when a file get edited"-action is purely business logic. So this would mean it belongs in the BO-layer. However, we use Objectify for our Database, so to start a transaction we need to call ofy().transact(...). If we call this function in the BO layer, this breaks our design as there will be Database specific calls (Objectify) in our Business layer.

What would be a clean solution for this problem?

  • Can't FileBO call FolderBO.edit(newDate) because of the transaction problem ? – Spotted Oct 4 '16 at 9:03
  • does java not have an equvilant of c# TransactionScope? – Ewan Oct 4 '16 at 13:45
  • In Java, the transaction scope depends on the framework you use. In JEE it could be managed by the app server but usually is defined and managed declaratively vía Frameworks like Spring (vía annotations, xml, ...) – Laiv Oct 7 '16 at 5:11
  • Worry less about trying to make different "layers" of your application functionally independent/ignorant of each other. Embrace the idea that your code is built for the architecture it supports and instead focus on making that code well-composed with respect to itself. – Ant P Apr 22 '17 at 10:50
5

How you cut your transactions is indeed business logic. So let your DAO layer provide a db framework independent API for the transact method you mentioned (and probably for things like commit and rollback). Then you can use it from your BO layer without making it dependent from your database or your db framework.

4

Looks like Objectify is designed for atomic-like transactions (Google Application Engine Transactions). It will demand to you to develop your own abstraction of the Transaction Management.

In this case. the abstraction goes on How do I delegate the transaction management to upper layers?

@DocBrown approach looks to me the faster and cleaner solution to implement into to the given architecture (layered architecture).

Due to we miss too many info about the application and its context, Doc's solution also seems to me the safest.

However, I would suggest taking a look to UnitOfWork design pattern for the business layer. I think it suits with the transaction management purposed by Objectify.

Briefly summarised, the pattern aims to encapsulate business rules into Business Transactions (units of work). The pattern allows inheritance between B.Ts and so far I see, Objectify too. It even supports composition. So either by composition or inheritance, the approach allows complex B.Ts.

Applied to the given architecture, would look like:

FileService -> FileBO : new EditFileTransaction().execute()
                           |-> ofy().transact(...)
                           |--> FileDAO.actionA()
                           |--> FolderDAO.actionA()
                           |-> [ofy().commit(...)|ofy().rollback()]

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.