Add a global error in Spring MVC from a non-controller location - spring

Somewhere in my Spring MVC app I need to add a global error. I no longer have access to any BindingResult, I only have my Request. My error is not the result of any binding issues, it's a global condition. Then I need to attach my new Errors object to the "errors" Req. attribute, so the JSP can display it.
But how to do this? I can't do
Errors errors = new Errors();
errors.reject(....);
request.setAttribute("errors", errors);
because Errors is an interface. The implementations all have to do with 'Binding',like BindException, AbstractBindingResult, MapBindingResult, etc. These all have nothing to do with my case, I don't have a binding field error, it's a general error msg.
Any tips?

Our resolution to this problem: The proper way to handle EXCEPTIONS (rather than VALIDATION errors) is to keep track of our own, custom Request Attribute that we display ourselves in our error area on the JSP.
BindingResult/Errors/etc. are all Binding-related, we can't hack it to handle general exception errors.
We just add a custom Request Attr. called "exceptions" and then our Error section checks for this additonal attribute list to display.
SpringMVC doesn't provide its own 'generic' Error collection.

Related

How to map an input validation error to a specific error code in Spring

I am having a case in which I would like to do some input validation on the #RequestParams of an endpoint.
I know about Validators and Custom Validators, and my current strategy implies creating a wrapper object around the RequestParams, a custom validator and apply class level the annotation that triggers the custom validation.
My problem is that the custom validation is implementing ConstraintValidator, which means that the validator will either return true or false, and an error will be created by Spring with some text (I also know that I can change this text). My desire, however, is to create a custom payload back to the client. An example could be
class MyError {
int code;
String message;
}
The way to return this object is through a #ControllerAdvice Error handler, which understands that a ConstraintValidationException should return my custom payload format. However, I need to return different codes and messages for different reasons on the input validation failed. For example:
A Field is empty -> code XXX
A Field is formatted incorrectly -> code YYY
As far as I know, there is little customization possible on the exception that is reachable from my #ControllerAdvice, I can get a list of errors that happened but I cannot easily determine what happened. (Technically I can, but it would have to be based on the message string, which is pretty weak).
Is there a way to provide extra data to the Exception so I can distinguish from the #ControllerAdvice what happened and create my custom error response accordingly?
Am I approaching it the wrong way?
You can intercept the BindException (https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/validation/BindException.html) with the #ExceptionHandler. This contains detailed information about all validation errors. For example, with e.getFieldErrors() you can access all errors associated with fields.
For example, for a field
#MyConstraint
#Length(min = 3)
private String field;
that failed validation you get the following information in the exception:
Field error in object data on field field: rejected value [XY]; codes [Length.data.field,Length.field,Length.java.lang.String,Length].
Field error in object data on field field: rejected value [XY]; codes [MyConstraint.data.field,MyConstraint.field,MyConstraint.java.lang.String,MyConstraint].
From this you can see that it failed the #Length constraint and the custom #MyConstraint constraint.

Displaying model state errors after ajax call on Razor views

I have razor view with #Html.ValidationMessageFor helpers and jquery unobtrusive validation setup.
I want to call controller/action and to show eventual model state errors returned by action by using same validation logic that is already set in place.
I've made some code that does it but I was wondering if there is already way to do it automatically, i.e. if I capture HTTP Bad Request as AJAX response, I want to take out model state errors from response body and plug them in to unobtrusive validation.
I'm looking for complete recommended solution, not workarounds :)
Thanks!
You can return errors with Json result (How to get all Errors from asp.net mvc modelState?):
var allErrors = ModelState.Values.SelectMany(v => v.Errors);
Then manually show errors. Get form validator:
var validator = $("form").validate();
Then check that your fields are initialized correctly, for example you can look here (optional step):
validator.settings.rules
OR
validator.settings.messages
If everything is fine, then you could show error:
validator.showErrors({"Password": "Too simple!"});
Where Password is field name and Too simple! is error message.

asp.net mvc 3 jquery adding validation message manually

