Search code examples
javaresttemplate

Fetch data from API that returns ResponseEntity<Object>


I have a service that calls another Api through rest template and the Api returns ResponseEntity Object. I have tried few things but I am unable to fetch the required data.

This is the code of the API which I am calling

SurveyService.java

     public ResponseEntity<Object> getSurveyData(String searchText) {
        List<SurveyResponse> dataList = new ArrayList<>();
        List<Map<Object, Object>> results =  someRepo.getSurveyData(searchText);
        if(null != results) {
            for (Map<Object, Object> item : results) {
            Survey t = (Survey) ObjectMapper.convertMapToJson(item, Survey.class); //Utility class
                    SurveyResponse response = SurveyResponse.builder()
                        .id(t.getId())
                        .type(t.getType())
                        .name(t.getName())
                        .jobDesc(t.getJobDesc())
                        .build();
        
           
              dataList.add(response);
            }
        }

        return ResponseHandler.generateResponse(SUCCESS, HttpStatus.OK, dataList);

    } 

Below is the utility Response handler class

ResponseHandler.java

  public static ResponseEntity<Object> generateResponse(String message, HttpStatus status, Object responseObj) {
        Map<String, Object> map = new LinkedHashMap<String, Object>();
        map.put(STATUS, status.value());
        map.put(MESSAGE, message);
        map.put(DATA, responseObj);
        return new ResponseEntity<>(map, status);

    }

This is the Entity class

Survey.java

    @Data
    @Entity
    @AllArgsConstructor
    @NoArgsConstructor
    public class Survey {
    @Id
    private String id;
    private String type;
    private String name;
    private String jobDesc;
    }

The response of the Api looks like this

{
    "status": 200,
    "message": "SUCCESS",
    "data": [
        {
            "id": "12345",
            "type": "person",
            "name": "P1",
            "jobDesc":"QA"
           
        }
    ]
}

This is the code from my Service class and I have created an entity class called Survey.java to map the response from the Api

PersonSurveyService.java

public void getSurvey(String personId){
 try {

            ResponseEntity<Map<String, Object>> response = restTemplate.exchange(url+personId, HttpMethod.GET, null,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    });
            List<Survey> alist = (List<Survey>) response.getBody().get("data");
            System.out.println("checking first element"+alist.get(0).getId());
}
 catch(Exception ex) {
            System.out.println("Exception is:"+ex);
        }

The above sysout prints fine until I print alist.get(0) but when I added getId() it throws below exception.

Exception is:java.lang.ClassCastException: class java.util.LinkedHashMap cannot be cast to class com.test.entity.Survey (java.util.LinkedHashMap is in module java.base of loader 'bootstrap'; com.test.entity.Survey is in unnamed module of loader 'app')

I have tried a few other approaches

Approach 1:
ResponseEntity<Survey> response = restTemplate.getForEntity(url + personId, Survey.class);

I do not get any error here but all the fields in Survey object gets mapped as null.

Approach 2:
 
 ResponseEntity<Map<String, Object>> response = restTemplate.exchange(url+personId, HttpMethod.GET, null,
                    new ParameterizedTypeReference<Map<String, Object>>() {
                    });

objectMapper.convertValue(response.getBody(),Survey.class);

Here I get an error: Exception is:java.lang.IllegalArgumentException: Unrecognized field "status"

Any inputs as to how can I correctly fetch the details(id, name, ...) from the below response object.

{
    "status": 200,
    "message": "SUCCESS",
    "data": [
        {
            "id": "12345",
            "type": "person",
            "name": "P1",
            "jobDesc":"QA"
           
        }
    ]
}

Solution

  • Here's what you should do:

    1. First, create a new class ApiResponse to capture the entire response:
    import java.util.List;
    
    public class ApiResponse {
        private Integer status;
        private String message;
        private List<Map<String, Object>> data;
    
        // getters and setters
    }
    
    1. Then, modify the restTemplate.exchange method in PersonSurveyService to use ApiResponse instead of Map<String, Object> and manually convert the Map<String, Object> in data to Survey.
    public void getSurvey(String personId) {
    
        try {
            ResponseEntity<ApiResponse> response = restTemplate.exchange(
                    url + personId,
                    HttpMethod.GET, 
                    null, 
                    new ParameterizedTypeReference<ApiResponse>() {});
    
            List<Survey> alist = response.getBody().getData().stream()
                .map(item -> objectMapper.convertValue(item, Survey.class))
                .collect(Collectors.toList());
    
            System.out.println("checking first element " + alist.get(0).getId());
        } catch (Exception ex) {
            System.out.println("Exception is: " + ex);
        }
    }