I have a some entities in the database that I'm editing with Spring Data Rest.
All of them have this as a base class:
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@JsonTypeInfo(use=JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes(
JsonSubTypes.Type(value = TextComponent::class, name = TextComponent.TYPE),
JsonSubTypes.Type(value = TextAreaComponent::class, name = TextAreaComponent.TYPE)
)
abstract class AbstractLabelComponent(
@field:ManyToOne
@field:JsonIgnore
open val template: Template?,
@field:Id
@field:GeneratedValue(strategy = GenerationType.AUTO)
open var id: Long? = null
)
Here is a middle class (I'm not sure if it is important so better have it than not):
@Entity
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
abstract class AbstractTextComponent(
template: Template?,
@field:ManyToOne(optional = false)
open var font: Font,
): AbstractLabelComponent(template)
And here is a child class. Posting only one because all of them behave the same way.
@Entity
class TextComponent(
template: Template? = null,
font: Font,
): AbstractTextComponent(template){
companion object {
const val TYPE = "text"
}
}
And here is the template that has a list of components:
@Entity
data class Template(
@field:OneToMany(mappedBy = "template", cascade = [CascadeType.ALL], orphanRemoval = true)
var components: MutableList<AbstractLabelComponent> = mutableListOf()
@field:Id
@field:GeneratedValue(strategy = GenerationType.AUTO)
open var id: Long? = null
)
I'm sending the following JSON to the API:
{
"components": [
{
"alignment": 0,
"content": "",
"fieldID": "TEXT",
"font": "/api/fonts/9",
"rotation": 0,
"type": "text",
"x": 84,
"y": 36
}
],
}
But I'm getting this error:
JSON parse error: Instantiation of [simple type, class com.components.TextComponent] value failed for JSON property font due to missing (therefore NULL) value for creator parameter font which is a non-nullable type
I figured it is because the font property in the constructor is not optional, so I made it optional. But then I received an error from the DB that font_id
has no default value, so I think the real problem is that the font is not deserialized or passed properly.
Also weird that if I have the URI to the font in an array it complains that arrays can not be converted to Font, so I guess it can deserialize but it does not pass it to the constructor. Before that, I had it as a JSON of the Font but got the same error as now so I thought I should use URIs instead.
Here is the Font class:
@Entity
data class Font(
var humanReadable: String = "",
private val width: Int = 1,
private val height: Int = 1,
@field:Id
@field:GeneratedValue(strategy = GenerationType.AUTO)
open var id: Long? = null
)
I just tried with an other component that has no Font
and got the same error that I mentioned that I get when the font is optional on my components:
java.sql.SQLException: Field 'bold_font_id' doesn't have a default value
Here is the other component that has no font:
@Entity
class CodeComponent(
template: Template? = null,
private var code: String = ""
): AbstractLabelComponent(template) {
Here is that one component that has bold_font. I wasn't using this while I copied the errors below:
@Entity
class TextAreaComponent(
template: Template? = null,
content: String = "",
font: Font,
@field:ManyToOne(optional = false)
var boldFont: Font
): AbstractTextComponent(template, font,content)
Here is the repository of the template entity:
@Repository
interface TemplateRepository: CrudRepository<Template, Long>{
}
CodePudding user response:
It seems to me that you have a bold_font_id
column in your database table, but I can't see any such property in your model classes that map to such a column. Make sure you have a property matching every column in your database table or if not, you will have to assign default values in your database schema while creating it.