handleConstraintViolationException in a controller advice - java

I use spring boot 3, I search to centralize error handling about validation
public record RepoPubRecord(
#NotEmpty(groups={Intranet.class,Extranet.class}
Long idRepoPub,
#NotEmpty(#NotEmpty(groups={Extranet.class})
String pubSib,
#NotNull(groups={Intranet.class,Extranet.class}
PubRecord pub){
}
In a method of one of my service
public void update(Repo repot, RepoPubRecord repoPubRecord){
Set<ConstraintViolation<RepoPubRecord>> violations = validator.validate(repoPubRecord, Extranet.class);
if (!violations.isEmpty()) {
throw new ConstraintViolationException(violations);
}
....
}
I would like to manage this error globally
#ControllerAdvice
public class GlobalExceptionHandler extends ResponseEntityExceptionHandler {
protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers,HttpStatus status, WebRequest request) {
String error = ex.getParameterName() + " parameter is missing.";
return new ResponseEntity<Object>(new MissingServletRequestParameterException(error, ex.getParameterType()), HttpStatus.BAD_REQUEST));
}
#ExceptionHandler(ConstraintViolationException.class)
protected ResponseEntity<?> handleConstraintViolationException(ConstraintViolationException ex, HttpServletRequest request){
try {
Set<String> messages = ex.getConstraintViolations().stream().map(ConstraintViolation::getMessage).collect(Collectors.toSet());
return new ResponseEntity<>(new ConstraintViolationException(messages), HttpStatus.BAD_REQUEST);
} catch (Exception e) {
return new ResponseEntity<>(new ConstraintViolationException<>(new HashSet<String>().add(ex.getMessage())), HttpStatus.INTERNAL_SERVER_ERROR);
}
}
}
I just don't understand what i'm suppoing to put in the ResponseEntity to get information of what has failed

Related

ConstraintViolationException is not called by ResponseEntityExceptionHandler

I have a Spring Boot RESTful API and I am creating the error system for my API. I want to be able to catch each errors and each validation exceptions in my class that extend ResponseEntityExceptionHandler.
#ControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
HttpHeaders defaultHttpHeaders = new HttpHeaders();
public RestResponseEntityExceptionHandler() {
this.defaultHttpHeaders.setContentType(MediaType.APPLICATION_PROBLEM_JSON);
}
#ExceptionHandler({ ConstraintViolationException.class })
protected ResponseEntity<Object> handleConstraintViolation(ConstraintViolationException ex, WebRequest request) {
logger.info("CONSTRAINT VIOLATION EXCEPTION");
List<ValidationErrorResponse.ValidationError> errors = new ArrayList<>();
List<String> tests = new ArrayList<>();
for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
tests.add(violation.getRootBeanClass().getName() + " " +
violation.getPropertyPath() + ": " + violation.getMessage());
}
return new ResponseEntity<Object>(tests, new HttpHeaders(), HttpStatus.MULTI_STATUS);
}
#ExceptionHandler(value = {IncidentologistNotFoundException.class, UserNotFoundException.class, ReturnRequestNotFoundException.class})
protected ResponseEntity<Object> handleEntityNotFoundException(RuntimeException ex, WebRequest request) {
ErrorResponse errorResponse = new ErrorResponse(
ErrorTypes.ENTITY_NOT_FOUND,
HttpStatus.NOT_FOUND,
"The entity has not been found",
ex.getMessage()
);
return handleExceptionInternal(ex, errorResponse, new HttpHeaders(), errorResponse.getStatus(), request);
}
}
The handleEntityNotFoundException() works as excepted.
However, handleConstraintViolation() which is supposed to catch all the exceptions related to the ConstraintViolation is not called at all. I do not know why, because, I marked my #RequestBody with the #Valid annotation in my controller:
#PostMapping("/return-requests")
ResponseEntity<?> postReturnRequest(#Valid #RequestBody MutateReturnRequestDto newReturnRequest) {
Incidentologist requester = incidentologistRepository.findById(newReturnRequest.getIcRequesterId())
.orElseThrow(() -> new IncidentologistNotFoundException(newReturnRequest.getIcRequesterId()));
ReturnRequest returnRequest = manuallyConvertToEntity(newReturnRequest);
returnRequest.setIcRequester(requester);
ReturnRequest createdReturnRequest = returnRequestService.createReturnRequest(returnRequest);
return new ResponseEntity<>(convertToDto(createdReturnRequest), HttpStatus.CREATED);
}

