When using Spring MVC for REST API i typically have the normal components - Repository for DB access, Service for CRUD operations, and RESTController for Web layer.
Things get out of balance when i want to add a new API that is not a typical CRUD API. For example lets say i have a Person class
class Person{
private Long id;
private String name;
private List<Person> familyMembers;
private Address address;
private Bank bank;
}
And i'd like to add a api that will be used by calling
POST /persons/{personId}/registerToBestBank
The method will do all sort of calculation that is very specific to it, it might register it to the bank that has most of its family members, or the one most closest to him - or some sort of complicated calculation that depends on other entities.
The RestController is the only place which will use this calcluation so it makes since to me to put it in there, and not add more APIs to the service which adds a lot of noise to the system.
Is there a best practice?
API stands for Application Programming Interface.
As such it should be only a layer that translates the rest calls into proper calls to the service. The business logic itself should be implemented in the service layer.
Think about it this way: If one day REST is replaced by some other technology or you want to add another way to execute the same function (e.g. react on an external event etc.) you only have to implement the new API. The functionality itself, since it is implemented in the service does not have to be changed at all.
You can still separate the CRUD service functionality from any other functionality if you feel that the service gets too bloated.
If you really are 100% sure that some function is only going to be needed for the REST API you can implement it in the controller. But testing controllers can be a bit of challenge, so I would not recommend that unless you have that problem solved.
keep your business logic in Service layer and only delegation specific code in your controller.
Rule of thumb :
Presentation Layer : Controller (#Controller)
Only responcible for delegation to App Service
Application Service Layer : Application Service (#Service)
Responcible for business use cases, any business logic calculation or rules/algo etc
Repository (#Repository) etc
No business logic only DB operations
Controllers should not contain any code which belongs to Service layer i.e business logic.
Even we create the microservices for better-structured way. It may vary that we can place CRUD operations in one service and can place other operation in another service if required.
Ideal Way
For REST APIs request, response is the core part which should be handled by Controller
Service should contain business login
repository to handle DB operation
DTO/DAO according to the requirement
Why?
Structured way (cleaner and easier to understand/discover)
Easy to write TestCases
Related
When creating a entity with the Jhipster helper, it asks
? Do you want to use separate service class for your business logic? (Use arrow keys)
> No, the REST controller should use the repository directly
Yes, generate a separate service class
Yes, generate a separate service interface and implementation
In which case should I use which option?
What are the benefits and flaws of each solution?
Is it possible to change easily the architecture once everything is set?
IMHO it depends on how complex your application is going to be and how long you plan on having to maintain it.
If your domain model is quite simple and your REST controllers are straightforward CRUD operations without complex mapping, you can get away without using a separate service layer.
If your domain model or interactions get more complex, you might need a 'Separation of Concerns': your Controller classes should just map REST calls from/to the correct DTO's for the REST API, and business logic and coordination between different entities should go in a service class that does not have anything to do with the REST API. In the long term, that makes it easier to make changes in the REST API separate from changes in the business logic.
Some blog posts to read:
https://www.petrikainulainen.net/software-development/design/understanding-spring-web-application-architecture-the-classic-way/
https://blog.cleancoder.com/uncle-bob/2012/08/13/the-clean-architecture.html
Then about the decision to use interfaces or not. The main advantages of using interfaces used to be that it allowed better testing and avoided coupling modules too close. But since 2010, there has been a lot of discussion whether it's worth the overhead. Maybe start reading the discussion underneath Adam Bien's original post:
https://www.adam-bien.com/roller/abien/entry/service_s_new_serviceimpl_why
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.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 7 years ago.
Improve this question
I have a question regarding database access in a mvc application. Where should my database access logic placed?
should it be placed in each model? (if I have a Person model)
Person p = new Person();
p.save();
should it be placed in each controller?
or should I create a different set of classes only to perform the database logic, which means I have an additional layer in addition to model,view and controller?
How is this done?
Also what if an ORM is used?
In MVC pattern, M means models, V means view, C means controller. A common MVC application progress is that once a request is coming, controller get it and do necessary processing, retrieving results data, then pass the results data to view for rendering. After view layer is rendered, it displays to users via GUI.
Controller can be regarded as a commander, it controls process, but it is not good to handle data retrieving in controller. Model should be responsible for retrieving and organizing data. That means data objects should be stored in Model instead of Controller, Controller calls Model to retrieve data objects.
For your case, my suggestion is it needs following components:
PersonController, it calls PersonService.savePerson(Person person) method to save data(or in other case it retrieves result). I suggest Controller layer should be thin.
PersonService, it has method savePerson(Person person), this method calls PersonDAO.savePerson(Person person) method to save/retrieve projects data(here it saves data), and maybe other handling. Here business logic goes.
PersonDAO, it has several methods which deal with Person objects(like savePerson(Person person), getAllPersons()), deal with database in this layer. But these methods should be independent with business logic(as business logic should be deal in PersonService).
Person object, it is value object, it just defines what attributes a Person should have, like name, age, etc, with get/set methods, used for passing data through different layers. It does not deal with database at all.
While for uncomplex application, Service layer is not very necessary and can be integrated to Controller layer, which means just PersonController is ok.
Others have pointed out that database access is a Controller function, but I recommend that you create a new library project to handle the database interaction. Typically this will have a name like "customerService.jar" - i.e. it encapsulates everythng you want to do to a customer. This will simplify your application, and add greatly to the reusability of your code.
This would be by approach:
Define an interface that exposes business level operations (eg. changeUserRole(long userId, Role newRole) or makePayment(long accountId, BigDecimal amount) rather than the CRUD approach of updateUser(User user) etc. Typically some of the methods exposed by the interface will look like CRUD methods but might do more at the database end (e.g. check account status, maintain audit tables).
Implement your business logic in this layer. Purists would say that there should be a separate layer for the business logic, but this makes it difficult to use SQL facilities (joins in particular) to efficiently access the database. In my experience these two layers need to be combined to keep the system simple and performant.
Use an ORM tool to access the database and map from business objects to the database. (MyBatis is my favorite). If your database accurately reflects your business model, then you probably won't need separate DAO and business objects.
Inject an instance of your customerService into your web MVC controller. The job of the controller is now to validate user input, populate the model, pass through requests to the customerService and put response data back into the model.
So if your needs change in future (e.g. You need to create an IOS or Android native app) you have a re-usable service that will happily do the job. Similarly if the architects insist on exposing it as a REST or SOAP service, you only need add the "glue logic" to implement the REST or SOAP service.
Also, it is easy to mock out the customerService in web unit tests.
Best of luck!
Its always better to segregate your code and group them according to their behavior. Model classes can be used as logical representation of your DB. You should have some Utility / helper classes which does your DB activities, and controller should interact with them.
Ideally you should have as many model classes (if not more) as you number of tables in the DB.
When you use ORM, the connections and mappings (once declared) are take care off by the framework and you focus on the business logic.
In a Web application using a framework such as Spring or Jersey (which you should use), it's generally best to make your "controllers" (HTTP request handlers) as simple as is practical, wrappers around a service layer that contains your business logic such as database access. This both makes testing dramatically simpler, since you can test the business logic directly without the complication of HTTP requests, and makes it easier to reuse your business logic in future changes such as adding scheduled tasks.
When more than very simple CRUD operations are involved with something like a Person object, I will create a PersonService with methods that are expressed in terms of the business operations and inject that service into the controller. For simple CRUD operations, I generally use Spring Data repositories directly from the controller.
Define function which accesses Db or which does DB related operations in your class file which we call it as Model and then access that function using that class object in Controller. Controller is just set of functions which give us DB results and assign those results to variables in Controller and access those variables in View which is your front-end
I have design issue when implement 1 simple web application.
I use struts2 web controller, spring’s IOC and Hibernate as persist layer.
Because this web application is very simple at begging. So I only have 2 layers:
1 DAO layer which used to access database. Almost every table have related DAO.
2 Action layer. User struts2.
I am satisfy with this architecture because can quickly implement my web application.
As project become bigger, I found the action layer become big and complex, and very hard to re-use.
I try to create service layer, to solve complex business logic is good, but my application still have a lot of simply logic. E.g: Load 1 object, save 1 object, and get collection by some condition and display it to webpage. If give each simple DB access method have corresponding service method. Still cost a lot of effort. How can solve this issue?
And I think, if service layer existing, direct call DAO layer still not good design for my application.
Is any good solution for this kind of small web application?
When planing the different layers in a web application it is good practice to explicitly protect attributes and associations in your model from being manipulated without providing an identity context.
This is something that should neither be done in the DAO layer nor in the Controller. You should wrap your DAO layer in a service layer and have the controller only talk to the services not the DAO directly.
Protecting your model against unwanted manipulation means that you for instance adapt the amount of information passed in a data structure between Controller and Service to the actual operation that you want to perform.
For instance: adding or removing an element from a collection is an explicit operation in the service, it does not happen implicitly by manipulating a collection as a member of a DAO object and passing that DAO back into the service.
Instead your service may look like this:
+ getAllCompanies(): CompanyType[*]
+ getAllEmployeesOfCompany(c: CompanyType) : EmployeeType[*]
+ addEmployeeToCompany(e: EmployeeType, c: CompanyType)
+ removeEmployeeFromCompany(e: EmployeeType, c: CompanyType)
The additional benefit of such an architecture is that the service layer serves as boundary for your transactions. Using the methods of your controller as boundary for your transactions is in fact a very bad habbit. You could even call it an anti-pattern. Why? Because for instance it would mean that when your client hangs up it would roll back your transaction. That is clearly unwanted in 99% of the cases.
As #mwhs commented, Apache Isis provides plenty of guidance on layering your app. To figure out whether it fits your requirements, you could run through this tutorial I presented at a recent conference.
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.