Error while I configure my personal message in JWT access - java

I'm trying to handle JWT requests when they are expired or not valid...
But when I tryning to catch the error I get this:
Unable to handle the Spring Security Exception because the response is already committed.
and I can't use a code like this:
response.sendError(HttpServletResponse.SC_BAD_REQUEST, "Invalid JWT Token");
I still get error 500 in postman

Your question is not clear enough to decide...
but I suppose you just need two things:
1- create a #ControllerAdvice class for your exceptions handling, this class should handle the responses displayed in postman when an exception occurred.
Read about Spring Exception Handling https://javatodev.com/microservices-exception-handling/
and here are some outlines of that class:
#ControllerAdvice
public class ExceptionsController extends RunTimeExceptions{
#ExceptionHandler(Exception.class)
public final ResponseEntity<String> handleAllExceptions(){
return new ResponseEntity<>(response, HttpStatus.OK);
}
}
2- second of all is very obvious, you should surround your statements with try... catch
and throw a new exception in the catch clause to invoke the ExceptionHandler class that we created.

Related

Handle exceptions in a rest controller in Spring Boot

I create REST web-service with Spring Boot.
I would like to know what is a better way to handle exceptions in a controller. I have seen other questions and didn’t found an answer.
My controller:
#GetMapping
public ResponseEntity<?> saveMyUser(){
MyUser myUser = new MyUser(“Anna”);
//throws SQLException
MyUserDetails userDetails = userService.saveMyUser(myUser);
//if successful
return ResponseBody.ok(userDetails);
}
saveMyUser() method of UserService:
public MyUserDetails saveUser(MyUser) throws SQLException {...}
So at this point I have at least 2 simple options:
Add exception to method signature.
Here I may rely on Spring Boot to pass all information about exception and status code to a client. However do not know if it is a reliable approach.
Surround with try/catch and pass all information about exceptions manually.
What is a better simple way?
You can create an additional class with #ControllerAdivce annotation and later you will be able to write custom response logic for each exception e.g:
#ControllerAdvice
public class GlobalExceptionHandler {
#ExceptionHandler({SQLException.class})
public ResponseEntity<Object> sqlError(Exception ex) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Some SQL exception occured");
}
}
Also, you can extend ResponseEntityExceptionHandler and override the default behavior for mapping from exceptions to HTTP response.
Also, take a look at this, it holds very usefull information for your case.

How could we use #ExceptionHandler with spring web flux?

In spring web we could use annotation #ExceptionHandler for handling server and client errors for controllers.
I've tried to use this annotation with web-flux controller and it still worked for me, but after some investigation I've found out here
The situation with Spring Web Reactive is more complicated. Because
the reactive streams are evaluted by a different thread than the one
that executes the controllers method, the exceptions won’t be
propagated to the controller thread automatically. This means that the
#ExceptionHandler method will work only for exceptions that are thrown
in the thread that handles the request directly. Exceptions thrown in
the stream will have to be propagated back to the thread if we want to
use the #ExceptionHandler feature. This seems like a bit of a let down
but at the time of writing this Spring 5 is still not released so
error handling might still get better.
So my question is how to propagate back exception to the thread. Is there a good example or article about using #ExceptionHandler and Spring web flux?
Updated:
From spring.io it looks like it's supported, but still lack general understanding
Thanks,
Now it is possible to use the #ExceptionHandler as well as #RestControllerAdvice or even #ControllerAdvice in Spring WebFlux.
Example:
Add the webflux dependency
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Create your class ExceptionHandler
#RestControllerAdvice
public class ExceptionHandlers {
private static final Logger LOGGER = LoggerFactory.getLogger(ExceptionHandlers.class);
#ExceptionHandler(Exception.class)
#ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
public String serverExceptionHandler(Exception ex) {
LOGGER.error(ex.getMessage(), ex);
return ex.getMessage();
}
}
Create a Controller
#GetMapping(value = "/error", produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
public Mono<String> exceptionReturn() {
return Mono.error(new RuntimeException("test error"));
}
Example extracted here:
https://ddcode.net/2019/06/21/spring-5-webflux-exception-handling/
You can use #ExceptionHandler annotated methods to handle errors that happen within the execution of a WebFlux handler (e.g., your controller method). With MVC you can indeed also handle errors happening during the mapping phase, but this is not the case with WebFlux.
Back to your exception propagation question, the article you're sharing is not accurate.
In reactive applications, the request processing can indeed hop from one thread to another at any time, so you can't rely on the "one thread per request" model anymore (think: ThreadLocal).
You don't have to think about exception propagation or how threads are managed, really. For example, the following samples should be equivalent:
#GetMapping("/test")
public Mono<User> showUser() {
throw new IllegalStateException("error message!");
}
#GetMapping("/test")
public Mono<User> showUser() {
return Mono.error(new IllegalStateException("error message!"));
}
Reactor will send those Exceptions as error signals as expected in the Reactive Streams contract (see the "error handling" documentation section for more on that).
not an exact answer to the original question, but a quick way to map your exceptions to http response status is to throw org.springframework.web.server.ResponseStatusException / or create your own subclasses...
Full control over http response status + spring will add a response body with the option to add a reason.
{
"timestamp": 1529138182607,
"path": "/api/notes/f7b.491bc-5c86-4fe6-9ad7-111",
"status": 400,
"error": "Bad Request",
"message": "For input string: \"f7b.491bc\""
}
The following global error handler did the trick for me:
import org.springframework.web.server.ResponseStatusException;
#Slf4j
#RestControllerAdvice
#ConditionalOnWebApplication(type = ConditionalOnWebApplication.Type.REACTIVE)
public class MyCustomReactiveErrorHandling {
#ExceptionHandler(MyCustomNotFoundException.class)
public void handleMyCustomException(MyCustomNotFoundException ex) {
throw new ResponseStatusException(404, "Data not found!", ex);
}
}
Throwing my exceptions returns the correct http status code at the rest service.

