我刚刚添加了一个REST api到我现有的
Spring BlazeDS Hibernate服务器,并且当数据被检索和序列化为
JSON时,一切似乎都可以工作,但是当我尝试将POST数据解串行化到POJO中时,我得到一个异常.
我的印象是,春天的注释和杰克逊罐子在类路径中的存在将是所有需要的,至少是我的列表,获取,删除具有简单参数的方法.
org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type,class com.twoh.dto.Company] from JSON String; no single-String constructor/factory method
public abstract class BaseEntityService<T extends BaseEntity> implements IBaseEntityService<T> { private IBaseEntityDAO<T> DAO; @Autowired private ValidationResultHelper validationResultHelper; public void setDAO(IBaseEntityDAO<T> DAO) { this.DAO = DAO; } ... @Secured("ROLE_USER") @RequestMapping(value="/create",method=RequestMethod.POST) public @ResponseBody ValidationResult create(@RequestBody T entity) { ValidationResult result = null; try { result = DAO.persistEntity(entity); } catch(JDBCException e) { result = ExceptionHelper.getValidationResult(e); } catch(DataIntegrityViolationException e) { result = ExceptionHelper.getValidationResult(e); } validationResultHelper.log(DAO.getSession(),entity.getId(),entity.getClass(),result); return result; } }
这里是完全例外:
org.codehaus.jackson.map.JsonMappingException: Can not instantiate value of type [simple type,class com.twoh.dto.Company] from JSON String; no single-String constructor/factory method at org.codehaus.jackson.map.deser.std.StdValueInstantiator._createFromStringFallbacks(StdValueInstantiator.java:379) at org.codehaus.jackson.map.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:268) at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromString(BeanDeserializer.java:759) at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:585) at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:2723) at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1914) at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readInternal(MappingJacksonHttpMessageConverter.java:135) at org.springframework.http.converter.AbstractHttpMessageConverter.read(AbstractHttpMessageConverter.java:154) at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.readWithMessageConverters(HandlerMethodInvoker.java:633) at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveRequestBody(HandlerMethodInvoker.java:597) at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:346) at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:171) at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436) at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424) at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790) at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719) at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669) at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:585) at javax.servlet.http.HttpServlet.service(HttpServlet.java:637) at javax.servlet.http.HttpServlet.service(HttpServlet.java:717) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:311) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:101) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.authentication.logout.logoutFilter.doFilter(logoutFilter.java:105) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:323) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:173) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:857) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Unknown Source)
更新:添加公司DTO的定义
@CheckDictionaryProperty.List({ @CheckDictionaryProperty(propertyName="partyId",dictionaryName="Party") }) @Unique.List({ @Unique(properties = {"code"},message = "UNIQUE_CODE"),@Unique(properties = {"name"},message = "UNIQUE_NAME") }) @Entity @FXClass @Table(name="edrcompany") @JsonAutoDetect public class Company extends BaseEntity { private static final long serialVersionUID = 1L; public Company(){} @NotBlank @Column private String name; public String getName(){ return this.name; } public void setName(String name){ this.name = name; } @Column private String code; public String getCode() { return this.code; } public void setCode(String code) { this.code = code; } @NotNull @Column(name="party_id") private Integer partyId; public Integer getPartyId() { return this.partyId; } public void setPartyId(Integer partyId) { this.partyId = ValueHelper.isNullOrZero(partyId) ? null : partyId; } @ElementCollection(targetClass=Integer.class,fetch=FetchType.EAGER) @Fetch(FetchMode.SUBSELECT) @CollectionTable(name="edrcompanyadminlink",joinColumns={@JoinColumn(name="company_id")}) @Column(name="user_id") private Collection<Integer> adminUserIdList = new HashSet<Integer>(); public Collection<Integer> getAdminUserIdList() { return this.adminUserIdList; } public void setAdminUserIdList (Collection<Integer> adminUserIdList) { this.adminUserIdList = adminUserIdList; } } @MappedSuperclass @FXClass public abstract class BaseEntity implements Serializable { private static final long serialVersionUID = 1L; public BaseEntity(){} @Id @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") private Integer id; public Integer getId() { return id; } public void setId(Integer id) { this.id = ValueHelper.isNullOrZero(id) ? null : id; } @Column(name="ENTITY_UID",unique=true,nullable=false,updatable=false,length=36) /* Assign a default whenever this class is instantiated Hibernate will * overwrite it when retrieving an entity from the DB. */ private String uid = UUID.randomUUID().toString(); public String getUID() { return uid; }; public void setUID(String uid) { this.uid = uid; } @Version @Column private Integer version; @FXIgnore public Integer getVersion() { return this.version; } public void setVersion(Integer version) { this.version = version; } // Fake property so that DTO2FX will put it in public String getClassName() { return this.getClass().getName(); } @JsonIgnore public void setClassName(String className) { throw new UnsupportedOperationException(); } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || !(o instanceof BaseEntity)) return false; BaseEntity other = (BaseEntity) o; // if the id is missing,return false if (uid == null) return false; // equivalence by uid return uid.equals(other.getUID()); } @Override public int hashCode() { if (uid != null) { return uid.hashCode(); } else { return super.hashCode(); } } @Override public String toString() { return this.getClassName() + ": " + this.getId(); } }
更新
如果我修改了DTO,以便Jackson忽略了Company.adminUserIdList属性,那么记录创建成功.
@JsonIgnore public Collection<Integer> getAdminUserIdList() { return this.adminUserIdList; } @JsonIgnore public void setAdminUserIdList (Collection<Integer> adminUserIdList) { this.adminUserIdList = adminUserIdList; }
更新
这是使用FireFox RESTClient由/ company / get / 1方法返回的Json
{ "partyId":1,"adminUserIdList":[21],"name":"2H Mechanical LLC","code":null,"uid":"fc5e15e7-a9a7-11e1-be90-7d08b05cbb96","id":1,"className":"com.twoh.dto.Company","version":0 }
我使用一个类似的模式(更少的“id”和不同的“uid”)为/ compamy /创建调用与Content-type = application / json标题