How to get rid of spring boot's default exception?

I am new to spring boot and I am adding custom exceptions to my controller through controllerAdvisor.
In MyController.class, I am doing three operations
Get all the tickets present in the database.
Get ticket by id
Create the ticket.
Below mentioned class is MyController.class.
#RestController
public class MyController {
#Autowired
private TicketServiceImpl ticketService;
#GetMapping(/ticket)
public ResponseEntity<?> getAllTickets() {
List<Ticket> list=(List<Ticket>)ticketService.findAll();
return new ResponseEntity<>(list, HttpStatus.OK);
}
#GetMapping(Constant.BASE_URL+"/{id}")
public ResponseEntity<Ticket> getTicketById(#PathVariable("id") long id) {
Optional<Ticket> ticketData = Optional.ofNullable(ticketService.get(id));
if(!ticketData.isPresent()){
throw new RecordNotFoundException("id-" + id);
}
return new ResponseEntity<>(ticketData.get(), HttpStatus.OK);
}
#PostMapping(/ticket)
public ResponseEntity<Ticket> createTicket(#RequestBody Ticket ticket) {
ticketService.save(ticket);
return new ResponseEntity<>(ticket, HttpStatus.CREATED);
}
}
Below class is my custom exception handle class where I am handling my custom exceptions.
#SuppressWarnings({"unchecked","rawtypes"})
#ControllerAdvice
public class CustomExceptionHandler extends ResponseEntityExceptionHandler {
#ExceptionHandler(Exception.class)
public final ResponseEntity<Object> handleAllExceptions(Exception ex, WebRequest request) {
List<String> details = new ArrayList<>();
details.add(ex.getLocalizedMessage());
ErrorResponse error = new ErrorResponse("Server Error", details);
return new ResponseEntity(error, HttpStatus.INTERNAL_SERVER_ERROR);
}
#ExceptionHandler(RecordNotFoundException.class)
public final ResponseEntity<Object> handleUserNotFoundException(RecordNotFoundException ex, WebRequest request) {
List<String> details = new ArrayList<>();
details.add(ex.getLocalizedMessage());
ErrorResponse error = new ErrorResponse("Record Not Found", details);
return new ResponseEntity(error, HttpStatus.NOT_FOUND);
}
#Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
List<String> details = new ArrayList<>();
for(ObjectError error : ex.getBindingResult().getAllErrors()) {
details.add(error.getDefaultMessage());
}
ErrorResponse error = new ErrorResponse("Validation Failed", details);
return new ResponseEntity(error, HttpStatus.BAD_REQUEST);
}
}
The below class is specific for not found exceptions.
#ResponseStatus(HttpStatus.NOT_FOUND)
public class RecordNotFoundException extends RuntimeException {
public RecordNotFoundException(String exception) {
super(exception);
}
}
In application.properties, I am adding these three conditions
server.error.whitelabel.enabled=false
spring.mvc.throw-exception-if-no-handler-found=true
spring.resources.add-mappings=false
When I hit my server with GET API http://localhost:8080/ticke .It should throw bad request exception but its throwing Not found "404" exception and when I hit GET API http://localhost:8080/ticket/24, in this my id is not created. Hence, it should return resource not found exception.But, its returning, 500 internal server error.
Please advise on this.
The error you are getting is because Spring was not able to find the endpoint you are looking for. So it does not apply any controller advices to it, since it did not find a controller that maps to the requested URL.
Here is a small article explaining it in a little more detail.

How to return the ConstraintViolationException messages in the response body?

