postforentity getforobject java resttemplate spring-rest spring-web

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(); } }