About Petri Kainulainen

Petri is passionate about software development and continuous improvement. He is specialized in software development with the Spring Framework and is the author of Spring Data book.

The Biggest Flaw of Spring Web Applications

The developers who are using Spring Framework in their applications are good to talk about the benefits of dependency injection. Unfortunately, they are not so good to leverage its benefits such as the single responsible principle and separation of concerns in their applications. If we take a look at any Spring powered web application, the odds are that the application is implemented by using these common and equally erroneous design principles:

  1. The domain model objects are used only to store the data of the application. In other words, the domain model follows the anemic domain model anti-pattern.
  2. The business logic lies in the service layer which manages the data of the domain objects.
  3. The service layer has one service class per each entity of the application.

The question is: If this is so common, how can it be wrong? Let’s find out.

Old Habits Die Hard

The reason why Spring web applications look this way is that this is the way things have always been done, and old habits die hard, especially if they are enforced by senior developers or software architects. The problem is that these people are very good at defending their opinions. One of their favourite arguments is that our application follows the separation of concerns principle because it has been divided into several layers and each layer has specific responsibilities.

A typical Spring web application has the following layers:

  • The web layer which is responsible of processing user’s input and returning the correct response back to the user. The web layer communicates only with the service layer.
  • The service layer which acts as a transaction boundary. It is also responsible of authorization and contains the business logic of our application. The service layer manages the domain model objects and communicates with other services and the repository layer.
  • The repository / data access layer which is responsible of communicating with the used data storage.

The separation of concerns principle is defined as follows:

Separation of concerns (Soc) is a design principle for separation a computer program into distinct sections, such that each section addresses a separate concern. Although it is true that a typical Spring web application follows this principle in some level, the reality is that the application has a monolithic service layer which has too many responsibilities. To be more specific, the service layer has two major problems:

First, the business logic of the application is found from the the service layer.

This is a problem because the business logic is scattered around the service layer. If we need to check how a certain business rule is implemented, we have to find it first. This might not be easy. Also, if the same business rule is needed in multiple service classes, the odds are that the rule is simply copied from one service to another. This leads into a maintenance nightmare.

Second, the service layer has one service class per each domain model class.

This violates the single responsibility principle which is defined as follows: The single responsibility principle states that every class should have a single responsibility, and that responsibility should be entirely encapsulated by the class. All its services should be narrowly aligned with that responsibility.

The service classes have a lot of dependencies and a lot of circular dependencies. The service layer of a typical Spring web application does not consist of loosely coupled services which have only one responsibility. It is a more like a net of tightly coupled and monolithic services. This makes is it hard to understand, maintain and reuse. This might sound a bit harsh but the service layer is often the most problematic part of a Spring web application. Luckily for us, all hope is not lost.

Breaking Free

The current situation is bad, but it is not totally hopeless. Let’s find out how we can break free from old habits.

First, we have to move the business logic of our application from the service layer to the domain model classes.

The reason why this make sense should be clear to us if we think of the following example:

Let’s assume that I am a service class and you are a domain model object. If a tell you to jump off from a roof, would you prefer to have a veto right to my decision?

Moving the business logic from the service layer to the domain model classes gives us three advantages:

  1. The responsibilities of our code are divided in a logical way. The service layer takes care of the application logic and our domain model classes takes care of the business logic.
  2. The business logic of our application is found from a single place. If we need to verify how a specific business rule is implemented, we always know where to look for.
  3. The source code of the service layer is cleaner and does not contain any copy paste code.

Second, we have to divide the entity specific services into smaller services which serves only a single purpose.

For example, if our application has a single service class which provides CRUD operations for persons and operations related to user accounts, we should divide it into two separate service classes:

  • The first service provides CRUD operations for persons.
  • The second service provides operations related to user accounts.

This gives us three big advantages:

  1. Each service class has a logical set of responsibilities.
  2. Each service class has less dependencies which means that they are no longer tightly coupled giants. They are smaller and loosely coupled components.
  3. The service classes are easier to understand, maintain and reuse.

These two simple steps will help us to clean up the architecture of our application, and increase the productivity and happiness of our fellow developers.

Now, we might be wondering if all this is really necessary and if so, when it is critical to address these issues?

Sometimes Life Is Black and White

I have often heard an argument which states that we should not pay much attention to the “architecture” because our application is small and simple. Although this argument has some truth in it, we must remember that a project which starts small can grow into something much bigger.

If we don’t take this into account when it happens, we are screwed.

Sailing in uncharted waters might sound like a bad idea but we must remember that Titanic was sailing in a familiar route when it was hit by an iceberg which sank it. This same thing might be happening to our application right now.

We must have the courage to yell STOP when things are getting out of control.

P.S. If you are ready to take the red pill, I recommend that you read Whoops! Where did my architecture go by Olivier Gierke (or watch his SpringOne2GX presentation about the same subject). But beware, the rabbit hole goes much deeper than you think.
 

Reference: The Biggest Flaw of Spring Web Applications from our JCG partner Petri Kainulainen at the Petri Kainulainen blog.

Do you want to know how to develop your skillset to become a Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