I am developing a Spring Boot based REST API. I am validating the input entities using custom ConstraintValidator annotations. My problem is that I cannot return the ConstraintViolationException messages in the response. My exception handler does not catch the exceptions (maybe because they're wrapped in another types of exceptions).
Can I please get some advice on how to handle the situation?
I've searched all over the Internet but I couldn't find a fitting solution for me and I've also wasted some hours doing so.
Example annotation:
#Documented
#Retention(RUNTIME)
#Target({FIELD, PARAMETER})
#Constraint(validatedBy = BirthDateValidator.class)
public #interface ValidBirthDate {
String message() default "The birth date is not valid.";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
Validator class:
public class BirthDateValidator extends FieldValidationBase implements ConstraintValidator<ValidBirthDate, LocalDate> {
private static final Logger LOGGER = LoggerFactory.getLogger(BirthDateValidator.class);
#Override
public void initialize(ValidBirthDate constraintAnnotation) {
}
#Override
public boolean isValid(LocalDate birthDate, ConstraintValidatorContext constraintValidatorContext) {
constraintValidatorContext.disableDefaultConstraintViolation();
LOGGER.info("Starting the validation process for birth date {}.", birthDate);
if(birthDate == null) {
constraintValidatorContext.buildConstraintViolationWithTemplate("The birth date is null.")
.addConstraintViolation();
return false;
}
//other validations
return true;
}
Model class:
public class Manager extends BaseUser {
//other fields
#Valid
#ValidBirthDate
private LocalDate birthDate;
//setters & getters
Exception handler:
#ExceptionHandler(value = ConstraintViolationException.class)
public ResponseEntity handleConstraintViolationException(ConstraintViolationException ex, WebRequest request) {
List<String> errors = new ArrayList<>();
for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
errors.add(violation.getRootBeanClass().getName() + ": " + violation.getMessage());
}
Error response = new Error(errors);
return new ResponseEntity<Object>(response, new HttpHeaders(), BAD_REQUEST);
}
The controller:
#RestController
#RequestMapping(value = "/register", consumes = "application/json", produces = "application/json")
public class RegistrationController {
#Autowired
private RegistrationService registrationService;
#PostMapping(value = "/manager")
public ResponseEntity registerManager(#RequestBody #Valid Manager manager) {
registrationService.executeSelfUserRegistration(manager);
return new ResponseEntity<>(new Message("User " + manager.getEmailAddress() + " registered successfully!"), CREATED);
}
}
I get the 400 response code, but I am not seeing any response body containing the violated constraint messages.
After some more debugging, I found out that all constraint violations were wrapped into a MethodArgumentNotValidException (because of the #Valid annotations) - I had to dig a bit inside that exception to get my information.
I've overriden the handleMethodArgumentNotValid() method from ResponseEntityExceptionHandler and this is how I got it to work:
#Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
List<String> errorMessages = new ArrayList<>();
BindingResult bindingResult = ex.getBindingResult();
List<ObjectError> errors = bindingResult.getAllErrors();
for(ObjectError error : errors) {
String message = error.getDefaultMessage();
errorMessages.add(message);
}
return new ResponseEntity<>(new Error(errorMessages), new HttpHeaders(), BAD_REQUEST);
}
Maybe this helps someone.
When the target argument fails to pass the validation, Spring Boot throws a MethodArgumentNotValidException exception. I have extracted the error message from bindingResult of this exception as shown below:
#RestControllerAdvice
public class RestResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
#Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(
MethodArgumentNotValidException ex, HttpHeaders headers,
HttpStatus status, WebRequest request) {
//to extract the default error message from a diagnostic
// information about the errors held in MethodArgumentNotValidException
Exception exception = new Exception(ex.getBindingResult().getAllErrors().get(0).getDefaultMessage());
return this.createResponseEntity(HttpStatus.BAD_REQUEST, exception, request);
}
private ResponseEntity<Object> createResponseEntity(
HttpStatus httpStatus, Exception ex, WebRequest request) {
ErrorResponse errorResponse = ErrorResponse.builder()
.timestamp(LocalDateTime.now())
.status(httpStatus.value())
.error(httpStatus.getReasonPhrase())
.message(ex.getMessage())
.path(request.getDescription(true))
.build();
return handleExceptionInternal(ex, errorResponse,
new HttpHeaders(), httpStatus, request);
}
}
ErrorResponse class:
#Data
#Builder
#NoArgsConstructor
#AllArgsConstructor
public class ErrorResponse {
private LocalDateTime timestamp;
private int status;
private String error;
private String message;
private String path;
}
The response will be 400 with body in JSON format as shown below:
{
"timestamp": "2021-01-20T10:30:15.011468",
"status": 400,
"error": "Bad Request",
"message": "Due date should not be greater than or equal to Repeat Until Date.",
"path": "uri=/api/tasks;client=172.18.0.5;user=109634489423695603526"
}
I hope this helps. If you need a detailed explanation on class-level constraint, have a look at this video.