JAX-RS service throwing a 404 HTTPException but client receiving a HTTP 500 code

I have a RESTful resource, which calls a EJB to make a query. If there is no result from the query, the EJB throws a EntityNotFoundException. In the catch block, it will be thrown a javax.xml.ws.http.HTTPException with code 404.
#Stateless
#Path("naturezas")
public class NaturezasResource {
#GET
#Path("list/{code}")
#Produces(MediaType.APPLICATION_JSON)
public String listByLista(
#PathParam("code") codeListaNaturezasEnum code) {
try {
List<NaturezaORM> naturezas = this.naturezaSB
.listByListaNaturezas(code);
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(naturezas);
} catch (EntityNotFoundException e) { // No data found
logger.error("there is no Natures with the code " + code);
throw new HTTPException(404);
} catch (Exception e) { // Other exceptions
e.printStackTrace();
throw new HTTPException(500);
}
}
}
When I call the Rest Service with a code for which there are no results, the log message inside the EntityNotFoundException catch block is printed. However, my client receives a HTTP code 500 instead a 404. Why am I not receiving a 404 code?
Thanks,
Rafael Afonso
javax.xml.ws.http.HTTPException is for JAX-WS. JAX-RS by default doesnt know how to handle it unless you write an ExceptionMapper for it. So the exception bubbles up to the container level, which just sends a generic internal server error response.
Instead use WebApplicationException or one of its subclasses. Here a list of the exceptions included in the hierarchy, and what they map to (Note: this is only in JAX-RS 2)
Exception Status code Description
-------------------------------------------------------------------------------
BadRequestException 400 Malformed message
NotAuthorizedException 401 Authentication failure
ForbiddenException 403 Not permitted to access
NotFoundException 404 Couldn’t find resource
NotAllowedException 405 HTTP method not supported
NotAcceptableException 406 Client media type requested
not supported
NotSupportedException 415 Client posted media type
not supported
InternalServerErrorException 500 General server error
ServiceUnavailableException 503 Server is temporarily unavailable
or busy
You can find them also in the WebApplicationException link above. They will fall under one of the direct subclasses ClientErrorException, RedirectionException, or ServerErrorException.
With JAX-RS 1.x, this hierarchy doesn't exist, so you would need to do something like #RafaelAlfonso showed in a comment
throw new WebApplicationException(Response.Status.NOT_FOUND);
There are a lot of other possible constructors. Just look at the API link above

Spring Boot - Error Controller to handle either JSON or HTML

