I'm building a straight forward AJAX / JSON web service with Spring. The common data flow is:
some DTO from browser
v
Spring #Controller method
v
Spring #Service method
I'm looking for the most easy way to handle data validation.
I know the #Valid annotation which works pretty well inside #Controller methods.
Why does #Valid not work within #Service methods?
I mean: A service method can be used by any other service and controller. So wouldn't it make much more sense to validate at #Service level?
Let's take this simple example:
MyDTO.java:
public class MyDTO {
#NotNull
public String required
#Min(18)
public int age;
}
MyServiceImpl.java:
public MyDomainObject foo(MyDTO myDTO) {
// persist myDTO
// and return created domain object
}
MyController.java:
#Autowired
MyService myService;
#Autowired // some simple bean mapper like Dozer or Orika
Mapper mapper; // for converting domain objects to DTO
#RequestMapping(...)
public MyDomainObjectDTO doSomething(#RequestBody MyDTO myDTO) {
mapper.map(myService.foo(myDTO), MyDomainObjectDTO.class);
}
Is it common practice that the service method receives the DTO?
If yes: What's the best practice to validate that DTO inside the service method?
If no: Should maybe the controller manipulate the Domain object and just let the service save that object? (this seems pretty useless to me)
In my opinion the service should be responsible for only data consistency.
How do you solve this?
My answer? Both.
The service must check its own contract for validity.
The controller is part of the UI. It should validate and bind for a better user experience, but the service should not rely on it.
The service cannot know how it's being called. What if you wrap it as a REST service?
The service also knows about business logic violations in a way that no UI can. It needs to validate to make sure that the use case is fulfilled appropriately.
Double bag it; do both.
See my other answer: Check preconditions in Controller or Service layer
If you really want to do validation like error handling in your Service layer similar to Spring MVC you can use javax.validation and AspectJ (to advice the methods to validate) which is what I do because I like making reflection do the work and declarative programming (annotations).
Spring MVC doesn't need to do AspectJ/AOP to do the error handling because the methods are being called through reflection (url routing/dispatching).
Finally for you MVC code you should know that #Valid is sort of unofficially deprecated. Instead consider #Validated which will leverage more of the javax.validation features.
Related
When spring was introduced its advice to use an interface between different layers like Controller,Service,DAO instead of directly calling them using actual class reference.
In new age of Spring 5.x and Spring Boot 2.x do we need to still use interface between Controller and Service class. In my case I am developing a REST application with single GET method which call DB and do some business logic. So In my service I have only one method in this case still I do need to use ServiceInterface to call my actual ServiceImpl? what is best practice and is there any specific advantage of using ServiceInterface in this scenario?
Below is Sample code without ServiceInterface
public class MyTestController{
private MyTestServiceImpl myTestServiceImpl;
public MyTestController(MyTestServiceImpl myTestServiceImpl){
this.myTestServiceImpl = myTestServiceImpl;
}
#GetMapping("/test")
public String getTestString(){
myTestServiceImpl.getTestString();
}
}
#Service
public class MyTestServiceImpl(){
private MyTestRepository myTestRepository;
//constructor
//Service method impl
}
In very small applications, it doesn't really matter, because it is still very easy to keep track of all the classes and what classes do what. In a large scale enterprise application it can quickly become a cluttered mess. For example, if you have a rest endpoint/controller that has 100 methods, and it in turn calls 50 methods in your DAO. If you at some point decide to change the DAO methods, you will now have to change all 100 methods in the controller/endpoint. Whereas if you have a service layer in between to bridge the DAO and rest controller you only have to change the service methods.
Another point as #p.streef has mentioned is the seperation of classes and their functions. You can have a modular application wherein the service layer handles all the business logic and rules, the DAO is only responsible for database operations and the controller's only job is to send and receive data. The S in S.O.L.I.D stands for Single responsibility principle, so instead of the service layer is supposed to handle only receiving and transmitting data, and not business logic.
However, if you are building a very very small application then it shouldn't matter.
I am working on a spring base web application where, we have a few RestControllers and some Request DTO classes. Request DTO contains a token field which needs some validation. So I used spring validators to validate that. After validation, we want to send that field to an external system using another REST API (Just for some kind of analytics logging). The same field is repeated in multiple DTO objects and their controllers. So, I am easily able to define annotations for validators and reuse them across the DTOs. But I am not sure how to process that field after validation succeeds (i.e. call analytics API to consume that field post validation), without mixing it with the core logic of controllers.
Approaches I could think of:
Implement a filter/interceptor and process the field there. But then
there is a limitation that request body can be read only once so I
need to use some alternate ways by creating request wrappers.
Repeat the logic in every controller and it is very error prone as for
every new controller we need to remember to write that code.
But non of these approaches look cleaner. Can someone recommend a better way to achieve that?
Thanks in advance.
You can create a BaseController and implement the method there. Extend this BaseController wherever you need this logging service. Like below.
BaseController.java
class BaseController {
protected void remoteLogging(String name,String token) {
//Calling the remote log services}
}
AppController.java
#Controller
#RequestMapping("register")
public class LeaseController extends BaseController {
#PostMapping("new")
public String new(#Valid #ModelAttribute("registration") Registration registration,BindingResult result){
if(rest.hasErrors(){
remoteLogging("name","token");
}
}
I'm working through a spring mvc video series and loving it!
https://www.youtube.com/channel/UCcawgWKCyddtpu9PP_Fz-tA/videos
I'd like to learn more about the specifics of the exact architecture being used and am having trouble identifying the proper name - so that I can read further.
For example, I understand that the presentation layer is MVC, but not really sure how you would more specifically describe the pattern to account for the use of service and resource objects - as opposed to choosing to use service, DAO and Domain objects.
Any clues to help me better focus my search on understanding the layout below?
application
core
models/entities
services
rest
controllers
resources
resource_assemblers
Edit:
Nathan Hughes comment clarified my confusion with the nomenclature and SirKometa connected the architectural dots that I was not grasping. Thanks guys.
As far as I can tell the layout you have mentioned represents the application which communicates with the world through REST services.
core package represents all the classes (domain, services, repositories) which are not related to view.
model package - Assuming you are aiming for the typical application you do have a model/domain/entity package which represents your data For example: https://github.com/chrishenkel/spring-angularjs-tutorial-10/blob/master/src/main/java/tutorial/core/models/entities/Account.java.
repository package - Since you are using Spring you will most likely use also since spring-data or even spring-data-jpa with Hibernate as your ORM Library. It will most likely lead you to use Repository interfaces (author of videos you watch for some reason decided not to use it though). Anyway it will be your layer to access database, for example: https://github.com/chrishenkel/spring-angularjs-tutorial-10/blob/master/src/main/java/tutorial/core/repositories/jpa/JpaAccountRepo.java
service package will be your package to manipulate data. It's not the best example but this layer doesn't access your database directly, it will use Repositories to do it, but it might also do other things - it will be your API to manipulate data in you application. Let's say you want to have a fancy calculation on your wallet before you save it to DB, or like here https://github.com/chrishenkel/spring-angularjs-tutorial-10/blob/master/src/main/java/tutorial/core/services/impl/AccountServiceImpl.java you want to make sure that the Blog you try to create doesn't exist yet.
controllers package contain all classes which will be used by DispacherServlet to take care of the requests. You will read "input" from the request, process it (use your Services here) and send your responses.
resource_assemblers package in this case is framework specific (Hateoas). As far as I can tell it's just a DTO for your json responses (for example you might want to store password in your Account but exposing it through json won't be a good idea, and it would happen if you didn't use DTO).
Please let me know if that is the answer you were looking for.
This question may be of interest to you as well as this explanation.
You are mostly talking about the same things in each case, Spring just uses annotations so that when it scans them it knows what type of object you are creating or instantiating.
Basically everything request flows through the controller annotated with #Controller. Each method process the request and (if needed) calls a specific service class to process the business logic. These classes are annotated with #Service. The controller can instantiate these classes by autowiring them in #Autowire or resourcing them #Resource.
#Controller
#RequestMapping("/")
public class MyController {
#Resource private MyServiceLayer myServiceLayer;
#RequestMapping("/retrieveMain")
public String retrieveMain() {
String listOfSomething = myServiceLayer.getListOfSomethings();
return listOfSomething;
}
}
The service classes then perform their business logic and if needed, retrieve data from a repository class annotated with #Repository. The service layer instantiate these classes the same way, either by autowiring them in #Autowire or resourcing them #Resource.
#Service
public class MyServiceLayer implements MyServiceLayerService {
#Resource private MyDaoLayer myDaoLayer;
public String getListOfSomethings() {
List<String> listOfSomething = myDaoLayer.getListOfSomethings();
// Business Logic
return listOfSomething;
}
}
The repository classes make up the DAO, Spring uses the #Repository annotation on them. The entities are the individual class objects that are received by the #Repository layer.
#Repository
public class MyDaoLayer implements MyDaoLayerInterface {
#Resource private JdbcTemplate jdbcTemplate;
public List<String> getListOfSomethings() {
// retrieve list from database, process with row mapper, object mapper, etc.
return listOfSomething;
}
}
#Repository, #Service, and #Controller are specific instances of #Component. All of these layers could be annotated with #Component, it's just better to call it what it actually is.
So to answer your question, they mean the same thing, they are just annotated to let Spring know what type of object it is instantiating and/or how to include another class.
I guess the architectural pattern you are looking for is Representational State Transfer (REST). You can read up on it here:
http://en.wikipedia.org/wiki/Representational_state_transfer
Within REST the data passed around is referred to as resources:
Identification of resources:
Individual resources are identified in requests, for example using URIs in web-based REST systems. The resources themselves are conceptually separate from the representations that are returned to the client. For example, the server may send data from its database as HTML, XML or JSON, none of which are the server's internal representation, and it is the same one resource regardless.
with spring, when we have a service layer, dao layer and controller to manage a form data (list, selected list value, data found by the bd)
is it a good practice to put all this data in a object?
is a good practice to create a method in the service layer who will call many dao method to feed listbox... and feed a ford object or it's better
to call different method in the service layer from the controller ?
public class UserForm {
private SearchCritera searchCritera;
private List<String> city;
private List<String> country;
...
}
public class SearchCritera {
private List<String> selectedCity;
private List<String> selectedCountry;
...
}
maybe there are a better way that the two idea I proposed?
To me, it makes more sense to have what you suggested:
a DAO layer where you access the database with single operations
a service layer where you aggregate calls to the DAO layer and do some business logic
a web / controller layer where you make calls to the service layer and do what is necessary for the view to be rendered.
Keep in mind that either way you're designing your application, you have to configure it so that the transactions are dealt with properly. If your service layer is transactionnal and there are multiple calls from the web layer within the same method to the service layer, then if something goes wrong, likely the database might not end up in a clean state.
What you want to avoid too is to have business logic in your controller layer.
I'd like to be able to create a base controller in my Spring app that, among other things, determines if a user is a registered user or not. This base controller, following the template design pattern, would contain an abstract protected method that controller subclasses would implement.
The abstract method would have passed to it an instance of User, registered or otherwise. However, I have no idea how I would do this since it seems that by using controllers purely using the #Controller annotation each controller is free to define their request handling method however they like.
Would creating some sort of user service class that is injected into each controller and used to validate a user be one way to get around this? This begs the question (at least for me) how does such a controller get a hold of a HttpServletRequest or the Session object?
Thanks.
Define an abstract BaseController, with no annotations
Define concrete and abstract methods
Call these methods from subclasses (which are annotated with #Controller) whenever needed.
I think the Base Controller is not a good idea if the only code it is to have is for UserAuthentication...instead use Spring security. This is the best option.
Alternatively, you can have methods like this...take a look at the Spring reference..
#Controller("loginController")
public class LoginController {
#RequestMapping(value="/login.do", method=RequestMethod.POST)
public String login(Model model, HttpServletRequest request) {
String userIdFromRequest = (String)request.getParameter("userId");
String password = (String)request.getParameter("password");
boolean verified = ...send userIdFromRequest and password to the user service for
verification...
if (verified){
request.getSession().setAttribute("userId", userIdFromRequest);
}
}
//More Methods
}
Did it help?
-SB
The basic problem is that annotational bootstrapping is not polymorphic. I found this paper useful: http://sanguinecomputing.com/design-pattern-for-hierarchical-controller-organization-with-annotational-configuration-spring-mvc-3/