Tuesday, April 28, 2015

The 'Generic Service' Design Pattern

Hello everyone. Let me tell you some information about a very useful design pattern - 'Generic Service'.

One of the big Java development problems is verboseness. Java language is as well verbose as a typical Java-application design. I.e. enterprise applications are usually developed using a multylayered architecture. In the approach a developed application is sliced to three different parts: the presentations layer, the business logic layer (in JavaEE applications usually is implemented as a set of services), and the data access layer. Every layer can be called from an overlying one via some interfaces. There are interfaces between layers because developers want to have the ability to change a layer implementation without any modifications of other ones.

Please, let's see what we as developers have to do for adding an operation to a service:

  • add a method to the service interface;

  • add a method body to the service implementation;

  • add a method to a data access layer interface (optional);

  • add a method body to every implementation of the access layer interface (sometime we have more then one implementation of the interface) (optional).

Also we need to remember in enterprise application a service method usually contains a transaction control logic as well as business logic (I mean bean-management transactions). The method looks like as the following piece of code:

Sad, but there is the only one line that really do business logic and we have to write 15 lines of redundant code! It's not a normal situation! Of course, we can use some frameworks like Spring Framework or Google Guice but sometime the code without any frameworks is the best choice. I don't know why we need a framework to develop a small application with 5-10 UI forms and 7-8 business objects. Sometime also a method can't be executed in one transaction, so bean-management transactions (BMT) was invented to solve this problem.

The responsibility of every class that implements some business logic can be divided into two parts: one is transactions management, another is business logic essentially. The main idea is to create a generic service that will be used in an application at all. The service contains three operations: loading data from a storage without a transaction, loading data from a storage within a transaction, and saving data to a storage within a transaction. The GenericService interface can be as follows:

The classes implementing the UpdateRequest and LoadRequest<T> interfaces encapsulate only some business logic. Each class implements only a small piece of work and has only one responsibility, so the classes do not break the SRP. The interfaces methods (update and load, respectively) accept a registry of DAOs (DaoRegistry) as a parameter for the interaction with storage.

The DaoRegistry interface can have the following implementation:

The implementation of GenericService is totally specific for every application. The implementations different from one another by the selected storage interaction approach and the strategy of transaction management. I.e. the implementation of the GenericService interface, which uses JPA and implements the 'one entity manager object per a transaction' strategy, can look like the following piece of code (only the 'updateTransactionally' method):

Let's see some examples of the service usage:

Of course, if the implementation of GenericInterface is too long you just can make a new unanonymous class, i.e.:

and then use the class in the following way:

Since the service is generic, it is possible to have only one 'GenericService' implementation with the application but this one must be thread safe. Thus it's very easy to build the pool of entity managers or to use the 'Open Session In View' design pattern, using IoC or not.

Could you share your opinion about the generic service pattern, please? Do you develop some applications without using IoC containers or today using the containers is a common sense?

No comments:

Post a Comment