java - getforobject - Spring RestTemplate y tipos genéricos ParameterizedTypeReference colecciones como List<T>
resttemplate post (4)
La solución más fácil para mí es definir un objeto MyOperationResult que contenga la lista que espera como campo y usar restTemplate.getForObject para obtener este resultado.
Una clase de controlador abstracta requiere una lista de objetos de REST. Mientras usa Spring RestTemplate, no lo asigna a la clase requerida, en cambio, devuelve el HashMAp vinculado.
public List<T> restFindAll() {
RestTemplate restTemplate = RestClient.build().restTemplate();
ParameterizedTypeReference<List<T>> parameterizedTypeReference = new ParameterizedTypeReference<List<T>>(){};
String uri= BASE_URI +"/"+ getPath();
ResponseEntity<List<T>> exchange = restTemplate.exchange(uri, HttpMethod.GET, null,parameterizedTypeReference);
List<T> entities = exchange.getBody();
// here entities are List<LinkedHashMap>
return entities;
}
Si yo uso,
ParameterizedTypeReference<List<AttributeInfo>> parameterizedTypeReference =
new ParameterizedTypeReference<List<AttributeInfo>>(){};
ResponseEntity<List<AttributeInfo>> exchange =
restTemplate.exchange(uri, HttpMethod.GET, null,parameterizedTypeReference);
Funciona bien. Pero no se puede poner en todas las subclases, cualquier otra solución.
No pude encontrar una solución de Spring, por lo tanto, lo he hecho con ParameterizedTypeReference
en HashMap
como
public final static HashMap<Class,ParameterizedTypeReference> paramTypeRefMap = new HashMap() ;
static {
paramTypeRefMap.put(AttributeDefinition.class, new ParameterizedTypeReference<List<AttributeDefinition>>(){} );
paramTypeRefMap.put(AttributeInfo.class, new ParameterizedTypeReference<List<AttributeInfo>>(){} );
}
y lo usé
ParameterizedTypeReference parameterizedTypeReference = paramTypeRefMap.get(requiredClass);
ResponseEntity<List> exchange = restTemplate.exchange(uri, HttpMethod.POST, entity, parameterizedTypeReference);
Trabajé alrededor de esto usando el siguiente método genérico:
public <T> List<T> exchangeAsList(String uri, ParameterizedTypeReference<List<T>> responseType) {
return restTemplate.exchange(uri, HttpMethod.GET, null, responseType).getBody();
}
Entonces podría llamar:
List<MyDto> dtoList = this.exchangeAsList("http://my/url", new ParameterizedTypeReference<List<MyDto>>() {});
Esto hizo que mis interlocutores cargaran con la necesidad de especificar el ParameterizedTypeReference
al llamar, pero significaba que no tenía que mantener una asignación estática de tipos como en la respuesta de vels4j
Usando ParameterizedTypeReference
para una List<Domain>
, cuando Domain es una clase explícita, esa ParameterizedTypeReference
funciona bien, como esto:
@Override
public List<Person> listAll() throws Exception {
ResponseEntity<List<E>> response = restTemplate.exchange("http://example.com/person/", HttpMethod.GET, null,
new ParameterizedTypeReference<List<Person>>() {});
return response.getBody();
}
Sin embargo, si un método listAll
se usa en sabor genérico, esa lista debe parametrizarse. La mejor manera que encontré para esto es:
public abstract class WebServiceImpl<E> implements BaseService<E> {
private Class<E> entityClass;
@SuppressWarnings("unchecked")
public WebServiceImpl() {
this.entityClass = (Class<E>) ((ParameterizedType) getClass().getGenericSuperclass())
.getActualTypeArguments()[0];
}
@Override
public List<E> listAll() throws Exception {
ResponseEntity<List<E>> response = restTemplate.exchange("http://example.com/person/", HttpMethod.GET, null,
new ParameterizedTypeReference<List<E>>() {
@Override
public Type getType() {
Type type = super.getType();
if (type instanceof ParameterizedType) {
Type[] responseWrapperActualTypes = { entityClass };
ParameterizedType responseWrapperType = new ParameterizedTypeImpl(List.class,
responseWrapperActualTypes, null);
return responseWrapperType;
}
return type;
}
});
return response.getBody();
}
}