Skip to main content

Transactions. Part 1: Intent?

A lot has been written about transactions, a lot I read. Yet here is some more that I am planning to write in context to what we face in real life situations while developing enterprise applications. A few of the forthcoming posts will be dedicated to transactions before I start moving into other pain areas that we developers face in actual development situations.

To start with, let's consider what Transaction is. Out of the book, it is defined as a unit of work that either completes or fails. Try digging deeper and it starts getting all confusing with isolation levels, ACID concepts and lot more. But here we shall not rewrite what is already present in a lot of documentation.

What we shall deal with today, is the intent of transactions. Why do we have to consider transactions in the first place? Understanding that is imperative for developers to correctly identify "transaction boundaries" when it comes to real implementation.

Any piece of code executes as an interaction between modules, systems or methods.
While talking transactions here are the questions that a developer shall ask oneself to correctly understand whether he needs one or not, while writing code and where to start and end it.

a. Is the interaction going to persist some information into a persistent storage? Storage can be but is not limited to databases. We can define transaction boundary during reads too, but developers should use discretion while doing so. If parts of application just read data but does not decide to update or insert new data based on what it reads, it can live without transactions for reads. Believe me, there are lot of such scenarios in real life, no matter what gurus may say.

b. What happens if the storage of that data fails? If it does not matter, such as in the case of a user submitting a tweet, the developer can just save precious processing time by staying away from transactions. This is a major reason for Twitter should store tweets in Cassandra, but that shall be a different topic for another day. (Imp: Twitter is not using C* for storing tweets, but for geolocation and analytics but that's something only twitter knows. C* is a good fit for tweets, if it fails the user may just click again. He won't even know)

c. Where does the interaction starts storing data and where exactly does it end? If there are multiple pieces of data being stored, what all data is related that needs to be stored "together". That's the unit of work and right where we start storing it and where we end storing all pieces, defines our transaction boundary.

It is extremely useful to understand transaction boundaries of an application to efficiently implement and use transactional capabilities in enterprise applications. A lot of enterprise applications end up running entire processing logic within container transactions while a very small part of that code would actually be performing any real "transactions". That leads to unnecessary waste of precious system resources and processing time.




Comments

Popular posts from this blog

Catch hold of that Exception and hide that stacktrace!!!

E xceptions happen!!! Rules are to be followed, too. Time and again, Java developers are told the golden rule to catch specific exceptions and not to catch the generic Exception. The thought process behind that is, applications should not catch runtime exceptions. This is apt as runtime exceptions are an indicator of "bugs" in the code. However, blindly following rules, as always, can have unexpected consequences. If you are developing services that are to be exposed over the wire, it is always a good idea to break this rule and "catch that Exception". Instead, follow the below principles: Service methods should implement a generic Exception block, along with catching declared exceptions, thrown from inner layers of the code.  If needed, the service can throw another exception back to the client. What's important is that we create a new Exception instance to be thrown, along with relevant message for the client. The service can log stacktrace for the E...

Using JNDI managed JMS objects with Apache CAMEL

Apache CAMEL uses Spring JMS to work with JMS Queues or Topics. Evidently, we will need Spring to configure and use JMS capabilities provided by CAMEL. Details about how to implement JMS based routes using Apache CAMEL can be found in the CAMEL documentation. However, the documentation leaves a lot to be figured out. In a typical Java EE container, it is usually a good idea to abstract the underlying JMS resources by using JNDI. We can use the below configuration to achieve that. This configuration is tested in Websphere environment, but should work in any JEE container. Create a JMS queue connection factory in the JNDI registry. CAMEL configuration will be able to use only one queue connection factory, even if we have more than one. Create one or more JMS queue or topics, in the JNDI registry, as required. The above two steps are related to generic JNDI configuration for JMS resources. Now we come to the setup required for making these JMS resources work with CAMEL rout...

Cassandra data modelling: Redundant data, a tough decision

The biggest challenge around building an efficient data model for Cassandra is data redundancy. Though the basic rules for data modelling with Cassandra, mention the usual RDBMS modelling goals, as non goals for Cassandra (Refer:  Basic rules for C* data modelling ), it builds upon assumptions that clusters are built on commodity hardware, storage is cheap, and as data needs increase more nodes can be added to the cluster incurring very low cost. But in real life we are faced with technical as well as non technical problems. a. Keeping multiple column families in sync can be a major overhead, if the same data is spread across them. What if writes to some CF succeed and some fail? How long and how much will we retry? b. Horizontal scalability may be a truth, but think of a mundane question of where to keep all those heat producing, energy guzzling machines? So how do we model the database that does not allow joins without redundancy? The simple answer is, we do not. Wh...