Retrieving Grails Domain Validation Messages - java

I'm pretty new to grails and I'm sure this has been asked multiple times. I have an application which I'm developing in grails. In my service, I make an entry into multiple tables. If one of them fails with a mysql unique constraint exception, I get an error as part of domainInstance.errors object. How do I parse this to return appropriate error code to my controller.
Normally in spring, I was generally adding an exception interceptor for controller to take care of this. Whats the preferred way to do it in grails.

When a validated domain object has validation errors they are stored under domainObject.errors, as an implementation of the Spring Errors interface. To render the errors for a field of this object in a GSP, you typically use something like:
<g:hasErrors bean="${book}" field="title">
<div class="errors">
<g:renderErrors bean="${book}" field="title" as="list" />
</div>
</g:hasErrors>
The exact message that is displayed is resolved from the message*.properties files. If you want to get these messages in a controller instead, do this:
class MyController {
MessageSource messageSource
LocaleResolver localeResolver
def myAction(Book book) {
Locale locale = localeResolver.resolveLocale(request)
if (!book.validate()) {
List allErrorMessages = book.errors.allErrors.collect {
messageSource.getMessage(it, locale)
}
// print all error messages
println allErrorMessages
}
}
}

Related

Add Entire Protobuf Message to Model in Spring Boot

I'm starting to play around with Spring Boot to learn how it functions for a MVC web application.
At a high-level the goal is to have a controller that will handle GET requests by issuing a request to an external gRPC server which will return a Order protobuf message. The Order data will be added to the Model and served via a template with Thymeleaf.
I am new to the Spring framework as a whole so the approach is likely incorrect but what I was doing is:
#Controller
public class OrderController {
#GetMapping("/order")
public String getOrder(#RequestParam(name = "order_number") String orderNumber, Model model) {
// Code for getting Order proto message from external server here
model.addAttribute("name", Order.getDate());
model.addAttribute("total", Order.getTotal());
model.addAttribute("number", Order.getNumber());
....
return "order";
}
}
However, this seems pretty tedious (especially for larger messages). Is there something I am missing that would allow me to add these fields en-masse?
Sorry, I cannot comment on question (SO restriction), hence asking here - cannot you just put your order object in model (rather than individual fields) and access it's fields/methods in view (Thymeleaf)?
In controller
model.addAttribute("order", order);
in view, I am not sure as I have not used Thymeleaf but should be simillar to
<span th:text="${order.getName()}" />

Spring boot translate default exceptions

