java.lang.IllegalStateException: Could not resolve parameter [0] in public org.springframework.http.ResponseEntity<java.lang.Object>
Asked Answered
S

3

5

I have custom exception handler yet I am finding constraint violation exception difficult to handle.

Controller

@RestController
@RequestMapping("/clients")
@Slf4j
public class ClientController {
    private final ClientService clientService;
    private final SuccessResponse successResponse;
    ModelMapper modelMapper = new ModelMapper();

    ClientController(ClientService clientService, SuccessResponse successResponse) {
        this.clientService = clientService;
        this.successResponse = successResponse;
    }

    @PostMapping
    public ResponseEntity<ResponseModel> addClient(@Valid @RequestBody ClientRequest clientRequest) {
        log.info("Inside ClientController add clientRequest"+ clientRequest );
        ClientRequest client = clientService.addClient(clientRequest);
        log.info("Inside ClientController add clientRequest"+ client );
        return handleSuccessResponseEntity("Client added successfully", HttpStatus.CREATED, client);

    }
    

    public ResponseEntity<ResponseModel> handleSuccessResponseEntity(String message, HttpStatus status, Object payload){
        successResponse.setMessage(message);
        successResponse.setStatus(status.value());
        successResponse.setPayload(payload);
        return new ResponseEntity<>(successResponse, HttpStatus.OK);
    }
}

Service

@Service
@Slf4j
public class ClientService implements ClientServices {

    private final ClientRepository clientRepository;
    ModelMapper modelMapper = new ModelMapper();

    ClientService(ClientRepository clientRepository){this.clientRepository = clientRepository;}

    @Override
    public ClientRequest addClient(ClientRequest clientRequest) {
        log.info("Inside ClientService add client");
        Client client = modelMapper.map(clientRequest, Client.class);
        log.info("Inside ClientService add client" + client);
        Client clientCreated = clientRepository.save(client);
        return convertEntityToDto(clientCreated);

    }

    @Override
    public ClientRequest getClientById(Long clientId) {

        Client client = clientRepository.findById(clientId).get();
        log.info("Inside ClientService getClientById" + client);
        return convertEntityToDto(client);
    }

    public List<ClientRequest> getAllClient() {
        List<Client> clients = clientRepository.findAll();
        log.info("Inside ClientService getAllClient" + clients);
        return clients.stream()
                .map(this::convertEntityToDto)
                .collect(Collectors.toList());
    }



}

Error handler

@ControllerAdvice
@Slf4j
public class CustomRestExceptionHandler extends ResponseEntityExceptionHandler {
    @Autowired
    ErrorResponse error;


    @Override
    protected ResponseEntity<Object> handleMethodArgumentNotValid(
            MethodArgumentNotValidException ex,
            HttpHeaders headers,
            HttpStatus status,
            WebRequest request) {
        return buildResponseEntity(getValidationErrors(ex.getBindingResult().getFieldErrors()));

    }

    @ExceptionHandler({ MethodArgumentTypeMismatchException.class })
    public ResponseEntity<Object> handleMethodArgumentTypeMismatch(
            MethodArgumentTypeMismatchException ex, WebRequest request) {
        return errorHandlerController(ex, BAD_REQUEST);
    }

    @Override
    protected ResponseEntity<Object> handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException ex, HttpHeaders headers, HttpStatus status, WebRequest request) {
        return errorHandlerController(ex, status);
    }

    @ExceptionHandler(EntityNotFoundException.class)
    protected ResponseEntity<Object> handleEntityNotFound(
            EntityNotFoundException ex) {
        error.setMessage(NOT_FOUND.toString());
        error.setStatus(NOT_FOUND.value());
        error.setError(ex.getLocalizedMessage().replace("com.darothub.clientservice.entity.", ""));
        return buildResponseEntity(error);
    }

    @ExceptionHandler({ NoSuchElementException.class })
    public ResponseEntity<Object> handleNoSuchElement(Exception ex) {
        return errorHandlerController(ex, NOT_FOUND);
    }


    @ExceptionHandler({ ConstraintViolationException.class })
    public ResponseEntity<Object> handleConstraintViolation(
            ConstraintViolationException ex, WebRequest request) {
        List<String> errors = new ArrayList<String>();
        for (ConstraintViolation<?> violation : ex.getConstraintViolations()) {
            errors.add(violation.getRootBeanClass().getName() + " " +
                    violation.getPropertyPath() + ": " + violation.getMessage());
        }
        return errorHandlerController(ex, HttpStatus.BAD_REQUEST);

    }


    private ResponseEntity<Object> buildResponseEntity(ErrorResponse error) {
        return new ResponseEntity<>(error, HttpStatus.valueOf(error.getStatus()));
    }

    private ErrorResponse getValidationErrors(List<FieldError> fieldErrors) {
        ErrorResponse error = new ErrorResponse();
        error.setStatus(BAD_REQUEST.value());
        error.setMessage(BAD_REQUEST.toString());
        Map<String, String> errors = new HashMap<>();
        fieldErrors.forEach(e -> errors.put(e.getField(), e.getDefaultMessage()));
        error.setError(errors);
        return error;
    }

    private ResponseEntity<Object> errorHandlerController(Exception ex, HttpStatus status){
        error.setMessage(status.toString());
        error.setStatus(status.value());
        error.setError(ex.getMessage());
        return new ResponseEntity<>(error, HttpStatus.valueOf(error.getStatus()));
    }
}

