Estaba trabajando para tratar de hacer una llamada a mi backend y configuré un controlador simple como este.
@RestController public class HelloController { @RequestMapping("/hello") public String Hello(IPerson person) { return person.sayHello(); } }IPerson es una interfaz de la siguiente manera
package com.example.demo.models; public interface IPerson { default String sayHello() { return "Hey There"; } }Y he implementado la interfaz como
package com.example.demo.models; import lombok.Builder; @Builder public class Person implements IPerson{ String name; String age; }La llamada funciona cuando cambio el parámetro en el controlador a la implementación de la interfaz, es decir
@RestController public class HelloController { @RequestMapping("/hello") public String Hello(Person person) { return person.sayHello(); } }Al llamar a la función con IPerson como parámetro, aparece el siguiente error.
java.lang.IllegalStateException: No primary or single unique constructor found for interface com.example.demo.models.IPerson at org.springframework.beans.BeanUtils.getResolvableConstructor(BeanUtils.java:267) ~[spring-beans-5.3.12.jar:5.3.12] at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:219) ~[spring-web-5.3.12.jar:5.3.12] at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:85) ~[spring-webmvc-5.3.12.jar:5.3.12] at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:147) ~[spring-web-5.3.12.jar:5.3.12] at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:121) ~[spring-web-5.3.12.jar:5.3.12] at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:179) ~[spring-web-5.3.12.jar:5.3.12]Lo que creo que podría estar sucediendo es que espera una implementación de IPerson, pero no puede encontrar una, pero no estoy seguro de si este tipo de llamada es posible y, si es así, qué configuración podría estar faltando.
Spring usa la reflexión para instanciar un atributo de modelo en un método de manejo de solicitudes. Intentará encontrar un constructor predeterminado y llamarlo.
Por diseño en Java, no puede crear una instancia de una interfaz (ni una clase abstracta), sino solo para clases concretas. Por lo tanto, su IPerson fallará ya que es una interfaz y su Person tendrá éxito ya que es una clase con un constructor.
En resumen, no puede usar interfaces para vincular variables a un objeto modelo, solo clases concretas.
Intente agregar la anotación @RequestBody a los parámetros. Además, sugiero cambiar RequestMapping a PostMapping
Ejemplo
@PostMapping("/hello") public String Hello(@RequestBody Person person) { return person.sayHello(); }