Spring Data REST Bean Validation - java

Consider a Person entity with a property name that is annotated as #NotNull. Then a simple PersonRepository and this repo exposed with Spring Data Rest.
When I POST to create a new Person, if the name property is null a ValidationException occurs as expected. But what I actually get on the client is an Internal Server Error (500) and the message is a TransactionSystemException that happened much later in the exception chain.
What I'd expect to get is a Bad Request (400) with the actual ValidationException and all it's useful information so the client can know what's wrong with the posted data.
There seems to be a way to attach custom validators with SDR as explained here. But the thing is, this is not a custom validator, it's a standard bean validation that happens when the repository is asked to save data. So I'm not really sure how those two come together.
So questions:
What are my options to let the client know what's wrong with the submitted data when using SDR?. Things like what fields are invalid and what's the error for each field would be awesome.
Are there any examples about this anywhere?
Thanks a lot.

What you need is a proper ExceptionHandler, it will handle back end exceptions and send meaningful rich messages (json/xml) to the front end client.
Take a look a this git repository

Related

how to create json response in spring boot java like this as shown when the following attributes are not present in json request

I am creating an controller where there is certain attributes in json which is an doing in postman a POST request like this if all attributes are posted then its fine
if one then is missing then it would look like this
i want this response when some attribute is missing how to implement this
This is normally implemented in two steps:
Implement a validation mechanism for the method that handles the incoming request. Normally you would throw an exception here if the input is incorrect, in your example a missing JSON key.
Implement a global error handler that will process the exception from point 1 and format the response as JSON.
For point 1 the usual choice is the Java Bean Validation framework because it's integrated with Spring Boot and allows to define validation constraints with annotations like #NotEmpty. You can take a look at this example.
For point 2 the usual choice is #RestControllerAdvice or #ControllerAdvice. You would have to understand your service web server setup to implement it properly e.g. it might behave differently if you use Spring WebFlux.

What to return to from a REST API when updates fail

I am writing a web application using Spring Boot that frequently updates data on the back end and returns the updated object to reflect the update on the front end.
The question I have is what to return from my methods if the update should fail for some reason.
I am currently returning the object as it was received should it fail but as it stands the state on the front end would not reflect the failure on the back end in the case that it occurs.
I want to return the object to update the state but doing so prevents me from returning a String or HttpStatus indicating a problem doesn't it? Returning the old object doesn't seem a good solution either.
You can throw an exception in this case of failure from your REST controller.
To handle this exception, Spring provides ResponseEntityExceptionHandler callback class with the help of which you can handle the thrown exception and set different headers in the response entity.
So on client-side, you can recognise that some failure is occurred on server side.
You can set HttpStatus as HttpStatus.INTERNAL_SERVER_ERROR and add more details in the body.
The question I have is what to return from my methods if the update should fail for some reason.
You first need to determine whether the error was caused by the client or by the server, then you can determine the most suitable status code to be returned, either in the 4xx or in the 5xx range. See this answer which may give you some insights.
Instead of returning the request request back in the response, you should return a payload that describes what the problem was. Consider, for example, the payload defined in the RFC 7807 along with the application/problem+json media type.
Finally, this answer may give you insights on how to map an exception to a HTTP status code in Spring:
You can map exceptions to responses by annotating an exception class with #ResponseStatus.
It also gives you the possibility to implement a HandlerExceptionResolver or extend one of the existing implementations, such as the AbstractHandlerExceptionResolver.
Another approach would be using a ResponseEntityExceptionHandler annotated with #ControllerAdvice and define the handled exceptions by annotating the implemented method with #ExceptionHandler.

Spring boot REST server throws HttpRequestMethodNotSupportedException on POST of unexpected request body with #Validated