ExceptionHandler, got java.lang.IllegalStateException: Could not resolve method parameter at index 0?

I've a problem with the ExceptionHandler of Java Spring. I have a my Exception called EntityNotFoundException, and I want call ExceptionHandler method from REST Controller when exception is thrown.
This is my REST Controller method code:
#ExceptionHandler(Exception.class)
public ResponseEntity insertTicket(#Valid #RequestBody Ticket ticket, #AuthenticationPrincipal Principal principal) throws EntityNotFoundException {
ticket.setCreationTimestamp(Instant.now());
ticket.setSource(TicketSource.CLIENT);
ticket.setCurrentTicketStatus(TicketStatus.VALIDATION);
User customer = userController.findUserByUsername(principal.getName());
ticket.setCustomer(customer);
try {
ticket.setAttachments(savedFiles(
ticket.getAttachments(),
ticket.getCustomer().getUsername()
));
} catch (FileUploadException e) {
return CommonResponseEntity.NotFoundResponseEntity("ENTITY_NOT_FOUND");
}
ticketController.insertTicket(ticket);
mailSenderController.sendMail(customer.getEmail(), "TICKET_OPENED");
return CommonResponseEntity.CreatedResponseEntity("CREATED");
}
This is my Exception Handler code:
#EnableWebMvc
#ControllerAdvice
#RestControllerAdvice
public class InterceptedResponseEntityExceptionHandler extends
ResponseEntityExceptionHandler {
#Override
protected ResponseEntity<Object> handleMethodArgumentNotValid(MethodArgumentNotValidException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
BindingResult bindingResult = ex.getBindingResult();
List<MethodArgumentFieldError> methodArgumentFieldErrors = bindingResult
.getFieldErrors()
.stream()
.map(fieldError -> new MethodArgumentFieldError(fieldError.getField(), fieldError.getCode(), fieldError.getRejectedValue()))
.collect(Collectors.toList());
List<MethodArgumentGlobalError> methodArgumentGlobalErrors = bindingResult
.getGlobalErrors()
.stream()
.map(globalError -> new MethodArgumentGlobalError(globalError.getCode()))
.collect(Collectors.toList());
MethodArgumentError methodArgumentError = new MethodArgumentError(methodArgumentFieldErrors, methodArgumentGlobalErrors);
return new ResponseEntity<>(methodArgumentError, HttpStatus.UNPROCESSABLE_ENTITY);
}
#Override
protected ResponseEntity<Object> handleMissingServletRequestParameter(MissingServletRequestParameterException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
MissingParameterError missingParameterError = new MissingParameterError(ex.getParameterName(), ex.getMessage());
return new ResponseEntity<>(missingParameterError, HttpStatus.UNPROCESSABLE_ENTITY);
}
#ExceptionHandler(Exception.class)
public ResponseEntity<Object> handleNotFound(Exception ex, WebRequest request) {
System.out.println("inside!");
if( ex instanceof DataIntegrityViolationException){
System.out.println("Data integrity violation");
String constraintViolationErrors = ex.getMessage();
String msgErr = (constraintViolationErrors.substring(constraintViolationErrors.indexOf("=") + 1));
return new ResponseEntity<>(msgErr, HttpStatus.BAD_REQUEST);
}
if(ex instanceof UsernameNotFoundException) {
String msgErr = ex.getMessage();
return new ResponseEntity<>(msgErr, HttpStatus.BAD_REQUEST);
}
if (ex instanceof NotFoundEntityException || ex instanceof EntityNotFoundException || ex instanceof NoSuchElementException){
//return CommonResponseEntity.NotFoundResponseEntity(ex.getMessage());
System.out.println("inside the handler!");
return new ResponseEntity<>(ex.getMessage(),HttpStatus.NOT_FOUND);
}
if(ex instanceof UpdateException){
return new ResponseEntity<>(HttpStatus.CONFLICT);
}
return null;
}
#Data
#AllArgsConstructor
public class MethodArgumentError {
private List<MethodArgumentFieldError> fieldErrors;
private List<MethodArgumentGlobalError> globalErrors;
}
#Data
#AllArgsConstructor
public class MethodArgumentFieldError {
private String field;
private String code;
private Object rejectedValue;
}
#Data
#AllArgsConstructor
public class MethodArgumentGlobalError {
private String code;
}
#Data
#AllArgsConstructor
public class MissingParameterError {
private String parameterName;
private String message;
}
#Data
#AllArgsConstructor
public class ConstraintViolationError {
private String invalidValue;
private String message;
}
}
I don't know why, when I get a DataIntegrityViolationException the ExceptionHandler is called, instead when I get an EntitynotFoundException I get this message:
java.lang.IllegalStateException: Could not resolve method parameter at index 0 in public org.springframework.http.ResponseEntity com.isssr.ticketing_system.rest.TicketRest.insertTicket(com.isssr.ticketing_system.entity.Ticket,java.security.Principal) throws com.isssr.ticketing_system.exception.EntityNotFoundException: No suitable resolver for argument 0 of type 'com.isssr.ticketing_system.entity.Ticket'
What's the problem??
I saw other strage things; I get this message:
Failed to invoke #ExceptionHandler method: public org.springframework.http.ResponseEntity com.isssr.ticketing_system.rest.TicketRest.insertTicket(com.isssr.ticketing_system.entity.Ticket,java.security.Principal) throws com.isssr.ticketing_system.exception.EntityNotFoundException
So it seems that Spring is trying to invoke another method instead of method of my ExceptionHandler.
How is possibile this?

