2014-10-26 22 views
6

Sto usando Spring 4.1.1 con JavaConfig e Jackson 2.4.3.Spring non usa il costruttore annotato (@JsonCreator) per l'istanziazione

mio regolatore di simile a questa:

@RestController 
public interface PatientWebService { 

    @RequestMapping(value = "/patients", method = POST) 
    PatientResource createPatient(@RequestBody PatientResource resource); 
} 

JSON mando si presenta così:

{ 
    "firstName": "Max", 
    "lastName": "Mustermann", 
    "birthDate": "1964-04-14", 
    "sex": "MAN" 
} 

e io voglio che sia analizzato in questa classe:

package at.landsteiner.patient.web; 

import at.landsteiner.patient.Patient; 
import at.landsteiner.patient.Sex; 
import at.landsteiner.web.EntityResource; 
import com.fasterxml.jackson.annotation.JsonCreator; 
import com.fasterxml.jackson.annotation.JsonProperty; 

import java.time.LocalDate; 

public class PatientResource extends EntityResource { 

    private String firstName; 
    private String lastName; 
    private LocalDate birthDate; 
    private Sex sex; 

    @JsonCreator 
    public PatientResource(@JsonProperty("firstName") String firstName, @JsonProperty("lastName") String lastName, @JsonProperty("birthDate") LocalDate birthDate, @JsonProperty("sex") Sex sex) { 
     this.firstName = firstName; 
     this.lastName = lastName; 
     this.birthDate = birthDate; 
     this.sex = sex; 
    } 

    // getter 
} 

Questo è l'output che sto ottenendo:

