Skip to content

Instantly share code, notes, and snippets.

@slmanju
Created January 25, 2018 05:46
Show Gist options
  • Star 30 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save slmanju/a85a6854cb7d37d069351edae06a4eb7 to your computer and use it in GitHub Desktop.
Save slmanju/a85a6854cb7d37d069351edae06a4eb7 to your computer and use it in GitHub Desktop.
Generic RestTemplate wrapper
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.CollectionType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.HttpClientErrorException;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import java.io.IOException;
import java.util.List;
@Component
public class RestTemplateHelper {
private static final Logger LOGGER = LoggerFactory.getLogger(RestTemplateHelper.class);
private RestTemplate restTemplate;
private ObjectMapper objectMapper;
@Autowired
public RestTemplateHelper(RestTemplateBuilder restTemplateBuilder, ObjectMapper objectMapper) {
this.restTemplate = restTemplateBuilder.build();
this.objectMapper = objectMapper;
}
public <T> T getForEntity(Class<T> clazz, String url, Object... uriVariables) {
try {
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class, uriVariables);
JavaType javaType = objectMapper.getTypeFactory().constructType(clazz);
return readValue(response, javaType);
} catch (HttpClientErrorException exception) {
if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
LOGGER.info("No data found {}", url);
} else {
LOGGER.info("rest client exception", exception.getMessage());
}
}
return null;
}
public <T> List<T> getForList(Class<T> clazz, String url, Object... uriVariables) {
try {
ResponseEntity<String> response = restTemplate.getForEntity(url, String.class, uriVariables);
CollectionType collectionType = objectMapper.getTypeFactory().constructCollectionType(List.class, clazz);
return readValue(response, collectionType);
} catch (HttpClientErrorException exception) {
if (exception.getStatusCode() == HttpStatus.NOT_FOUND) {
LOGGER.info("No data found {}", url);
} else {
LOGGER.info("rest client exception", exception.getMessage());
}
}
return null;
}
public <T, R> T postForEntity(Class<T> clazz, String url, R body, Object... uriVariables) {
HttpEntity<R> request = new HttpEntity<>(body);
ResponseEntity<String> response = restTemplate.postForEntity(url, request, String.class, uriVariables);
JavaType javaType = objectMapper.getTypeFactory().constructType(clazz);
return readValue(response, javaType);
}
public <T, R> T putForEntity(Class<T> clazz, String url, R body, Object... uriVariables) {
HttpEntity<R> request = new HttpEntity<>(body);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.PUT, request, String.class, uriVariables);
JavaType javaType = objectMapper.getTypeFactory().constructType(clazz);
return readValue(response, javaType);
}
public void delete(String url, Object... uriVariables) {
try {
restTemplate.delete(url, uriVariables);
} catch (RestClientException exception) {
LOGGER.info(exception.getMessage());
}
}
private <T> T readValue(ResponseEntity<String> response, JavaType javaType) {
T result = null;
if (response.getStatusCode() == HttpStatus.OK ||
response.getStatusCode() == HttpStatus.CREATED) {
try {
result = objectMapper.readValue(response.getBody(), javaType);
} catch (IOException e) {
LOGGER.info(e.getMessage());
}
} else {
LOGGER.info("No data found {}", response.getStatusCode());
}
return result;
}
}
private RestTemplateHelper restTemplateHelper;
// other codes...
// find by id
UserDto userDto = restTemplateHelper.getForEntity(UserDto.class, "http://localhost:8080/users/{id}", id);
// find all
UserDto userDto = restTemplateHelper.getForList(UserDto.class, "http://localhost:8080/users");
// save
UserDto userDto = restTemplateHelper.postForEntity(UserDto.class, "http://localhost:8080/users", userDto);
// update
UserDto userDto = restTemplateHelper.putForEntity(UserDto.class, "http://localhost:8080/users/{id}", userDto, id);
// delete
restTemplateHelper.delete("http://localhost:8080/users/{id}", id);
@rafaelnicolett
Copy link

Great!!!

@robsonlira
Copy link

Hello! I'm trying to consume an API, and found its wrapper class, the api I'm consuming has a complex JSON
https://bittrex.com/api/v1.1/public/getmarkets
so I have a model with generics ApiResult that has the attributes success, message and T result how to use your wrapper and for this Pojo?
ApiResult apiResult

Thank you
Robson C

@Cuica20
Copy link

Cuica20 commented Feb 8, 2019

Good job!

@dnagl
Copy link

dnagl commented Jul 23, 2019

Nice one :)

@BrunoSzczuk
Copy link

Thank you!!!!!!!!!!!!!!!!!!!!!!
You've saved my life.

Copy link

ghost commented Dec 25, 2020

Great! I found this very useful

@Artanniel
Copy link

Great!
Thanks!

@AlexKukhtinDev
Copy link

Maybe someone have exchange implementation?

@thiagocavalcanti
Copy link

Maybe someone have exchange implementation?

restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers), String.class);

@thiagocavalcanti
Copy link

thiagocavalcanti commented Aug 28, 2022

If you want to return something like ResponseWrapper<T> you can use this:

 public <T> ListWrapperDTO<T> getForWrapper(String url, HttpHeaders headers,  Class<T> clazz) {
        return restTemplate.exchange(url, HttpMethod.GET, new HttpEntity<>(headers),
                new ParameterizedTypeReference<ListWrapperDTO<T>>() {
                    public Type getType() {
                        return new CustomParameterizedType((ParameterizedType) super.getType(), new Type[]{clazz});
                    }
                }
        ).getBody();
    }

where

class CustomParameterizedType implements ParameterizedType {
    private final ParameterizedType delegate;
    private final Type[] actualTypeArguments;
    
    CustomParameterizedType(ParameterizedType delegate, Type[] actualTypeArguments) {
        this.delegate = delegate;
        this.actualTypeArguments = actualTypeArguments;
    }
    
    @Override
    public Type[] getActualTypeArguments() {
        return actualTypeArguments;
    }
    
    @Override
    public Type getRawType() {
        return delegate.getRawType();
    }
    
    @Override
    public Type getOwnerType() {
        return delegate.getOwnerType();
    }
    
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment