Hello Im trying to implement a generic method as controller base method, but the problem which I cannot understand happens with the generic method signature.
<T> ResponseEntity<T> makeApiCall(String path, HttpMethod httpMethod, T body, boolean isAdmin){
        String sender = isAdmin ? adminHash : userHash;
        HttpHeaders headers = new HttpHeaders();
        headers.add("Authorization", sender);
        headers.add("Content-Type", "application/json");
        HttpEntity<T> entity = new HttpEntity<>(body,headers);
        ResponseEntity<T> responseEntity = restTemplate.exchange(path, HttpMethod.POST, entity, body.getClass());
        return responseEntity;
}
The compile error I currently have is as follows:
Incompatible equality constraint: T and capture of ? extends Object
                You don't say exactly where the problem occurs, but I think this will occur on the restTemplate.exchange( call, as a result of passing body.getClass() as a parameter. This is because the return type of body.getClass() is Class<? extends Object>, as in the Javadoc:
The actual result type is
Class<? extends |X|>where|X|is the erasure of the static type of the expression on whichgetClassis called
The problem is that you can't guarantee that body is specifically a T - it could be a subclass of T. As such, the result of body.getClass() might not be a Class<T>.
If you want to be type-safe, you would need to pass that in as an additional parameter to the method.
<T> ResponseEntity<T> makeApiCall(
    String path, HttpMethod httpMethod, T body, Class<T> bodyClass, 
    boolean isAdmin){
  // ...
  ResponseEntity<T> responseEntity =
      restTemplate.exchange(
          path, HttpMethod.POST, entity, bodyClass);
  // ...
}
Note that the only way to obtain a Class<T> is to use a class literal, e.g. String.class if T is String. This precludes the use of generic body types, since there are no generic class literals.
You need to cast body.getClass() to Class<T>
@SuppressWarnings("unchecked")
<T> ResponseEntity<T> makeApiCall(String path, HttpMethod httpMethod, T body, boolean isAdmin){
    String sender = isAdmin ? adminHash : userHash;
    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", sender);
    headers.add("Content-Type", "application/json");
    HttpEntity<T> entity = new HttpEntity<>(body,headers);
    ResponseEntity<T> responseEntity = restTemplate.exchange(path, HttpMethod.POST, entity, (Class<T>) body.getClass());
    return responseEntity;
}
To make it type-safe you need to pass the class object as a parameter explicitly:
<T> ResponseEntity<T> makeApiCall(String path, HttpMethod httpMethod, T body, Class<T> clazz, boolean isAdmin){
String sender = isAdmin ? adminHash : userHash;
    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", sender);
    headers.add("Content-Type", "application/json");
    HttpEntity<T> entity = new HttpEntity<>(body,headers);
    ResponseEntity<T> responseEntity = restTemplate.exchange(path, HttpMethod.POST, entity, clazz);
    return responseEntity;
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With