Spring Boot Bean Validation In HashMap Not Working - spring

I am creating a REST controller which shall take a list of Dtos.
It all works but the validation is not working, therefore it fails during persistence only.
My code:
#Valid #RequestBody HashMap<String, MyDto> myDtoMap
And unfortunately the MyDto does not get validated.
I also tried this way:
#Valid #RequestBody HashMap<String, #Valid MyDto> myDtoMap

Please try :
annotate your controller with :
#RestController
#Validated
Then you can validate you class with :
#RequestBody HashMap<String, #Valid MyDto> myDtoMap

Related

How to define a class or method after #Getmapping in a Spring Controller

when defining a class after #Getmapping annotation in Spring Controller, are there other ways besides Iterable see code sample below on how to define a class or method after #Getmapping in a Spring Controller,
#RestController
#RequestMapping("/rooms")
public class RoomController {
#Autowired
private RoomRepository roomRepository;
#GetMapping
public Iterable<Room> getRooms(){
return this.roomRepository.findAll();
}
}
Are there other ways to define a class or method after #Getmapping in a Spring Controller
Based on HTTP GET specification:
The GET method means retrieve whatever information (in the form of an
entity) is identified by the Request-URI. If the Request-URI refers
to a data-producing process, it is the produced data which shall be
returned as the entity in the response and not the source text of the
process, unless that text happens to be the output of the process.
So, for GetMapping you can return any type which defines as an entity (i.e. any Class which suits your requirement).

Hibernate Validator with Hibernate Dynamic Models (No Entity Class)

I'm using hibernate dynamic models to create a CRUD. I'm wondering how can I validate the http request (#Valid) annotation because I don't have the any entity or DTO.
#PostMapping("/signup")
public ResponseEntity<RestResponse> signup(#Valid #RequestBody Map<String, Object> user) {
var restResponse = new RestResponse<>();
restResponse.setStatusCode(HttpStatus.OK.value());
restResponse.setResponse(user);
return ResponseEntity.status(HttpStatus.OK)
.body(restResponse);
}
You can't because there is no java class that for bean validation annotations to put on and that is the sole basis for bean validation. Maybe you should switch to a proper class based model which will also make it easier to understand and debug your application

What is #PostMapping annotation in Spring Web MVC?

For what purpose #PostMapping annotation is used in Spring MVC?
#PostMapping is a composed annotation that acts as a shortcut for #RequestMapping(method = RequestMethod.POST).
#PostMapping annotated methods handle the HTTP POST requests matched with given URI expression. e.g.
#PostMapping(path = "/members", consumes = "application/json", produces = "application/json")
public void addMember(#RequestBody Member member) {
//code
}
Follows this :example
Hope this helps..!
Spring Framework 4.3 has introduced #PostMapping annotation.
#PostMapping is a composed annotation that acts as a shortcut for
#RequestMapping(method = RequestMethod.POST)
Similarly the following annotations are available:
#GetMapping
#PutMapping
#DeleteMapping
#PatchMapping
These annotations can improve the readability of code.
Reference: Spring API documentation.

calling a method by class level annotated with #RequestMapping that includes an autowired class

I am trying to call a method that is annotated with #RequestMapping(signIn) through a class level (from method: authentication) like so:
#RequestMapping(value = /authenticate, method = RequestMethod.POST)
public #ResponseBody Response authentication(HttpServletRequest request)
{
UserController user = new UserController();
return user.signIn(request, null);
}
and my controller looks like:
#Autowired
private UserManager userManager;
#RequestMapping(value = /signin, method = RequestMethod.POST)
public #ResponseBody Response signIn(HttpServletRequest request) {
JsonObject json = Misc.parseJson(request);
String lang = Misc.getLang(request);
user.setEmail(Misc.getEmail(json));
user.setPassword(Misc.getEncryptedPassword(json));
return ResponseUtils.success(userManager.auth(user, lang));
}
user manager is annotated with #component:
#Component
public class UserManager {
public User auth(User user, String lang) {
....
return user;
}
}
Problem is when I call the method "signIn" and just new-up a UserController instance through "/authenticate" mapping, the UserManager becomes NULL. So now I'm assuming that autowiring doesn't work when it's done this way.
Is there any other way to call the signIn method? I would hate to copy paste an already existing code to another class just to get this to work...
Autowiering only works in spring managed bean. If you create a class with new keyword, it is not a spring managed bean and autowiering would not work.
You can try to autowire the class which contains the method which is annotated or better put the code in a service class which can be used by both methods.
It's not problem with #Autowired .There are two type of Annotation
firstly method base annotation and field level annotation. You just used field level annotation.Check your import class with "org.springframework.beans.factory.annotation.Autowired" or it can be problem with initiation of "UserManager"
I don't know why you not moving logic into separate Service classs, but try this:
UserController.java
public UserController(UserManager userManager) {
this.userManager = userManager;
}
and then inside controller where authentication resource method is located:
#Autowired UserManager userManager;
#RequestMapping(value = /authenticate, method = RequestMethod.POST)
public #ResponseBody Response authentication(HttpServletRequest request) {
UserController user = new UserController(userManager);
return user.signIn(request);
}
So in the end I just separated the logic instead. Though one solution that I tried and I could have used was to just add another mapping to the signIn method instead of adding a new method in the other class since the logic was similar. Still I opted for a separate logic instead since there were a lot of unnecessary code in the signIn method for my purpose.

Mocking spring controller validator

I want to unit test this Spring controller method:
#Autowired
private MyValidator validator;
public String register(
HttpServletRequest request,
ModelMap model,
Principal principal,
#PathVariable Plain plain,
RedirectAttributes ratts,
#ModelAttribute #Valid PlainMoreObject pmo,
BindingResult result)
{
validator.validate(pmo, result);
I'm using JMock. How do I mock the validator in order to test controller by calling
controller.register(....) ?
There is a helper class in Spring called ReflectionTestUtils (link) you can use to inject mocked beans to fields.
#Mock MyValidator validatorMock;
ReflectionTestUtils.setField(controller, "validator", validatorMock);
controller.register(...);

Resources