'Generic response for @RestController

I am attempting replace my current response to implement generic response class to handle all responses. But I hit a wall certain point. Here is my GenericResponse class:

@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
@ToString
public class GenericResponse<T>  {
   
    private String status;
    private Error error;
    private String message;
    private T data;
}
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@ToString
@Builder
public class Error {
    private String errorCode;
    private String  errorDescription;
}

My controller class:

@PostMapping("application/internal/get-app-docs-by-app-id")
public ResponseEntity<ApplicationDocuments> retrieveAppDcosByAppId(
        
        @RequestBody ApplicationSubmitRequest applicationId) {

    log.info("Retrieving applicant docs by application id..");
    return new ResponseEntity<>(applicationService.retrieveAppDcosByAppId(applicationId), HttpStatus.OK);
}

And lastly.. service class

public ApplicationDocuments retrieveAppDcosByAppId(ApplicationSubmitRequest applicationId) {
        log.info("Retrieve application docs");
        ApplicationDocuments appDocs = appDocsRepo.
                findByApplicationId(applicationId.getApplicationId());
        if (appDocs == null) {

          /* TRYING TO REPLACE CURRENT IMPL TO GENERIC */

            GenericResponse.builder()
            .status(FAILURE)
            .message(applicationId.getApplicationId().toString())
            .error(com.ms.onboard.model.response.Error.builder()
                    .errorCode(RESOURCE_NOT_FOUND)
                    .errorDescription(RESOURCE_NOT_FOUND_MSG)
                    .build());


            throw new EmptyResultDataAccessException("App docs id: " + applicationId.getApplicationId(), 1);
        }

        /* TRYING TO REPLACE CURRENT IMPL TO GENERIC */

        GenericResponse.builder()
        .status(SUCCESS)
        .message("Applicant found!")
        .data(appDocs)
                .build();


        return appDocs;
    }

As you can see from the block comments, I am trying to replace the current implementation using generic class.

The top is for failure (no resource found) and bottom success (resource found). I just parked it there because when I tried to return these new generic response, editor shows error.

For the top, it says:

Type mismatch: cannot convert from GenericResponse.GenericResponseBuilder<Object> to ApplicationDocuments

..and suggest me to:

Change method return type to 'GenericResponseBuilder<Object>'

For the bottom, it says:

Type mismatch: cannot convert from GenericResponse<Object> to ApplicationDocuments

..and suggest me to:

Change method return type to 'GenericResponse<Object>'

If I change one, editor will ask to change the other. I am caught in a loop. How do I resolve this? Thanks in advance!



Solution 1:[1]

Your function refactored should look like:

    public GenericResponse<ApplicationDocuments> retrieveAppDcosByAppId(ApplicationSubmitRequest applicationId) {
        log.info("Retrieve application docs");
        ApplicationDocuments appDocs = appDocsRepo.findByApplicationId(applicationId.getApplicationId());

        GenericResponse<ApplicationDocuments> response = new GenericResponse<ApplicationDocuments>();
        
        if (appDocs == null) {
            //since you're trying to use the generic response for errors too, it wouldn't be necessary to throw exception
            response.setStatus(FAILURE);
            response.setMessage((applicationId.getApplicationId().toString());
            response.setError(com.ms.onboard.model.response.Error.builder()
                    .errorCode(RESOURCE_NOT_FOUND)
                    .errorDescription(RESOURCE_NOT_FOUND_MSG)
                    .build());

            return response;
        }

    response.setStatus(SUCCESS);
    response.setMessage("Applicant found!");
    response.setData(appDocs);

    return response;
}

And your controller something like:

@PostMapping("application/internal/get-app-docs-by-app-id")
public ResponseEntity<GenericResponse<ApplicationDocuments>> retrieveAppDcosByAppId(
        
        @RequestBody ApplicationSubmitRequest applicationId) {

    log.info("Retrieving applicant docs by application id..");
    return new ResponseEntity<>(applicationService.retrieveAppDcosByAppId(applicationId), HttpStatus.OK);
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ypdev19