2012-05-31 4 views
11

Ich habe gerade eine REST-API zu meinem bestehenden Spring + BlazeDS + Hibernate-Server hinzugefügt und alles scheint zu funktionieren, wenn Daten als JSON abgerufen und serialisiert werden, aber wenn ich versuche, POST-Daten zu de- serialisiert in ein POJO bekomme ich die Ausnahme.JsonMappingException: Kann den Wert von type [simple type, a.b.c.Company] aus JSON String nicht instanzieren; keine single-String-Konstruktor-/Factory-Methode

Ich hatte den Eindruck, dass die Frühlingsanmerkungen und die Anwesenheit der Jackson Gläser im Klassenpfad alles sein würde, was erforderlich war, zumindest war es für meine Liste, Methoden zu löschen, die einfache Parameter hatten.

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 

Hier ist die Methode aufgerufen wird:

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

und hier ist die vollständige Ausnahme:

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) 

Update: hinzugefügt Definition der Firma 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(); 
    } 

} 

Aktualisieren Wenn ich das DTO so ändern, dass Jackson die Company.adminUserIdList-Eigenschaft ignoriert, wird der Datensatz erfolgreich erstellt.

@JsonIgnore 
public Collection<Integer> getAdminUserIdList() { return this.adminUserIdList; } 
@JsonIgnore 
public void setAdminUserIdList (Collection<Integer> adminUserIdList) { this.adminUserIdList = adminUserIdList; }  

aktualisieren Hier ist die Json wie durch die /company/get/1 Methode FireFox RESTClient

zurück
{ 
    "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 
} 

I ein ähnliches Muster wurde unter Verwendung von (weniger die "ID" und eine andere "uid") für die /compamy/create Anruf mit einem Content-type=application/json Header

+0

Sollte 'com.twoh.dto.Company' nicht einen String-Konstruktor haben, der der Fehlermeldung entspricht? – Stan

+0

Das ist, was die Nachricht impliziert, aber wenn es automatisch zu JSON serialisiert, warum nicht die andere Richtung. Wenn ich eine Methode schreiben muss, die die Arbeit erledigt, scheint sie das Objekt zu besiegen. In einer ähnlichen Frage http://stackoverflow.com/questions/8369260/jackson-throws-jsonmappingexception-on-deserialize-demands-single-string-constr wurde das getan, aber keines der Beispiele, die ich von Spring-REST-Diensten gesehen habe schlagen vor, dass dies für jeden POJO erforderlich ist. – hairyone

+0

Können Sie möglicherweise eine Deklaration der com.twoh.dto.Company-Klasse angeben? – Stan

Antwort

11

Ich löste das gleiche Problem durch die Festsetzung der JSON, die ich an den Server schickte; es war ungültig. Ich habe die Zeichen "," am Ende der letzten Attribute entfernt und es hat funktioniert. Ich hoffe, es hilft

+2

Ähnliches Problem für mich ... Ich habe die JSON als '{" Währung ":" 1 "}' geschickt, um sie einem POJO zuzuordnen, das ' 'in seinem XML-Format ergeben hätte. .. aber ich sah den Fehler, über den in diesem Thread gesprochen wurde ... bis ich mein json als "{" currency ": {" id ":" 1 "}}' festlegte – pulkitsinghal

0

In meinem Fall fehlte ich Anfang und Ende geschweiften Klammern.

Verwandte Themen