19:43:41,842 INFO [stdout] (default task-1) 19:43:41 DEBUG o.s.w.s.DispatcherServlet.doService - DispatcherServlet with name 'DispatcherServlet' processing POST request for [/questionnaire-api/patients] 
19:43:41,846 INFO [stdout] (default task-1) 19:43:41 DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping.getHandlerInternal - Looking up handler method for path /patients 
19:43:41,850 INFO [stdout] (default task-1) 19:43:41 DEBUG o.s.w.s.m.m.a.RequestMappingHandlerMapping.getHandlerInternal - Returning handler method [public at.landsteiner.patient.web.PatientResource at.landsteiner.patient.web.PatientWebServiceImpl.createPatient(at.landsteiner.patient.web.PatientResource)] 
19:43:41,850 INFO [stdout] (default task-1) 19:43:41 DEBUG o.s.b.f.s.DefaultListableBeanFactory.doGetBean - Returning cached instance of singleton bean 'patientWebServiceImpl' 
19:43:41,868 INFO [stdout] (default task-1) 19:43:41 DEBUG o.s.w.s.m.m.a.ExceptionHandlerExceptionResolver.resolveException - Resolving exception from handler [public at.landsteiner.patient.web.PatientResource at.landsteiner.patient.web.PatientWebServiceImpl.createPatient(at.landsteiner.patient.web.PatientResource)]: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [at.landsteiner.patient.web.PatientResource]: No default constructor found; nested exception is java.lang.NoSuchMethodException: at.landsteiner.patient.web.PatientResource.<init>() 
19:43:41,869 INFO [stdout] (default task-1) 19:43:41 DEBUG o.s.w.s.m.a.ResponseStatusExceptionResolver.resolveException - Resolving exception from handler [public at.landsteiner.patient.web.PatientResource at.landsteiner.patient.web.PatientWebServiceImpl.createPatient(at.landsteiner.patient.web.PatientResource)]: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [at.landsteiner.patient.web.PatientResource]: No default constructor found; nested exception is java.lang.NoSuchMethodException: at.landsteiner.patient.web.PatientResource.<init>() 
19:43:41,870 INFO [stdout] (default task-1) 19:43:41 DEBUG o.s.w.s.m.s.DefaultHandlerExceptionResolver.resolveException - Resolving exception from handler [public at.landsteiner.patient.web.PatientResource at.landsteiner.patient.web.PatientWebServiceImpl.createPatient(at.landsteiner.patient.web.PatientResource)]: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [at.landsteiner.patient.web.PatientResource]: No default constructor found; nested exception is java.lang.NoSuchMethodException: at.landsteiner.patient.web.PatientResource.<init>() 
19:43:41,878 INFO [stdout] (default task-1) 19:43:41 DEBUG o.s.w.s.DispatcherServlet.processRequest - Could not complete request 
19:43:41,879 INFO [stdout] (default task-1) org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [at.landsteiner.patient.web.PatientResource]: No default constructor found; nested exception is java.lang.NoSuchMethodException: at.landsteiner.patient.web.PatientResource.<init>() 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:107) ~[spring-beans-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.createAttribute(ModelAttributeMethodProcessor.java:139) ~[spring-web-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.servlet.mvc.method.annotation.ServletModelAttributeMethodProcessor.createAttribute(ServletModelAttributeMethodProcessor.java:79) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.method.annotation.ModelAttributeMethodProcessor.resolveArgument(ModelAttributeMethodProcessor.java:105) ~[spring-web-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.method.support.HandlerMethodArgumentResolverComposite.resolveArgument(HandlerMethodArgumentResolverComposite.java:77) ~[spring-web-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.method.support.InvocableHandlerMethod.getMethodArgumentValues(InvocableHandlerMethod.java:157) ~[spring-web-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:124) ~[spring-web-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:104) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.java:781) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877) ~[spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:868) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at javax.servlet.http.HttpServlet.service(HttpServlet.java:707) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar!/:1.0.0.Final] 
19:43:41,879 INFO [stdout] (default task-1) at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842) [spring-webmvc-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,879 INFO [stdout] (default task-1) at javax.servlet.http.HttpServlet.service(HttpServlet.java:790) [jboss-servlet-api_3.1_spec-1.0.0.Final.jar!/:1.0.0.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.ServletHandler.handleRequest(ServletHandler.java:85) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.security.ServletSecurityRoleHandler.handleRequest(ServletSecurityRoleHandler.java:61) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.ServletDispatchingHandler.handleRequest(ServletDispatchingHandler.java:36) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at org.wildfly.extension.undertow.security.SecurityContextAssociationHandler.handleRequest(SecurityContextAssociationHandler.java:78) [wildfly-undertow-8.1.0.Final.jar!/:8.1.0.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.security.SSLInformationAssociationHandler.handleRequest(SSLInformationAssociationHandler.java:113) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.security.ServletAuthenticationCallHandler.handleRequest(ServletAuthenticationCallHandler.java:56) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.security.handlers.AbstractConfidentialityHandler.handleRequest(AbstractConfidentialityHandler.java:45) [undertow-core-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.security.ServletConfidentialityConstraintHandler.handleRequest(ServletConfidentialityConstraintHandler.java:61) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.security.handlers.AuthenticationMechanismsHandler.handleRequest(AuthenticationMechanismsHandler.java:58) [undertow-core-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.security.CachedAuthenticatedSessionHandler.handleRequest(CachedAuthenticatedSessionHandler.java:70) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.security.handlers.SecurityInitialHandler.handleRequest(SecurityInitialHandler.java:76) [undertow-core-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at org.wildfly.extension.undertow.security.jacc.JACCContextIdHandler.handleRequest(JACCContextIdHandler.java:61) [wildfly-undertow-8.1.0.Final.jar!/:8.1.0.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,882 INFO [stdout] (default task-1) at io.undertow.server.handlers.PredicateHandler.handleRequest(PredicateHandler.java:25) [undertow-core-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,883 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.ServletInitialHandler.handleFirstRequest(ServletInitialHandler.java:240) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,883 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.ServletInitialHandler.dispatchRequest(ServletInitialHandler.java:227) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,883 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.ServletInitialHandler.access$000(ServletInitialHandler.java:73) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,883 INFO [stdout] (default task-1) at io.undertow.servlet.handlers.ServletInitialHandler$1.handleRequest(ServletInitialHandler.java:146) [undertow-servlet-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,883 INFO [stdout] (default task-1) at io.undertow.server.Connectors.executeRootHandler(Connectors.java:177) [undertow-core-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,883 INFO [stdout] (default task-1) at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727) [undertow-core-1.0.15.Final.jar!/:1.0.15.Final] 
19:43:41,883 INFO [stdout] (default task-1) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142) [na:1.8.0] 
19:43:41,883 INFO [stdout] (default task-1) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) [na:1.8.0] 
19:43:41,883 INFO [stdout] (default task-1) at java.lang.Thread.run(Thread.java:744) [na:1.8.0] 
19:43:41,884 INFO [stdout] (default task-1) Caused by: java.lang.NoSuchMethodException: at.landsteiner.patient.web.PatientResource.<init>() 
19:43:41,884 INFO [stdout] (default task-1) at java.lang.Class.getConstructor0(Class.java:2971) ~[na:1.8.0] 
19:43:41,884 INFO [stdout] (default task-1) at java.lang.Class.getDeclaredConstructor(Class.java:2165) ~[na:1.8.0] 
19:43:41,884 INFO [stdout] (default task-1) at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:104) ~[spring-beans-4.1.1.RELEASE.jar:4.1.1.RELEASE] 
19:43:41,884 INFO [stdout] (default task-1) ... 43 common frames omitted 

Come configurare Spring per delegare l'istanza a Jackson?
È persino possibile combinare l'uso di @JsonCreator con @RequestBody?

mio JavaConfig si presenta così:

@Configuration 
@EnableWebMvc 
@ComponentScan(basePackages = { "at.landsteiner" }) 
public class WebConfig extends WebMvcConfigurerAdapter { 

    @Override 
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) { 
     converters.add(converter()); 
    } 

    @Bean 
    public MappingJackson2HttpMessageConverter converter() { 
     ObjectMapper mapper = new ObjectMapper(); 

     mapper.registerModule(new JSR310Module()); 
     mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false); 

     return new MappingJackson2HttpMessageConverter(mapper); 
    } 
} 
+0

ottengo un errore di completamente diverso. Non ha senso che proverà a ottenere il costruttore senza parametri della tua classe. Sei sicuro di mostrarci le classi esatte e l'errore? –

+0

Sì, abbastanza sicuro. Perché se aggiungo un costruttore senza parametri, l'errore scompare, ma l'oggetto è vuoto. Dalla stacktrace posso dire che la primavera prova ad istanziare il bean stesso e quindi non si preoccupa dell'annotazione '@ JsonCreator'. –

+0

Ho aggiunto la parte dello stacktrace dove dico, costruttore predefinito non trovato. Forse aiuta. –

risposta

4

Anche se non ho la prova con la Primavera 4.1.1 (ma fatto con Primavera 4.0.5), ho scoperto che il problema è che l'annotazione @RequestBody è presente solo nell'interfaccia.

Spring non esaminerà l'annotazione dell'argomento del metodo dall'interfaccia (non è nemmeno sicuro se è possibile), ma solo dall'implementazione concreta.

A causa dell'annotazione mancante sull'implementazione concreta, Spring tenta di utilizzare Jackson affatto per creare un'istanza dell'oggetto, ma utilizza il metodo del bean normale.

Se è sufficiente aggiungere l'annotazione l'argomento del metodo concreto e, tutto funzionerà bene

-1
org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [at.landsteiner.patient.web.PatientResource]: No default constructor found; nested exception is java.lang.NoSuchMethodException: at.landsteiner.patient.web.PatientResource.<init>() 
19:43:41,879 INFO [stdout] (default task- 

primavera provare a inizializzare di fagioli con costruttore di default senza argomenti, ma il vostro costruttore diventa oggetto. Inoltre è scritto un'interfaccia, ma non ho visto implementazione dell'interfaccia

+0

Hai letto la domanda o guardi semplicemente lo stacktrace? So che il mio costruttore accetta argomenti. È pensato per essere in questo modo. Voglio che Jackson inserisca gli argomenti del costruttore, ecco perché il costruttore è annotato con '@ JsonCreator'. Come si può leggere dallo stacktrace, le molle trovano un'implementazione dell'interfaccia. –

+0

Se ho capito che hai utilizzato i creatori basati su Property, puoi mettere l'implementazione dell'interfaccia –

+0

risorsa @RequestBody PatientResource:> forse a causa di questa riga, spring tenta di inizializzare bean con il costruttore predefinito –

Problemi correlati