How to separate Repository and Service Layers - java

How should be separated Repository and Service? IMHO clients (e.g. Controller) should primaly use Service layer instead of Repository as it should be separated from persistance implementation. Single Repository should provide methods of access of only one entity, while methods of Service are able to provide more complex actions, including usage of multiple repositories.
But what to do with rich repositories, that provides not only CRUD methods but much more, like JPARepository from Spring Data? In such implementations there are so many possible methods of fetching objects that duplicating them in Service isn't cool.
So what is the solution for that problem?
A. Duplicate methods in service layer like this
#Service
class XService{
#Autowired
private XRepository repository;
public List<X> findAll(){
return repository.findAll();
}
}
B. Simply using repository in controllers (autowired or access method in service)
C. Any other good approach?

Services should implement (business) logic and possibly modify entities according to that logic. If your service layer is only a thin wrapper around repositories, i.e. only fetching entities as your description suggests, something is wrong with your design.
Often logic is spread throughout the controllers. Identify that logic, extract and encapsulate it in services and restrict Controllers to manage the application's flow, by orchestrating the appropriate services.

Related

Spring Data:: Making Repository Methods Available in Service Interfaces

I am using spring Data and JPA/Hibernate for my repositories. When I extend JpaRepository, I get many methods as usual as it implements PagingAndSortingRepository and CrudRepository.
Am using the repositories inside my service classes. My question now is, is there a way I can get all the methods in the repositories inside my service interfaces so that the service implmenting classes can delegate the calls to the repositories using the same method names as the repositories.
I would like to use the same method names as the repository methods and also don't want to call my repositories directly from the controllers.
Do I have to copy all the method signatures from the JpaRepository, PagingAndSortingRepository and CrudRepository into my service interfaces?
If i have understood the question right.Firstly create repository as an interface that extends JpaRepository or others and do not forget annotate your interface with #Repository. Then create your service and inject your repository to it, so you can create your own methods(any name can be used) in a service. Then you can inject service to your controller. This technic mostly used.
I think you misunderstood what a Service really represents.
A Service is the point where to handle business logic. Its methods should represent business operations, not simply data-retrieval/persistence ones.
Simply having all the JpaRepository methods and delegating to a Repository is a recipe for massive code duplication, which you should avoid.
Build your Service along your business requirements.
If you feel there is no need to have a Service middleware, maybe because you only get/set data, simply Autowire the Repository inside your Controller.
It's not always true that using a Repository inside a Controller is wrong. It depends.
You do not need to copy the methods of Repository to any service. Spring Data JPA offers many powerful features to write custom queries.
Suppose you have UserRepository for a domain called User and want to find a user by his/her email address. Instead of creating findByEmail method in a separate service that extends UserRepository, just declare it inside the UserRepository interface:
User findByEmail(String email);
Spring Data JPA will then do all the dirty work for you. You can call this method by injecting UserRepository inside the Controller (or other classes).
Above is only a simple example. You can even declare a query with multiple conditions:
User findByEmailOrUsername(String email, String username);
User findByEmailAndActiveTrue(String email);
List<User> findTop10ByEmail();
I would suggest you to explore the official documentation of Spring Data JPA. There are so many things you can do by writing few lines of code.

Spring Architecture Questions: is Service needed?