1 . What i want to do is set default message for #Size validation like this
#Size(min = 8,max = 255,message = "{validation.size}")
I dont want to put this on every field, so im asking if there is any way of setting global translation of this message..
I want to translate error messages that are comming from spring security like Forbidden, Access denied etc
I already tried putting spring security messages like these in messages.properties
ExceptionTranslationFilter.insufficientAuthentication=A Custom message
AbstractAccessDecisionManager.accessDenied=A Custom message
But doesnt seem to be working..
You'll need a class annotated with #RestControllerAdvice. Add methods there to capture relevant exceptions and you can translate them into your responses. Even mess with http status response codes too if you want.
#RestControllerAdvice
#Slf4j
public class MyControllerExceptionHandling {
#ExceptionHandler(MethodArgumentNotValidException.class)
#ResponseStatus(BAD_REQUEST)
public MyErrorMessageDto handleMethodArgumentNotValidException(MethodArgumentNotValidException ex) {
return MyErrorMessageDto
.builder()
.cause("Bad something something")
.build();
}
}
Look up exceptions like MethodArgumentNotValidException and ConstraintViolationException as you'll need to handle these (and others) depending on your controller validation.
NB: The JSON you return for errors is just as much a contract with your clients as the JSON you return for successes, so have a google and see what others have done (before you get locked into something you wish you'd done better!).

How to handle the GET method so that I can update the requested object before returning it?

I'm working with an API implemented with Spring Data Rest and I would need to handle the GET method like I can do with the #RepositoryEventHandler, which allows me to handle before/after save, create, delete...
The case is that I need to update the object to be returned gathering information from other APIs before returning it as the GET response.
Is there any way to handle the GET in spring data rest?
You probably need to use #RepositoryRestController for this. It lets you get stuff from the #Repository and then add new things to the response object. Pretty similar to #RestController, but keeps Spring Data REST’s settings, message converters, exception handling, and more.
you could add Interceptor implementing HandleInterceptor and add it to mapped inteceptor bean.
#Bean
public MappedInterceptor myMappedInterceptor() {
return new MappedInterceptor(new String[]{"/**"}, new MyInterceptor());
}

Spring: is there built in way to raise jsr303 validation exception in service layer?

I have a model with jsr 303 annotations and service
public class User {
#NotNull
#Size(min = 2)
private String username;
#NotNull
private String email;
...
}
#Component
public class UserServiceImpl extends UserService {
public void createNewUser(#Valid User user) {
...
}
}
Is there any build-in way to raise validation exceptions (if any) whenever I call method on this service , like in Controller layer?
...
userService->createNewUser(user) <- Here I want validation exceptions to be thrown
...
P.S: I can do it with spring AOP, but I wonder if there is build in way.
The problem is in Spring the validation is integrated with your controller, so that validation messages get propagated back to the view, and you see something like for example: invalid email next to an email text box. The other place validation is used is in persistence, when you have constraints for when you are going to commit, update and delete. You cannot do these actions if the corresponding validation constraint is violated.
So it's clear a controller will show the error in your view, and a DAO won't commit to your database when validation fails. Now what do you expect to happen in the service layer? I can only think of that you would want to throw an exception if you call a method with the incorrect arguments. I guess you could make a case like you have for using aspect orientated programming to throw exceptions when this happens as you already know.
But I don't think anyone finds it too useful to have parameter validation at this level because you can't automatically display it back on the view like you can when you have validation in your request parameters in a controller. It would be better to find these violations in the controller so that the user can see these back in the view.
If you do choose to go down the aspect path then you could catch these exceptions and display a certain page with ControllerAdvice, so in a way you could integrate exceptions there back to this view, although it's never really occurred to me to do this, but you might find this helpful, it's just you might be in a service within a service within a service and the parameters might not mean much to the user who made some initial request.
But in general it would be the simplest to do this validation in the controller if you can.

Does Spring generate code for validaiton?

lately I was trying to understand how spring processes #Valid annotation. For example look at the following controller's method:
#RequestMapping(value = "/create", method = RequestMethod.POST)
public ModelAndView createEmployee(#Valid EmployeeForm form, Errors errors) {
if(errors.hasErrors()) {
//validation errors
}
//method code
}
I am struggling to understand how errors instance is getting populated with validation errors in real-time. Does Spring, during compilation of the controller, inject code responsible for validation at the beginning of the createEmployee method? If so how this code would look?
I really tried to find an example of how this validation is performed in real life but it's just impossible. Help me please.
Everything happens at runtime. See the reference for more details on doing validation or this post for extra explanations.
Basically this is part of how Spring works internally. When you start your application Spring registers some beans, bean processors, can scan your classpath for annotated classes, registers those found annotated classes, builds proxies for some of them etc and uses all of them to build a context.
When handling a request, the request is handled on some predetermined execution path that starts with the DispatcherServlet, picking up other beans from the context as needed to handle the request (like validation for example) then forwarding to you controller in the createEmployee (which was registered as startup because Spring found your #RequestMapping annotations on your controller). When you return from the method the flow continues by building a model, selecting a view to display and then generating the response to the client.
For your example, Spring basically finds the #Valid annotation, looks for an already configured validator (configured by you or by a provided implementation for e.g. JSR-303), runs the validator and stores the validation result inside the Errors object. It does this when the request is processed, as mentioned above, it does not generate code.
If your question is to know exactly how Spring does this, in all it's details, you could take the Spring source code and have a look/debug it.

Categories