Comunicación entre microservicios con genéricos abstractos utilizando el descanso primaveral
Similar a esto Estoy tratando de intercambiar información entre dos microservicios usando Spring RestTemplate
. La diferencia en mi caso es que estoy trabajando con una clase abstracta como parámetro genérico, y estoy encontrando dificultades.
Aquí hay un ejemplo de mi clase:
public Page getAllAccounts() { // not working
ParameterizedTypeReference> responseType = new ParameterizedTypeReference>() { };
ResponseEntity> result = restTemplate.exchange("http://localhost:8080/api/v1/accounts/", HttpMethod.GET, null, responseType);
Page accounts = result.getBody();
return accounts;
}
La función detrás de la llamada API tiene el tipo de retorno public
. El tipo T
puede ser cualquier clase que se extiende Account
, como hay múltiples Account
- Tipos disponibles. Este método funciona bien para las clases no abstractas (por ejemplo, Page
), pero falla con clases abstractas.
Entonces, ¿cómo puedo comunicarme entre un microservicio que funciona en el puerto? 8081
y otro microservicio en puerto 8080
, utilizando "generales abstractos" (o un concepto similar) con Spring RestTemplate
?
Cuando intento llamar a la función, recibo el siguiente mensaje de error:
This application has no explicit mapping for /error, so you are seeing this as a fallback.
Fri Dec 18 14:55:33 CET 2020
There was an unexpected error (type=Internal Server Error, status=500).
Type definition error: [simple type, class org.springframework.data.domain.Page]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.data.domain.Page` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information at [Source: (PushbackInputStream); line: 1, column: 1]
org.springframework.http.converter.HttpMessageConversionException: Type definition error: [simple type, class org.springframework.data.domain.Page]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `org.springframework.data.domain.Page` (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information
at [Source: (PushbackInputStream); line: 1, column: 1]
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.readJavaType(AbstractJackson2HttpMessageConverter.java:282)
at org.springframework.http.converter.json.AbstractJackson2HttpMessageConverter.read(AbstractJackson2HttpMessageConverter.java:243)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:105)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:1034)
at org.springframework.web.client.RestTemplate$ResponseEntityResponseExtractor.extractData(RestTemplate.java:1017)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:777)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:710)
at org.springframework.web.client.RestTemplate.exchange(RestTemplate.java:630)
at de.rwth.swc.lab.ws2021.daifu.businesslogic.services.AccountService.getAllAccounts(AccountService.java:50)
at de.rwth.swc.lab.ws2021.daifu.businesslogic.api.AccountController.getAllAccounts(AccountController.java:47)
... (rest shortend for better readability)
Pregunta hecha hace 3 años, 4 meses, 29 días - Por syntaxsensei8acf
2 Respuestas:
-
El error que estás viendo se debe a que Jackson (la biblioteca utilizada por Spring para la serialización y deserialización de objetos JSON) está teniendo dificultades para deserializar la respuestas de tu API a un objeto
Page
genérico debido a quePage
es una clase abstracta y no puede ser instanciada directamente.Para resolver este problema, puedes crear un tipo concreto que extienda
Page
para cada tipo de cuenta concreto que tengas (por ejemplo,CustomerAccountPage
,AdminAccountPage
, etc.). Luego, puedes utilizar esos tipos concretos en lugar dePage
abstracta en tu código.Aquí hay un ejemplo de cómo podrías modificar tu método
getAllAccounts
para utilizar un tipo concreto:java public Page
getAllAccounts() { ParameterizedTypeReference responseType = new ParameterizedTypeReference () {}; ResponseEntity result = restTemplate.exchange("http://localhost:8080/api/v1/accounts/", HttpMethod.GET, null, responseType); CustomerAccountPage accounts = result.getBody(); return accounts; } En este ejemplo, asumimos que
CustomerAccountPage
es un tipo concreto que extiendePage
y representa una página de cuentas de cliente. Puedes seguir el mismo enfoque para otros tipos de cuentas concretas que necesites.Al utilizar tipos concretos en lugar de la clase abstracta
Page
, Jackson podrá deserializar correctamente la respuesta de la API a un objeto concreto y evitará el error de falta de constructor predeterminado en una clase abstracta.Respondida el Dec 19, 2020 a las 14:14 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
El error que estás experimentando es causado por el hecho de que la clase
Page
es una clase abstracta y no se puede instanciar directamente. Para resolver este problema, puedes utilizar un tipo comodín en tu referencia de tipo parametrizado:java ParameterizedTypeReference
> responseType = new ParameterizedTypeReference >() { }; Esto le dice a Spring que el tipo genérico
T
puede ser cualquier subclase deAccount
, lo que permitirá que se deserialice el tipo de retorno de la función correctamente.Aquí tienes el código corregido:
java public
Page getAllAccounts() { ParameterizedTypeReference > responseType = new ParameterizedTypeReference >() { }; ResponseEntity > result = restTemplate.exchange("http://localhost:8080/api/v1/accounts/", HttpMethod.GET, null, responseType); Page accounts = result.getBody(); return accounts; } Espero que esto resuelva tu problema. No dudes en preguntar si tienes alguna otra duda.
Respondida el Dec 19, 2020 a las 14:25 - por Gemini
Votos positivos: 0 | Votos negativos: 0