JPA Mini Book

Learn how to leverage the power of JPA in order to create robust and flexible Java applications. With this Mini Book, you will get introduced to JPA and smoothly transition to more advanced concepts.

JVM Troubleshooting Guide

The Java virtual machine is really the foundation of any Java EE platform. Learn how to master it with this advanced guide!

Given email address is already subscribed, thank you!
Oops. Something went wrong. Please try again later.
Please provide a valid email address.
Thank you, your sign-up request was successful! Please check your e-mail inbox.
Please complete the CAPTCHA.
Please fill in the required fields.

6 Responses to "The Biggest Flaw of Spring Web Applications"

  1. In case you have a company that has multiple lines of businesses, which operate on the same data but from different angles, you usually prefer to separate logic from data so that each line of business can have their own separate logic layer, while all can share the same data model.

    This provides an abstraction, which give you great flexibility, especially to try out new use-cases and discard them if they do not apply or perform as expected without to much noise on the rest of the platform.

    • Sebastian, you should of course follow the path which makes the most sense to you. Also, If putting business logic to domain model classes makes things more complex, you should not do it. We should make our code simpler, not more complex.

      About your example: If the different businesses use same data from different angles, doesn’t using the same data model lead into compromises in the names of domain objects? What I mean is that this might lead into a situation where you have to create a generic data model which is not a perfect match for any of the businesses.

      Also, the ownership of the common data model can become a problem. It might be that the business which makes the best profit highjacks the data model and the other businesses are left in its mercy.

      I understand your point about flexibility though.

      DDD has its own solutions to this problem. Instead of trying to create a data model which suits for all businesses, teams following DDD would create an own bounded context (and ubiquitous languages) for all businesses. Of course the common data would have its own bounded context which would then be integrated with the business specific contexts. This way each business would have a domain model which is a perfect match to their needs but they could still share the common data.

      This idea seems fascinating to me but I also know that it does not always make sense to follow this path either.

      Thanks for the comment. It gave me something to think about.

  2. Sean Mitchell says:

    As always, a good read Petri.

    But I’m having a hard time accepting the idea of moving all the business logic to the domain classes. In fact, this feels a bit like the old days where the business logic was all stored procedures in a RDBMS and I certainly don’t want to go back there. There is some logic that would make sense to live at this level, “business logic” that I would tend to think of as domain logic…. you can’t build an X without a Y being in state A. However, a lot of the business logic that I have dealt with is frankly wrong from a domain perspective, when you have an application that is only a narrow perspective of what is (or may become) a much more encompassing system. Consider a many to many relationship that for a given application is only many to one.

    Product owners often tend to see things from the viewpoint of a single application, or group of applications, and when their business logic only makes sense in their own context, I’d put this in an application service layer.

    Essentially, I think I’m seeing it the same way as Sebastian.

    • Sean, you just found the same problem which has bothered me lately. As you probably noticed, I made a vague separation between “application logic” and “business logic”.

      These things are quite close to each other and maybe better names would be “business logic” and “domain logic”. We need to have something which manages the domain model objects of our application and often these responsibilities also fit under the term “business logic”.

      These responsibilities might include things like transactions, security, rollback behavior, integrations and so on. Putting this logic to the domain model classes is an awful idea.

      The reason why I started to wonder what logic I can move to the domain model classes was that I got the feeling that my service classes were doing everything. I started by following the advice which you mentioned in your comment:

      “you can’t build an X without a Y being in state A.”

      Moving this kind of code to my domain model classes did make the service layer a bit cleaner. Then I decided to write this blog post to see if I would get some useful feedback. It seems that it was a good choice since your comment also gave me something new to think about.

      P.S. The title was a link bait ;)

  3. gustavoH says:

    I agree with the article in general, but the same than my fellows before me here, I don’t quite like the idea of moving the business rules into the model layer. It simply doesn’t feel OK. Some business rules can involve more than one entity, and other problems arise in my mind immediately.

    The solution we’ve applied with good results along the years has been encapsulating the business rules into services classes (one rule per service). I’ve never done or seen the “one service class per each entity” but probably is just because we’re not following the common trend, which in this case is a good thing!

    To sum up, we’re used to have two teams (types, layers, whatever you want to call them) of services: one for the application logic and one for the business logic, and they can use each other in a loosely coupled way.
    Model remains model and business logic is encapsulated, atomic and easily maintainable.

    Thanks for the article!

Leave a Reply


1 + four =



Java Code Geeks and all content copyright © 2010-2014, Exelixis Media Ltd | Terms of Use | Privacy Policy | Contact
All trademarks and registered trademarks appearing on Java Code Geeks are the property of their respective owners.
Java is a trademark or registered trademark of Oracle Corporation in the United States and other countries.
Java Code Geeks is not connected to Oracle Corporation and is not sponsored by Oracle Corporation.
Do you want to know how to develop your skillset and become a ...
Java Rockstar?

Subscribe to our newsletter to start Rocking right now!

To get you started we give you two of our best selling eBooks for FREE!

Get ready to Rock!
You can download the complementary eBooks using the links below:
Close