2014-10-26 30 views
6

我使用Spring 4.1.1与JavaConfig和Jackson 2.4.3。Spring不使用带注释的构造函数(@JsonCreator)进行实例化

我的控制器看起来是这样的:

@RestController 
public interface PatientWebService { 

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

的JSON我送这个样子的:

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

,我希望它被解析成这个类:

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 
} 

这是我得到的输出:

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 

如何配置Spring将实例化委托给Jackson?
是否可以结合使用@JsonCreator@RequestBody

我JavaConfig看起来是这样的:

@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

我得到一个完全不同的错误。它会尝试获取类的无参数构造函数是没有意义的。你确定你向我们展示确切的课程和错误吗? – 2014-10-26 18:11:14

+0

是的,很确定。因为如果我添加一个无参数的构造函数,错误消失,但是那个对象是空的。 从stacktrace中我可以看出,spring试图实例化bean本身,因此不关心'@ JsonCreator'注释。 – 2014-10-26 18:21:28

+0

我已经添加了我说的默认构造函数未找到的那部分堆栈跟踪。也许它有帮助。 – 2014-10-26 18:31:46

回答

4

虽然我没有用Spring 4.1.1(但是用Spring 4.0.5)测试过,但我发现问题是注释@RequestBody仅存在于界面中。

Spring不会从接口看方法参数的注解(甚至不知道这是否可能),但仅限于具体的实现。由于缺少对具体实现的注解,Spring确实试图使用Jackson来实例化对象,但是使用普通的bean方法。

如果你简单地添加注释的具体方法的参数为好,一切都将工作得很好

-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- 

春季尽量不带参数来初始化默认的构造函数豆,但你的构造得到对象。 你也写了一个界面,但我没有看到接口的实现

+0

你甚至读过这个问题,或只是看看堆栈跟踪? 我知道我的构造函数需要参数。它的意思就是这样。我想让杰克逊插入构造函数参数,这就是为什么构造函数用'@ JsonCreator'注释的原因。 正如您可以从堆栈跟踪中读取的,Spring会查找接口的实现。 – 2014-10-26 18:59:16

+0

据我了解你使用基于财产的创造者,请你可以把接口的实现 – 2014-10-26 19:03:37

+0

@RequestBody PatientResource资源:>也许因为这一行,春天试图初始化bean与默认构造函数 – 2014-10-26 19:05:42

相关问题