Home > Back-end >  java.lang.IllegalArgumentException: argument type mismatch while using Spring Custom Argument Resolv
java.lang.IllegalArgumentException: argument type mismatch while using Spring Custom Argument Resolv

Time:09-28

I am getting java.lang.IllegalArgumentException: argument type mismatch while using Spring Argument resolver with HandlerMethodArgumentResolver. debugged my code many times but able to find why this exception is coming. it will be great if anyone can help me with this. this is my code.

public final class SpringArgumentResolver implements HandlerMethodArgumentResolver {

    @Override
    public boolean supportsParameter(MethodParameter parameter) {
        return CommonHeader.class.isAssignableFrom(parameter.getParameterType());
    }

    @Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

        CommonHeader commonHeader = new CommonHeader();

        String user_id = webRequest.getHeader("UserID");
       
        commonHeader.setUser_id(user_id);

            return commonHeader;
    }

Config class:

@Configuration
@EnableWebMvc
public class SpringWebMvcConfig implements WebMvcConfigurer {


    @Override
    public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
        resolvers.add(new SpringArgumentResolver());
    }

}

CommonHeader class:

public class CommonHeader {

    private String user_id;
    private String ip_address;
    private String request_id;

    public CommonHeader(String user_id) {
            this.user_id = user_id;
    }
    public CommonHeader(){}
 
    public String getUser_id() {
        return user_id;
    }

    public void setUser_id(String user_id) {
        this.user_id = user_id;
    }
}

Controller:

@GetMapping("user_data")
public DeferredResult<ResponseEntity<JsonNode>> getUserPreferenceData(GetDataRequest getDataRequest) {
            DeferredResult<ResponseEntity<JsonNode>> deferredResult = new DeferredResult<>();
         // some logic 
        //  some logic
       return deferredResult;
    }

Request class which extends CommonHeader class:

@Getter
@Setter
public class GetDataRequest extends CommonHeader {

    private String name1;
    private String name2;
   
}

CodePudding user response:

Your SpringArgumentResolver is wrong. A GetDataRequest is a CommonHeader but a CommonHeader isn't a GetDataRequest. Your SpringArgumentResolver always returns a CommonDataHeader which cannot be cast/turned into a GetDataRequest hence the error.

CommonHeader header = new CommonHeader();
GetDataRequest request = (GetDataRequest) header;

Is basically what you expected that automatically would happen. Now this wouldn't work in regular java (leading to a ClassCastException) why should it in Spring? Spring does a check to see if the resulting object can be assigned to that method argument, in this case in cannot because GetDataRequest.isAssignableFrom(CommonHeader.class); will return false (although the opposite is true!).

What you should do in your SpringArgumentResolver is dynamically determine the class and instantie it, cast it to CommonHeader and set the fields.

@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {

    CommonHeader commonHeader = BeanUtils.instantiateClass(parameter.getParameterType());
    String user_id = webRequest.getHeader("UserID");
    commonHeader.setUser_id(user_id);
    return commonHeader;
}

This will use the actual type of the method argument to create an instance thus eliminating the ClassCastException and for Spring the IllegalArgumentException.

  • Related