I've been search for quite a while and haven't been able to find an answer to this.
I am using asp.net MVC 3 with unobtrusive validation. My model is bound with data annotations for simple validation (required fields, regex, etc..). However, I have more complex validation that occurs on the server. I'm doing an ajax post which returns me validation add'l messages that come from my domain model. All I want to do is put those validation messages on the form in the place of the existing ones. I don't want to use partial views since all I've really got are messages coming back and there isn't a need to refresh the whole view. Also, I'm not adding new rules or new inputs to the form so $.validator.unobtrusive.parse won't work. These are just messages I want to put on the form. The $.post call returns a list of message with which field is/was affected and the validation message.
Here's kind of what I'm looking to do
$.post(url, { someData}, function (data) {
for (message in data.Messages) {
$("#form").validate().addMessage(message.Field, message.Text);
}
});
Thanks for your help
Per request, here's a sample of the returning JSON, it's fairly simple.
{"id":0,"messages":["Level":0,"Message":"Style is required","Name":"Style"}],"operationResult":false}
messages is a list of objects that contain the severity level, the property the error belonged to and the error message. I would use the name in the messages object to match where it want on the form.
I had exactly the same requirement, I actually found the following method.
var validator = $("form").validate();
validator.showErrors({field : "Error Message"})

serving error pages in mvc: the control or the view?

Let's start by getting on the same page about MVC on the web. The control receives requests, selects a view, sends a response that it gets from the view. (Maybe the control gets data from the model, maybe the views do it themselves, I don't care.) Errors can occur, so we want to handle the errors and display a message or error page to the browser.
I'm trying to decide if these error messages/pages are part of the control or come from the view. Perhaps it is different for different kinds of errors.
some examples:
The request path is meaningless, so we want to respond with a custom "not found" page.
The control selects the "not found" view and uses its response
The control builds the "not found" page itself
.
The controller selects a view successfully, but the view throws an exception.
The view returns an error status. The controller checks the status and then selects a new view and uses its response
The view returns an error status. The controller build the error response itself.
The view handles the exception and returns a valid error page or message to the controller. The controller blindly sends it as the response.
Now, the difference between the first two options in both cases is technical/organizational, and there is probably no difference to the user. Is there a standard opinion on this (perhaps across MVC frameworks) or is the choice just arbitrary? What is the preferred method?
The controller selects a view successfully, but the view throws an exception.
If the MVC design pattern is followed, this should never happen. The only logic that should be contained in a view is solely display logic (formatting, localizing etc).
Errors should be trapped either at the model or controller level, but it's up to the controller to decide what to do with the user (redirect/404/etc).
Edit:
Of course it's not the only way.. I'm sure that you can find hacked up, bastardized code all over the place that does different things. As far as I'm concerned, yes - your views should be engineered in such a way that errors will not need to be trapped (other than ajax/javascript errors, but that's where they belong anyway).
I usually set it up so that I have a different view for each HTTP error code I want to handle, and a generic one for a catch-all. The controller will be responsible in this case to pass the error data to the view for rendering (usually as an array). Of course, this could also be done using an ErrorModel (which would be the 'correct' way of implementing it - I'm just lazy ;))
The approach I take is to allow the controller to handle your first case (route based errors). Any request made that is either unauthorized or poorly formed gets managed by a "static content" controller that renders the appropriate error view.
For your second class of errors - I'm not sure how/if the view can communicate back to the controller that it's thrown an error. I'm actually interested to see other's opinions, because as far as I know if a view encounters an error, it's up to the view to deal with it.

How to get error messages from model

Say you have a User model. The controller is attempting to create a new User. Should the controller check that the username is valid, and the password is long enough, and the first and last name are filled out, etc? Or should you pass all that data straight to the User model via a Create method? The Create method would then return a true on success, or false on failure?
If it's the latter (and I think it is), how do the error messages get sent back to the controller (so they can be displayed in a view)? Should you pass an errors array to the Create method which the model augments? Or should the model keep an internal store of errors, with appropriate accessors? I don't like either method...is there a better way?
These errors don't seem exceptional, so I don't think exception handling is appropriate.
Edit: I'm using PHP for this project, but I use Python too.
For the first question, the model should do the verifications (and use some form of error handling to notify the controller and view that errors did or did not occur). For the second, it depends on what programming language / framework you are using... What are you using?

Resources