I'm new to Spring and I'm creating a REST-Service.
I wonder what the Service-Layer is for (#Service).
Currently I encapsulate my DAOs with that Layer.
So for example my PersonController receives a PUT, calls the PersonService which calls the DAO which finally saves the person in my database.
I also saw some examples in the www. (https://howtodoinjava.com/spring/spring-core/how-to-use-spring-component-repository-service-and-controller-annotations/)
I also have read this question here: Is this a good Spring Architecture (include testing)
Do I even need the Services, if it only calls the DAO like:
public void save(Person p) {
personDAO.save(p);
}
?
I don't really see what the advantage of this is. I create classes which actually do nothing... Or is it just a architecture standard because additional business logic will be in this layer too?
Also... when I have several services like personService, familyService, animalService, etc. and they all have some method signatures that are the same and some which aren't... is it useful to use Interfaces here?
When I create Interfaces like: Saveable, Loadable, Deleteable (does this even make sense?) - how do I use them correctly? Do I create a new Interface for every service that extends the Interfaces I desire? Like a PersonServiceInterface that extends Loadable and Deleteable and I implement it in my PersonService?
Thanks in advance!
If you do not feel the need for a service layer, then chances are high your controllers are performing way more business logic than they should.
adding a service layer in between allows for dedicated tests of pure frontend (controller handle request and response wiring only / services handle the business logic/ repositories persist and query the data).
so rule of thumb - it is much easier to have many services handle fractions of your logic than to stuff everything into your controllers
i am not sure what you are trying to solve with the interfaces you introduce - i do not think it makes sense to re-invent the Repository interface on top of your services. If your services only forward to repositories directly then there is no use in having them anyway.

Call repository and service from controller layer with Spring

I use Spring Boot and Spring Data.
I have no problem in my mind to separate Repository Layer and Service Layer
So I have my UserRepository with CRUD method and some Spring Data method
findAll
findByUsername
I also have UserService with business method.
checkPassword(String login,String password)
businessMethodAction(String username)
Here is my question:
In my controller I have to call method from UserService and sometime from UserRepository. For the moment, I inject both in my controller, and I call service or repository
#Inject
UserService userService;
#Inject
UserRepository userRepository;
#RequestMapping("{username}")
private void myMethod(#PathVariable String username){
return userRepository.findOne(username);
}
#RequestMapping("{username}/doBusineesAction")
private void myMethod(#PathVariable String username){
return userService.doLogicalThin(username);
}
I'm just asking because I confused to inject both and to call one or the other in the same class
On another side, this would mean to duplicate method in service layer like this
public User findOne(String username){
return userRepository.findOne(username);
}
What's your opinion?
Controller layer shouldn't ever call repository directly. You should always use the service layer because the service layer encapsulates your business logic surrounding that call. Just because currently there isn't any business logic, doesn't mean that you should skip the layer entirely.
If your controller does not require business logic or perform a single repository operation, you can use the repositories directly. Use services to implement use cases that require business logic or orchestration of repository calls.
If it's a layered CRUD app, I think it's fine for the controller to have knowledge of the repository and directly call it for simple read operations as long as the app is simple, small
Tradeoffs:
The controller calling the repo removes the layer of abstraction of the service layer
The controller and repository are now coupled
If you don't have requirements/use cases/business logic for your read op., I would suggest not rolling out a full service. YAGNI (you aren't going to need it). Meaning, it doesn't make sense to implement an extra 'pass through' service layer at this time given the business needs.
Before you choose to make your controller aware of your repository, I suggest to consider whether or not you've decoupled your repository layer from your persistence layer.
The structure of controller -> service -> repository -> persistence is not a hard and fast rule, as opposed to controller -> repository -> persistence. Your use case seems to fit the latter.
In my opinion, the service layer must implement the business logic and it must be called from controllers. In most of the cases, this layer has to perform more operations than just calling a method from a DAO object. This is probably the best solution if your application has great size. Also, you can split your logic into several parts and make it working in one transaction, that help you to save the data in the non-controversial state.
If you don't need transaction and no business logic is involved there is no need to have extra code that doesn't do anything.
There are examples in spring documentation when controller is calling repo.
Example 51 from here https://docs.spring.io/spring-data/data-commons/docs/current-SNAPSHOT/reference/html/#reference for example.
One approach is to reserve controllers are for business level concepts displayed on the views and repositories for the normalized entities in the DB. One can then define services to address the many-to-many relationship between controllers and repositories.
Firstly, you should not be using both the service and repo class within the controller class. These are some good practices while using SpringBoot:
Repo class should be injected in Service class
Service class has to be injected in the Controller class
Following this you can use it efficiently. Using both the service and repo objects within controller is like confusing the spring context which instance to be called.
The correct annotation is #Autowired, not #Inject, if you are using spring boot.

Mixing DAO and service calls

Let's say we have some layer above service layer, with web controllers for example. Service layer is in turn above DAO/Repo layer. In the upper layer the service calls are used alongside repo calls. It breaks the layering of the application to some extent, but should we really bother about wrapping repo methods like findAll() into service methods. I don't think so. Are there any drawbacks that might cause a lot of pain because of such design? Transactional issues?
I would turn your question around and say - why not have a service layer for such a method? Is it such a pain to wrap a DAO method like:
public class PersonService {
...
private PersonDao personDao;
...
public List<Person> findAll() {
return personDao.findAll();
}
...
}
Client data
What if you don't want to send back the data entity that represents a Person to your controller? You could map the data in the service layer to an Object that only clients are dependent on.
Coupling
You are also coupling your layers. The controller layer should only depend on the service layer and the service layer should only depend on the DAO layer.
Transactions
All transactions should be handled at the service layer (as a service method may call multiple DAO methods).
Business Logic
All business logic should be in your service layer. Therefore, you should never bypass such logic by calling a DAO directly.
I know, for a method like findAll, it seems pointless but I think the point about layer coupling defeats that argument.
Yes it can be a pain if some developer used to call DAO layer code directly from other layers i.e. other than Service layer or whatever architecture you are following for this as a solution:
Use maven dependencies create 4-5 different modules for your project and mention the dependencies in pom.xml so that no calls will be made from any other incorrect layer.
For making it more clear:-
If you want to access layer 3 only from layer 4 just add one dependency entry in layer 3 for 4 and as no other modules have access to layer 3 they can't call code from it.
You definitely get hundred of example for doing this.

Using Services and DAOs in spring mvc controller

I'm building a web application that primarily constitutes of CRUD operations of data from back end/database. There are instances where in I have to write business logic(I'm sure we will have more business logic built as we go deeper in to development). Currently for each UI screen I'm creating I create a model class,Service class, DAO class, a controller(it's servlet essentially) and bunch of jsp pages. In most cases the service class just calls the methods from DAO to pass in model objects. Essentially we use model classes to map data from UI screens. Hence the controller will have the model objects populated when a form is submitted. I have started using service classes to keep a separation layer from web layer to DAO layer. But at times I feel that the service class is just adding unnecessary level of API calls, I would think that I could just inject the DAO in to Controller and complete the task faster. I want to use the service class only when there is additional business logic to be performed. If you have to design an application what factors do you consider using controller->DAO vs controller->Service->DAO control flow?
DAOs are more granular and deal with one specific entity. Services provide macro level functionalities and can end up using more than one DAO. Typically, Services are used for defining transaction boundaries to gain atomicity. In other words, if you end up updating multiple tables using multiple DAOs, defining transaction boundary at service will help in either committing or rollbacking all the changes done to DB.
In your design, since you are primarily doing CRUD for various entities, it may seem that services are not adding much value. However, think of web-based front end as one way of updating data. Usage of services will allow you to expose same capabilities as a web-service later to other forms of client like third party integrators, etc.
So, in summary, your design seems to be in line with conventional practices. If you feel that you can combine multiple services into one based on some common theme such that it can reduce the overhead of code, then, you should go ahead and do it. At the end of day, ultimate goal is to create maintainable code which no one is afraid to change when need arises.
In Pro-Spring-3 book they mentioned below line, for controller with JPA2
Once the EntityManagerFactory had been properly configured, injecting it into your service layer
classes is very simple.
and they are using the same class as service and repository as in below:
package com.apress.prospring3.ch10.service.jpa;
// Import statements omitted
#Service("jpaContactService")
#Repository
#Transactional
public class ContactServiceImpl implements ContactService {
private Log log = LogFactory.getLog(ContactServiceImpl.class);
#PersistenceContext
private EntityManager em;
// Other code omitted
}
but in case you are going to use spring-data CRUDRepository or JPARepository then your DAO will be Interface and you have to make service layer to handle your code
I'd reference my answer here
The long and short of it is the advantage of using a Service layer is it gives you room to move in the future if you want to do anything with Spring Security and roles etc. It allows you to handle transactions more atomically and Spring itself has really nice annotations for this.
Use a service class when dealing with more than one aggregate root.
Inject repositories (aka a dao that returns a collection) or dao's directly into controller, no need for an extra layer/class to do a basic get.
Only use service classes where necessary, otherwise you have twice as much code as required.
You can make repository generic, and annoatoate with #Transactional(propagation = Propagation.REQUIRED) which enforces a transaction is present, but won't create a new one if already present. So if you later use multple repositoes in one service class method, you will only have the one transaction.

Categories