Does Spring throw HttpRequestMethodNotSupportedException when a request body is not valid and #Valid (or #Validated) is used? I really expected MethodArgumentNotValidException.
Details: I have a small REST server built on Spring-Boot version 2.2.4. One of the methods looks like this:
#PostMapping("/yapp")
public Yapp kickYapp(#Validated #RequestBody YappDescriptor yappDescriptor) {
logger.debug("kickYapp descriptor {}", yappDescriptor);
doWork(yappDescriptor);
}
The YappDescriptor has annotations like "required" but nothing for valid values, ranges, etc. When I POST a well-formed JSON object with values for all the required fields as defined in the YappDescriptor POJO, the Spring controller method is found and invoked as expected.
I tried a couple error scenarios:
1) If I POST a well-formed JSON object that has only null values for the expected fields, the method is found and entered as expected.
2) If I POST a well-formed JSON object with a key that does not match any of the POJO's fields, the method is NOT found and entered. In watching class org.springframework.web.servlet.mvc.method.annotation.ResponseEntityExceptionHandler I see the exception is HttpRequestMethodNotSupportedException and the server answers 405 "Request method 'POST' not supported".
In this controller class, kickYapp is the only POST-mapped method at the specified path, so I think that answer is pretty confusing. Altho I'm definitely sending a bad request (unexpected data), I am surprised my POST-mapped method is not found and invoked.
This post Validating if request body in HTTP POST request is null in Spring Boot controller suggests I should be seeing HttpMessageNotReadableException which would be helpful, but I never get that exception.
Many other questions on SO seem to be about enabling validation of request bodies, like Spring 4.1.7 validate request body , but I seem to be past that.
Thanks in advance for helping me understand this behavior and maybe improve the server to help my users discover their errors more easily (which saves me time :). Thought I could maybe extend that method to accept a BindingResult parameter and report errors that way, but that's a non-starter if the controller method is never entered.
Update to respond to comments: yes I could have used #Valid. In my tests annotation #javax.validation.Valid and #org.springframework.validation.annotation.Validated have the same effect, both turned on validation of the RequestBody parameter.
why not use #Valid?
like so:
public ResponseEntity<SalaryDto> update(#Valid #RequestBody SalaryDto subject)
and don't forget to use javax.validation validation annotations in your request body object

Spring: When to chose which validation method?

I have a Spring application with a JPA Repository. Now I'd like to add some validations. I found several solutions but none works perfect and I don't know which methode should be used in which case:
1.) Im using validation annotations (e.g. #NotNull) in my model object. But this generates a not usefull rest error response like ""Internal Server Error","message":"Could not commit JPA transaction; "
2.) I'm using the 'Validator' interface for custom validations but I get the spring "compiler" error "Validator has incorrect spelling"
3.) Some tutorials use 'ConstraintValidator' interface
4.) Some tutorials write custom rest methods for validations.
When should I use which and how can I solve my problems?
This is how you can manage it and easy is:
Define all your custom message in /messages/messages.properties under resources folder.
so if you error property is: error.user.name = User name can not be null.
then call your specific property in your pojo for that property.
#NotNull(message = "error.user.name")

GenericType unmarshalling fails in spring restful

Given below is the scenario in which I am facing difficulty, I am using Restful based webservice in spring MVC where I am ineracting with JSON.
I have a class :
RegexObject and another class RegexObjectDME extends RegexObject.
RegexObject is in one common project, which is being used as it is in webservice consumer and RegexObjectDME in webservice provider.
Now, There is another bean in the same common project, Say HDTaskInfoBean ,
There are two child beans extending HDTaskInfoBean as
HDTaskInfoBeanClient extends HDTaskInfoBean<RegexObject>
and
HDTaskInfoBeanAgent extends HDTaskInfoBean<RegexObjectDME> .
The RegexObjectDME and RegexObject have same properties except a few methods.
HDTaskInfoBeanClient and HDTaskInfoBeanAgent too have same properties and there is generic setter getters for regexObject and regexObjectDME. The T type property name is regexArray.
HDTaskInfoBeanClient is used while making request and HDTaskInfoBeanAgent is used on webservice side.
I am getting the following exception:
Syntactical Error.
Another Scenario I used string as requestbody and tried to unmarshall it into Java Object using Gson() , It gave error:
Request processing failed; nested exception is java.lang.UnsupportedOperationException: Expecting parameterized type, got class com.*.
Are you missing the use of TypeToken idiom?
Please help, I want to use **HDTaskInfoBeanClient ** in Request and HDTaskInfoBeanAgent on webservice provider side. If there is any alternative to it, Kindly suggest.
Thanks in advance :)
I am not sure that why did this weird behavior was shown by default message converter which Comes with Spring Framework.
I found that one of the very good message converter from JSON to Object and back is GSON(A utility by Google) .
One reliable approach to handle such a problem is write your own Custom Message Converter by overriding a class and Using GSON in that. Here is the link for such a solution. I hope it helps you as a solution and would be more reliable.
Regards,
Rahul

Categories