Spring Boot Hibernate and JSR 303 - response formatting - java

Sifting through forums I can't seem to stumble into an issue solution I've been haveing with Spring Boot + JPA and JSR303 bean validation.
Simply put validation works but but when say
org.springframework.web.bind.MethodArgumentNotValidException
is thrown and then the output a consumer gets (from a rest controller) is something like this:
"timestamp": 1427658793929,
"status": 400,
"error": "Bad Request",
"exception": "org.springframework.web.bind.MethodArgumentNotValidException",
"message": "Validation failed for argument at index 1 in method: public org.springframework.http.HttpEntity<org.springframework.hateoas.Resource<org.home.project.UserInfo>>... {omitted for brevity}
This is overkill verbosity - can I intercept this to make the "message:" part of JSON more formatted and user friendly (e.g.) produce a simple list saying:
> - "messages:" { "firstName can not be Empty or Null or has to be at least 8 characters",
"lastName is a swear word...", ... }

Related

How to display error message into a Json using ResponseStatusException on Spring boot?

I have an issue displaying an error message at the moment that a bad request is triggered.
#DeleteMapping("/{projectId}/bugs/{bugId}")
public void deleteBug(#PathVariable (value = "projectId") Long projectId,
#PathVariable (value = "bugId") Long bugId){
if (!projectService.existById(projectId) || !bugService.existById(bugId)) {
throw new ResponseStatusException(HttpStatus.BAD_REQUEST, "ProjectId " + projectId + " or BugId " + bugId + " not found");
}
bugService.deleteBug(bugId);
}
This is the JSON response when I trigger the Response:
{
"timestamp": "2020-05-29T15:40:41.302+00:00",
"status": 400,
"error": "Bad Request",
"message": "",
"path": "/projects/3/bugs/2" }
As you can see the message is not appearing. If I change the HttpStatus in the code it actually works but for some reason, the message is not working.
I checked the constructor of the class and it actually allows only the status and the reason.
Am I missing something or is it a bug in the ResponseStatusException class?
I also encountered this. It's not a bug, so downgrading is not the best resolution. The Spring Boot 2.3.0 release notes explain:
Changes to the Default Error Page's Content
The error message and any binding errors are no longer included in the
default error page by default. This reduces the risk of leaking
information to a client. server.error.include-message and
server.error.include-binding-errors can be used to control the
inclusion of the message and binding errors respectively. Supported
values are always, on-param, and never.
So for example, in your application configuration you can set these to show message but not trace output (YAML example):
server:
error:
include-message: ALWAYS
include-stacktrace: NEVER

How to parse FirebaseAuthException exception message (Admin SDK Java)?

I'm using Firebase Admin SDK Java API v6.12.2.
I call FirebaseAuth.getInstance().generatePasswordResetLink(email, actionCodeSettings) to generate a password reset link for users. If the email isn't registered, I get a big blob of text with embedded JSON from e.getMessage().
The looked at the FirebaseAuthException doc and it only exposes one method e.getErrorCode(), which in this case returns internal-error.
I can certainly parse this text to look for "EMAIL_NOT_FOUND" and translate it into a user-friendly message. But isn't that a very clumsy error message? At least, there should have been methods to return the error code 400, and a simple String message, and the details could go into a JSON object.
What is the recommended approach here by the Firebase team and how are other developers handling it?
Output of e.getMessage():
Unexpected HTTP response with status: 400; body: {
"error": {
"code": 400,
"message": "EMAIL_NOT_FOUND",
"errors": [
{
"message": "EMAIL_NOT_FOUND",
"domain": "global",
"reason": "invalid"
}
]
}
}

Google Cloud Dataflow input collections number of elements added is not consistent with number of elements inserted into BigQuery?

I currently have a Google Cloud Dataflow job that consumes messages from a Google Cloud PubSub subscription and writes the results to BigQuery using Load Jobs every 2 minutes. However, I seem to be actually writing less rows to BigQuery than the number of elements added displayed in the Google Cloud Dataflow UI for the WriteToBigQuery step:
The amount of rows written to BigQuery were only around 200,000. After looking through the StackDriver logs, there were a few Info level logs stating that the job failed and a retry was taking place, but there were no indication of why the job was failing. There were no explicit errors that occurred, apart from one with the following message:
"Request failed with code 409, performed 0 retries due to IOExceptions, performed 0 retries due to unsuccessful status codes, HTTP framework says request can be retried, (caller responsible for retrying)"
The HTTP resource included with the message was:
{ "error": {
"code": 401,
"message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"errors": [
{
"message": "Login Required.",
"domain": "global",
"reason": "required",
"location": "Authorization",
"locationType": "header"
}
],
"status": "UNAUTHENTICATED"}}
The error was also followed by another Info level log with the following message (along with the 409 Exception code again):
BigQuery job {jobId=insert_job_id, location=US, project=project_id} already exists, will not retry inserting it:
There should not be any authentication errors as otherwise none of the rows would be written to BigQuery so I am rather confused here. Is there any other way to diagnose the problem?

REST api for field validation

I have to create a couple of web services for validating possible values of given fields. I'm contemplating having something like:
POST /entity/fieldName body { fieldValues }
where the POST will return 400 (Bad request) if the arguments are invalid and 422 (Unprocessable entity) otherwise. However I do not really like the 422 response part very much since it makes the request always return an error. On the other hand since I'm only doing validation and this is a POST I don't want to actually create a new resource on the server (i.e. return 200). Is there another HTTP method / API endpoint that is better suit for this? For what it's worth I will be checking that the entity field with <fieldName> has its value in a given range.
If all you do is validating, then I think you should send 422 by validation error and 200 by validation success. The POST does not mean you have to always create a new entity.
The action performed by the POST method might not result in a
resource that can be identified by a URI. In this case, either 200
(OK) or 204 (No Content) is the appropriate response status, depending
on whether or not the response includes an entity that describes the
result.
If a resource has been created on the origin server, the response
SHOULD be 201 (Created) and contain an entity which describes the
status of the request and refers to the new resource, and a Location
header (see section 14.30).
https://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
I'm prefer google's api error response style.
So my service sends error response as json or xml and 400 Bad request error code:
{
"status": "INVALID_REQUEST",
"type": "ERROR_MSG",
"data": {
"request": "/v2/data?age=23d",
"errors": [
"age: not a number"
]
},
"time": -1
}
otherwise 200 and corresponding message

How to change swagger response for exception

I am using spring boot with swagger for REST API services. The swagger returns the response in the following format when exception occurs
{
"timestamp": 1449742584285,
"status": 500,
"error": "Internal Server Error",
"exception": "com.foo.exception.NotFoundException",
"message": "User with id 1 not found",
"path": "/user/1"
}
Instead of returning the detailed response I want to show only the message. Also all the time the server tkhrows an RuntimeException.
How to achieve swagger to retun only the message.

Categories