I have a spring boot application.
I have a custom error controller, that is mapped to using ErrorPage mappings. The mappings are largely based on HTTP Status codes, and normally just render a HTML view appropriately.
For example, my mapping:
#Configuration
class ErrorConfiguration implements EmbeddedServletContainerCustomizer {
#Override public void customize( ConfigurableEmbeddedServletContainer container ) {
container.addErrorPages( new ErrorPage( HttpStatus.NOT_FOUND, "/error/404.html" ) )
}
And my error controller:
#Controller
#RequestMapping
public class ErrorController {
#RequestMapping( value = "/error/404.html" )
#ResponseStatus(value = HttpStatus.NOT_FOUND)
public String pageNotFound( HttpServletRequest request ) {
"errors/404"
}
This works fine - If I just enter a random non-existent URL then it renders the 404 page.
Now, I want a section of my site, lets say /api/.. that is dedicated to my JSON api to serve the errors as JSON, so if I enter a random non-existent URL under /api/.. then it returns 404 JSON response.
Is there any standard/best way to do this? One idea I tried out was to have a #ControllerAdvice that specifically caught a class of custom API exceptions I had defined and returned JSON, and in my standard ErrorController checking the URL and throwing an apprpriate API exception if under that API URL space (but that didn't work, as the ExceptionHandler method could not be invoked because it was a different return type from the original controller method).
Is this something that has been solved?
The problem was my own fault. I was trying to work out why my #ExceptionHandler was not able to catch my exception and return JSON - As I suggested at the end of my question, I thought I was having problems because of conflicting return types - this was incorrect.
The error I was getting trying to have my exception handler return JSON was along the lines of:
"exception": "org.springframework.web.HttpMediaTypeNotAcceptableException",
"message": "Could not find acceptable representation"
I did some more digging/experimenting to try to narrow down the problem (thinking that the issue was because I was in the Spring error handling flow and in an ErrorController that was causing the problem), however the problem was just because of the content negotiation stuff Spring does.
Because my errorPage mapping in the web.xml was mapping to /error/404.html, Spring was using the suffix to resolve the appropriate view - so it then failed when I tried to return json.
I have been able to resolve the issue by changing my web.xml to /error/404 or by turning off the content negotiation suffix option.
Now, I want a section of my site, lets say /api/.. that is dedicated
to my JSON api to serve the errors as JSON, so if I enter a random
non-existent URL under /api/.. then it returns 404 JSON response.
Is there any standard/best way to do this? One idea I tried out was to
have a #ControllerAdvice that specifically caught a class of custom
API exceptions I had defined and returned JSON, and in my standard
ErrorController checking the URL and throwing an apprpriate API
exception if under that API URL space (but that didn't work, as the
ExceptionHandler method could not be invoked because it was a
different return type from the original controller method).
I think you need to rethink what you are trying to do here. According to HTTP response codes here
The 404 or Not Found error message is an HTTP standard response code
indicating that the client was able to communicate with a given
server, but the server could not find what was requested.
So when typing a random URL you may not want to throw 404 all the time. If you are trying to handle a bad request you can do something like this
#ControllerAdvice
public class GlobalExceptionHandlerController {
#ExceptionHandler(NoHandlerFoundException.class)
#ResponseStatus(value = HttpStatus.BAD_REQUEST)
#ResponseBody
public ResponseEntity<ErrorResponse> noRequestHandlerFoundExceptionHandler(NoHandlerFoundException e) {
log.debug("noRequestHandlerFound: stacktrace={}", ExceptionUtils.getStackTrace(e));
String errorCode = "400 - Bad Request";
String errorMsg = "Requested URL doesn't exist";
return new ResponseEntity<>(new ErrorResponse(errorCode, errorMsg), HttpStatus.BAD_REQUEST);
}
}
Construct ResponseEntity that suites your need.

Spring Rest Client Exception Handling

I am using spring RestTemplate to consume rest services(exposed in spring rest). I am able to consume success scenarios. But for negative scenarios, service returns error messages and error codes. I need to show those error messages in my web page.
For e.g. for invalid request, service throws HttpStatus.BAD_REQUEST with proper messages. If i put try-catch block it goes to catch block and I am not able to get ResponseEntity object.
try {
ResponseEntity<ResponseWrapper<MyEntity>> responseEntity = restTemplate.exchange(requestUrl, HttpMethod.POST, entity,
new ParameterizedTypeReference<ResponseWrapper<MyEntity>>() {
});
responseEntity.getStatusCode();
} catch (Exception e) {
//TODO How to get response here, so that i can get error messages?
e.printStackTrace();
}
How to get ResponseWrapper for exception case?
I read about CustomRestTemplate and ResponseExtractor from here but could not decide which one is best for my case.
I found solution. HttpClientErrorException worked for me.
It has e.getResponseBodyAsString() function which returns ResponseBody.
You might want to distinguish between:
HttpClientErrorException (HTTP-Status >=400) or HttpServerErrorException (HTTP-Status >= 500) or even RestClientException.
Further on there is a good doc about defining your own ErrorHandler, see this link

Categories

Resources