The error I get is as below

java.lang.IllegalStateException: Could not resolve parameter [0] in public org.springframework.http.ResponseEntity<java.lang.Object> com.darothub.clientservice.exceptions.CustomRestExceptionHandler.handleConstraintViolation(javax.validation.ConstraintViolationException,org.springframework.web.context.request.WebRequest): No suitable resolver
    at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:167) ~[spring-web-5.3.2.jar:5.3.2]
    at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:137) ~[spring-web-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:106) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver.doResolveHandlerMethodException(ExceptionHandlerExceptionResolver.java:420) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.handler.AbstractHandlerMethodExceptionResolver.doResolveException(AbstractHandlerMethodExceptionResolver.java:75) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.handler.AbstractHandlerExceptionResolver.resolveException(AbstractHandlerExceptionResolver.java:141) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.handler.HandlerExceptionResolverComposite.resolveException(HandlerExceptionResolverComposite.java:80) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.DispatcherServlet.processHandlerException(DispatcherServlet.java:1321) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:1132) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:1078) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:961) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:1006) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:909) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:652) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
    at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:883) ~[spring-webmvc-5.3.2.jar:5.3.2]
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:733) ~[tomcat-embed-core-9.0.41.jar:4.0.FR]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:231) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166) ~[tomcat-embed-core-9.0.41.jar:9.0.41]
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:53) ~[tomcat-embed-websocket-9.0.41.jar:9.0.41]
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193) ~[tomcat-embed-core-9.0.41.jar:9.0.41]

2020-12-31 23:49:37.319 ERROR 13909 --- [nio-8001-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet]    : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction] with root cause

javax.validation.ConstraintViolationException: Validation failed for classes [com.darothub.clientservice.entity.Client] during persist time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
    ConstraintViolationImpl{interpolatedMessage='size must be between 3 and 46', propertyPath=lastName, rootBeanClass=class com.darothub.clientservice.entity.Client, messageTemplate='{javax.validation.constraints.Size.message}'}
    ConstraintViolationImpl{interpolatedMessage='First name must not be blank', propertyPath=firstName, rootBeanClass=class com.darothub.clientservice.entity.Client, messageTemplate='First name must not be blank'}
    ConstraintViolationImpl{interpolatedMessage='size must be between 3 and 46', propertyPath=firstName, rootBeanClass=class com.darothub.clientservice.entity.Client, messageTemplate='{javax.validation.constraints.Size.message}'}
    ConstraintViolationImpl{interpolatedMessage='Last name is blank', propertyPath=lastName, rootBeanClass=class com.darothub.clientservice.entity.Client, messageTemplate='Last name is blank'}
    ConstraintViolationImpl{interpolatedMessage='Please enter characters only', propertyPath=firstName, rootBeanClass=class com.darothub.clientservice.entity.Client, messageTemplate='Please enter characters only'}
]
    at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:140) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreInsert(BeanValidationEventListener.java:80) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.action.internal.EntityInsertAction.preInsert(EntityInsertAction.java:227) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:100) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:604) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.engine.spi.ActionQueue.lambda$executeActions$1(ActionQueue.java:478) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at java.base/java.util.LinkedHashMap.forEach(LinkedHashMap.java:684) ~[na:na]
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:475) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:348) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:40) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:102) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1362) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:453) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3212) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2380) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.4.25.Final.jar:5.4.25.Final]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562) ~[spring-orm-5.3.2.jar:5.3.2]

I understand the error is coming from the service save method as a result of request body constraint violation. I want to be able to catch that error.

Stenopetalous answered 31/12, 2020 at 23:1 Comment(1)
i'm gussing you have wrong import for this class ConstraintViolationExceptionPlotkin
A
8

The specific error you're getting in your logs, no suitable resolver, helps guide you towards the issue. The class declared by your @ExceptionHandler annotation must match the first argument in the method that annotation is attached to. Ensure there's no conflicting imports for the class ConstraintViolationException.

Academician answered 2/1, 2021 at 16:8 Comment(0)
M
5

@IrishSaltWater's answer helped me solve this simple yet annoying issue, just make sure that:

    @ExceptionHandler(YourException.class) // <- class(1) 
    protected ResponseEntity<Object> handleEntityNotFound(
            YourException exception) { // <- class(2)
            // ...
    }

class(1) match class(2)

ie. "class declared in @ExceptionHandler" should match the "first argument in the method".

Manteau answered 26/12, 2022 at 5:40 Comment(2)
what if multiple exceptions are defined with @ExceptionHandlerLynea
@RobertoMessa in this case multiple exceptions need to extend one common or be handled in own method for each exceptionAssembled
D
0

This exception occurred when I was working as there was an Illegal argument coming from the frontend side and I was not able to debug as it was not coming to the endpoint, when the correct argument was sent to the backend it was fixed.

Dispermous answered 25/1, 2023 at 9:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.