我正在构建一个Spring Data REST应用程序,当我尝试POST它时,我遇到了一些问题。主实体有其他两个相关实体嵌套。
有一个“问号”对象有很多答案,每个答案都有很多回复。
我从前端应用程序生成一个类似这样的JSON来POST问题:
{
"user": "http://localhost:8080/users/1",
"status": 1,
"answers": [
{
"img": "urlOfImg",
"question": "http://localhost:8080/question/6",
"replies": [
{
"literal": "http://localhost:8080/literal/1",
"result": "6"
},
{
"literal": "http://localhost:8080/literal/1",
"result": "6"
}
]
},
{
"img": "urlOfImg",
"question": "http://localhost:8080/question/6",
"replies": [
{
"literal": "http://localhost:8080/literal/3",
"result": "10"
}
]
}
]
}
但是当我尝试发布它时,我得到了以下错误响应:
{
"cause" : {
"cause" : {
"cause" : null,
"message" : "Template must not be null or empty!"
},
"message" : "Template must not be null or empty! (through reference chain: project.models.Questionary[\"answers\"])"
},
"message" : "Could not read JSON: Template must not be null or empty! (through reference chain: project.models.Questionary[\"answers\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Template must not be null or empty! (through reference chain: project.models.Questionary[\"answers\"])"
}
编辑:
我还添加了我的存储库:
@RepositoryRestResource(collectionResourceRel = "questionaries", path = "questionaries")
public interface InspeccionRepository extends JpaRepository<Inspeccion, Integer> {
@RestResource(rel="byUser", path="byUser")
public List<Questionary> findByUser (@Param("user") User user);
}
我的实体问题类是:
@Entity @Table(name="QUESTIONARY", schema="enco" )
public class Questionary implements Serializable {
private static final long serialVersionUID = 1L;
//----------------------------------------------------------------------
// ENTITY PRIMARY KEY ( BASED ON A SINGLE FIELD )
//----------------------------------------------------------------------
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEC_QUESTIONARY")
@SequenceGenerator(name = "SEC_QUESTIONARY", sequenceName = "ENCO.SEC_QUESTIONARY", allocationSize = 1)
@Column(name="IDQUES", nullable=false)
private Integer idques ;
//----------------------------------------------------------------------
// ENTITY DATA FIELDS
//----------------------------------------------------------------------
@Column(name="ESTATUS")
private Integer estatus ;
//----------------------------------------------------------------------
// ENTITY LINKS ( RELATIONSHIP )
//----------------------------------------------------------------------
@ManyToOne
@JoinColumn(name="IDUSER", referencedColumnName="IDUSER")
private User user;
@OneToMany(mappedBy="questionary", targetEntity=Answer.class)
private List<Answer> answers;
//----------------------------------------------------------------------
// CONSTRUCTOR(S)
//----------------------------------------------------------------------
public Questionary()
{
super();
}
//----------------------------------------------------------------------
// GETTERS & SETTERS FOR FIELDS
//----------------------------------------------------------------------
//--- DATABASE MAPPING : IDNSE ( NUMBER )
public void setIdnse( Integer idnse )
{
this.idnse = idnse;
}
public Integer getIdnse()
{
return this.idnse;
}
//--- DATABASE MAPPING : ESTADO ( NUMBER )
public void setEstatus Integer estatus )
{
this.estatus = estatus;
}
public Integer getEstatus()
{
return this.estatus;
}
//----------------------------------------------------------------------
// GETTERS & SETTERS FOR LINKS
//----------------------------------------------------------------------
public void setUser( Usuario user )
{
this.user = user;
}
public User getUser()
{
return this.user;
}
public void setAnswers( List<Respuesta> answers )
{
this.answers = answer;
}
public List<Answer> getAnswers()
{
return this.answers;
}
// Get Complete Object method public List<Answer>
getAnswerComplete() {
List<Answer> answers = this.answers;
return answers;
}
}
我的答案实体:
@Entity @Table(name="ANSWER", schema="enco" ) public class Answer
implements Serializable {
private static final long serialVersionUID = 1L;
//----------------------------------------------------------------------
// ENTITY PRIMARY KEY ( BASED ON A SINGLE FIELD )
//----------------------------------------------------------------------
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "SEC_ANSWER")
@SequenceGenerator(name = "SEC_ANSWER", sequenceName = "ENCOADMIN.SEC_ANSWER", allocationSize = 1)
@Column(name="IDANS", nullable=false)
private Integer idans ;
//----------------------------------------------------------------------
// ENTITY DATA FIELDS
//----------------------------------------------------------------------
@Column(name="IMG", length=100)
private String img ;
//----------------------------------------------------------------------
// ENTITY LINKS ( RELATIONSHIP )
//----------------------------------------------------------------------
@ManyToOne
@JoinColumn(name="IDQUES", referencedColumnName="IDQUES")
private Questionary questionary ;
@OneToMany(mappedBy="answer", targetEntity=Reply.class)
private List<Reply> replies;
@ManyToOne
@JoinColumn(name="IDQUE", referencedColumnName="IDQUE")
private Question Question ;
//----------------------------------------------------------------------
// CONSTRUCTOR(S)
//----------------------------------------------------------------------
public Answer()
{
super();
}
//----------------------------------------------------------------------
// GETTER & SETTER FOR THE KEY FIELD
//----------------------------------------------------------------------
public void setIdans( Integer idans )
{
this.idans = idans ;
}
public Integer getIdans()
{
return this.idans;
}
//----------------------------------------------------------------------
// GETTERS & SETTERS FOR FIELDS
//----------------------------------------------------------------------
//--- DATABASE MAPPING : IMAGEN ( VARCHAR2 )
public void setImg( String img )
{
this.img = img;
}
public String getImg()
{
return this.img;
}
//----------------------------------------------------------------------
// GETTERS & SETTERS FOR LINKS
//----------------------------------------------------------------------
public void setQuestionary( Questionary questionary )
{
this.questionary = questionary;
}
public Questionary getQuestionary()
{
return this.questionary;
}
public void setReplies( List<Reply> contestaciones )
{
this.replies = replies;
}
public List<Reply> getReplies()
{
return this.replies;
}
public void setQuestion( Question question )
{
this.question = question;
}
public Question getQuestion()
{
return this.question;
}
}
这是错误控制台:
Caused by: com.fasterxml.jackson.databind.JsonMappingException:
Template must not be null or empty! (through reference chain:
project.models.Questionary["answers"]) at
com.fasterxml.jackson.databind.JsonMappingException.wrapWithPath(JsonMappingException.java:232)
~[jackson-databind-2.3.3.jar:2.3.3] at *snip*
答案 0 :(得分:17)
尝试在课程@RestResource(exported = false)
中的字段answers
上添加Questionary
。
据我所知,出现此错误是因为反序列化器需要URI来获取答案,而不是将答案嵌套在JSON中。添加注释会使其以JSON格式查找。
答案 1 :(得分:5)
我仍然看到2.3.0.M1的这个错误,但我终于找到了解决方法。
基本问题是:如果你在JSON中发布嵌入实体的url,它就可以了。如果您发布实际的嵌入式实体JSON,则不会。它试图将实体JSON反序列化为URI,这当然是失败的。
看起来问题在于Spring数据休息在其配置中创建的两个TypeConstrainedMappingJackson2HttpMessageConverter对象(在RepositoryRestMvcConfiguration.defaultMessageConverters()中)。
我终于通过配置messageConverters支持的媒体类型来解决这个问题,以便它跳过这两个并点击普通的MappingJackson2HttpMessageConverter,它可以与嵌套实体一起使用。
例如,如果扩展RepositoryRestMvcConfiguration并添加此方法,那么当您发送内容类型为“application / json”的请求时,它将触及普通的MappingJackson2HttpMessageConverter,而不是尝试反序列化为URI:
@Override
public void configureHttpMessageConverters(List<HttpMessageConverter<?>> messageConverters) {
((MappingJackson2HttpMessageConverter) messageConverters.get(0))
.setSupportedMediaTypes(asList(MediaTypes.HAL_JSON));
((MappingJackson2HttpMessageConverter) messageConverters.get(2))
.setSupportedMediaTypes(asList(MediaType.APPLICATION_JSON));
}
用于配置RepositoryRestMvcConfiguration中defaultMessageConverters()生成的消息转换器。
请记住,普通的objectMapper无法处理JSON中的URI - 每次传递嵌入式实体的URI时,您仍需要点击两个预配置的消息转换器中的一个。
答案 2 :(得分:4)
您的JSON的一个问题是您尝试将字符串反序列化为一个问题:
"question": "http://localhost:8080/question/6"
在你的Answer
对象中,杰克逊期待一个问题的对象。您似乎正在使用ID的URL,因此您需要为您的问题传递类似的字符串而不是字符串:
"question": {
"id": "http://localhost:8080/question/6"
}
答案 3 :(得分:0)
尝试更新“Spring Boot Data REST Starter”库。为我工作。