Not able to return ResponseEntity with Exception Details in spring

I have created a Spring Restful Service and Spring MVC application.
Restful Service ::
Restful service returns an entity if its existing in DB. If it doesn't exist It returns a custom Exception information in ResponseEntity object.
It is working as expected tested using Postman.
#GetMapping(value = "/validate/{itemId}", produces = { MediaType.APPLICATION_JSON_VALUE, MediaType.APPLICATION_XML_VALUE })
public ResponseEntity<MyItem> validateItem(#PathVariable Long itemId, #RequestHeader HttpHeaders httpHeaders) {
MyItem myItem = myitemService.validateMyItem(itemId);
ResponseEntity<MyItem> responseEntity = null;
if (myItem == null) {
throw new ItemNotFoundException("Item Not Found!!!!");
}
responseEntity = new ResponseEntity<MyItem>(myItem, headers, HttpStatus.OK);
return responseEntity;
}
If the requested Entity does not exist Restful Service returns below.
#ExceptionHandler(ItemNotFoundException.class)
public ResponseEntity<ExceptionResponse> itemNotFEx(WebRequest webRequest, Exception exception) {
System.out.println("In CREEH::ItemNFE");
ExceptionResponse exceptionResponse = new ExceptionResponse("Item Not Found Ex!!!", new Date(), webRequest.getDescription(false));
ResponseEntity<ExceptionResponse> responseEntity = new ResponseEntity<ExceptionResponse>(exceptionResponse, HttpStatus.NOT_FOUND);
return responseEntity;
}
But when I am calling the above service from a spring MVC application using RestTemplate, It is returning a valid object if it exists.
If the requested object does not exist Restful service is returning the exception information but its not reaching the calling(spring MVC) application.
Spring MVC application calls Restful Web Service using Rest template
String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
ResponseEntity<Object> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, Object.class, uriParms);
int restCallStateCode = responseEntity.getStatusCodeValue();
This is expected behavior. Rest template throws exception when the http status is client error or server error and returns the response when http status is not error status.
You have to provide implementation to use your error handler, map the response to response entity and throw the exception.
Create new error exception class with ResponseEntity field.
public class ResponseEntityErrorException extends RuntimeException {
private ResponseEntity<ErrorResponse> errorResponse;
public ResponseEntityErrorException(ResponseEntity<ErrorResponse> errorResponse) {
this.errorResponse = errorResponse;
}
public ResponseEntity<ErrorResponse> getErrorResponse() {
return errorResponse;
}
}
Custom error handler which maps the error response back to ResponseEntity.
public class ResponseEntityErrorHandler implements ResponseErrorHandler {
private List<HttpMessageConverter<?>> messageConverters;
#Override
public boolean hasError(ClientHttpResponse response) throws IOException {
return hasError(response.getStatusCode());
}
protected boolean hasError(HttpStatus statusCode) {
return (statusCode.is4xxClientError() || statusCode.is5xxServerError());
}
#Override
public void handleError(ClientHttpResponse response) throws IOException {
HttpMessageConverterExtractor<ExceptionResponse> errorMessageExtractor =
new HttpMessageConverterExtractor(ExceptionResponse.class, messageConverters);
ExceptionResponse errorObject = errorMessageExtractor.extractData(response);
throw new ResponseEntityErrorException(ResponseEntity.status(response.getRawStatusCode()).headers(response.getHeaders()).body(errorObject));
}
public void setMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
this.messageConverters = messageConverters;
}
}
RestTemplate Configuration - You have to set RestTemplate's errorHandler to ResponseEntityErrorHandler.
#Configuration
public class RestTemplateConfiguration {
#Bean
public RestTemplate restTemplate() {
RestTemplate restTemplate = new RestTemplate();
ResponseEntityErrorHandler errorHandler = new ResponseEntityErrorHandler();
errorHandler.setMessageConverters(restTemplate.getMessageConverters());
restTemplate.setErrorHandler(errorHandler);
return restTemplate;
}
}
Calling Method
#Autowired restTemplate
String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
try {
ResponseEntity<Object> responseEntity = restTemplate.exchange(url, HttpMethod.GET, httpEntity, Object.class, uriParms);
int restCallStateCode = responseEntity.getStatusCodeValue();
} catch (ResponseEntityErrorException re) {
ResponseEntity<ErrorResponse> errorResponse = re.getErrorResponse();
}
Try using the #ResponseBody annotation on your Exceptionhandler. e.g:
public #ResponseBody ResponseEntity<ExceptionResponse> itemNotFEx(WebRequest webRequest, Exception exception) {... }
You should use Custom Exception Handler to fix your case. It looks like this
#ControllerAdvice
public class CustomResponseEntityExceptionHandler extends ResponseEntityExceptionHandler {
public CustomResponseEntityExceptionHandler() {
super();
}
// 404
#ExceptionHandler(value = { EntityNotFoundException.class, ResourceNotFoundException.class })
protected ResponseEntity<Object> handleNotFound(final RuntimeException ex, final WebRequest request) {
BaseResponse responseError = new BaseResponse(HttpStatus.NOT_FOUND.value(),HttpStatus.NOT_FOUND.name(),
Constants.HttpStatusMsg.ERROR_NOT_FOUND);
logger.error(ex.getMessage());
return handleExceptionInternal(ex, responseError, new HttpHeaders(), HttpStatus.NOT_FOUND, request);
}
}
And your code should throw some exception, eg:
if (your_entity == null) {
throw new EntityNotFoundException("said something");
}
If you get this case in somewhere else again, you just throw exception like above. Your handler will take care the rest stuffs.
Hope this help.
I've started your application and works just fine.
Maven :
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
The controller class is :
#Controller
public class ValidationController {
#GetMapping(value = "/validate/{itemId}")
public #ResponseBody ResponseEntity<MyItem> validateItem(#PathVariable Long itemId) {
if (itemId.equals(Long.valueOf(1))) {
throw new ItemNotFoundException();
}
return new ResponseEntity<>(new MyItem(), HttpStatus.OK);
}
#ExceptionHandler(ItemNotFoundException.class)
public ResponseEntity<ExceptionResponse> itemNotFEx(WebRequest webRequest, Exception exception) {
System.out.println("In CREEH::ItemNFE");
ExceptionResponse exceptionResponse = new ExceptionResponse("Item Not Found Ex!!!", new Date(), webRequest.getDescription(false));
ResponseEntity<ExceptionResponse> responseEntity = new ResponseEntity<>(exceptionResponse, HttpStatus.NOT_FOUND);
return responseEntity;
}
}
and the test:
#RunWith(SpringRunner.class)
#WebMvcTest(value = ValidationController.class, secure = false)
public class TestValidationController {
#Autowired
private MockMvc mockMvc;
#Test
public void testExpectNotFound() throws Exception {
mockMvc.perform(get("/validate/1"))
.andExpect(status().isNotFound());
}
#Test
public void testExpectFound() throws Exception {
mockMvc.perform(get("/validate/2"))
.andExpect(status().isOk());
}
}
Are you sure the url you are trying to use with RestTemplate is correct?
String url = "http://localhost:8080/ItemServices/items/validate/{itemId}";
Your get method is #GetMapping(value = "/validate/{itemId}"
If you don't have request mapping at the level of the controller the url should be:
http://localhost:8080/validate/1
Another difference is the missing #ResponseBody on your controller method.

Categories