Blazebit / blaze-persistence

Rich Criteria API for JPA providers
https://persistence.blazebit.com
Apache License 2.0
722 stars 84 forks source link

MappingSingular fields on EntityViews lead to exception when deserialiazed via jackson (spring boot integration) #1546

Open EugenMayer opened 1 year ago

EugenMayer commented 1 year ago

We are using @MappingSingular for entity views https://persistence.blazebit.com/documentation/1.6/entity-view/manual/en_US/#singular-collection-type-mappings

interface MyEntityView {
  @MappingSingular
  Set<String> getBaseDNs();
}

When this EntityView is posted on a PostPayload we get an exception

core  | org.springframework.http.converter.HttpMessageNotReadableException: Could not read document: Problem deserializing 'setterless' property 'baseDNs': get method returned null
core  |  at [Source: (PushbackInputStream); line: 1, column: 323] (through reference chain: de.kontextwork.dw.platform.borl.ldap.model.view.LdapServerConfigurationEntireView_$$_javassist_entityview_["baseDNs"]); nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Problem deserializing 'setterless' property 'baseDNs': get method returned null
core  |  at [Source: (PushbackInputStream); line: 1, column: 323] (through reference chain: de.kontextwork.dw.platform.borl.ldap.model.view.LdapServerConfigurationEntireView_$$_javassist_entityview_["baseDNs"])
core  |     at com.blazebit.persistence.spring.data.webmvc.impl.json.EntityViewAwareMappingJackson2HttpMessageConverter.readJavaType(EntityViewAwareMappingJackson2HttpMessageConverter.java:88) ~[blaze-persistence-integration-spring-data-webmvc-9.42-SNAPSHOT.jar:9.42-SNAPSHOT]
core  |     at com.blazebit.persistence.spring.data.webmvc.impl.json.EntityViewAwareMappingJackson2HttpMessageConverter.read(EntityViewAwareMappingJackson2HttpMessageConverter.java:74) ~[blaze-persistence-integration-spring-data-webmvc-9.42-SNAPSHOT.jar:9.42-SNAPSHOT]

Version: current master bb1c1a0b7c4c71fc64e53fd03cac5b383b028fa0 JPA-Provider: hibernate Application Server: spring boot 2.7.3

beikov commented 11 months ago

Can you please provide a reproducer for this problem? It seems very similar to https://github.com/Blazebit/blaze-persistence/issues/1289. Your example doesn't use @CreatableEntityView or @UpdatableEntityView, though I'm not sure if this was simply an oversight when you wrote the issue description. Deserializing read-only entity views is not supported.

EugenMayer commented 11 months ago

It's not really about updating or creating anything AFAICs. It's actually about a view. So we post a normal view, not a CV/UV. Maybe clearer: This issue is about deserialization of views as POST payloads, not paticular CV or UV.

This one is not working:

@EntityView(LdapGroupConfiguration::class)
interface LdapGroupConfigurationEntireView : LdapGroupConfigurationIdView {
    val syncEnabled: Boolean

    @get:MappingSingular
    val baseDNs: MutableSet<String>
    val idAttr: String
    val nameAttr: String
    val memberAttr: String
    val objectClass: String?
    val customerProvidedFilter: String?
}

Since we cannot use the view above for deserialization, we use a DTO instead:


/**
 * Represents a server configuration draft
 * Since we cannot use the [LdapGroupConfigurationEntireView] view due to
 * https://github.com/Blazebit/blaze-persistence/issues/1546 and mapping singular, we are using this DTO.
 *
 * FIXME: consider using [LdapGroupConfigurationEntireView] instead when the issue has been solved.
 */
class LdapGroupConfigurationDraftDTO(
    override var syncEnabled: Boolean = false,
    override var baseDNs: MutableSet<String>,
    override var idAttr: String = "",
    override var nameAttr: String = "",
    override var memberAttr: String = "",

    @JsonIgnore
    override var id: Long = 0,
    override var customerProvidedFilter: String? = null,
    override var objectClass: String = "",
) : LdapGroupConfigurationEntireView

Does this help?

beikov commented 11 months ago

This issue is about deserialization of views as POST payloads, not paticular CV or UV.

But that's exactly what I am saying, this is not supported.

Deserializing read-only entity views is not supported.

See this ^

EugenMayer commented 11 months ago

This is a fairly huge limitation, is it? This means that all EV can only be used for output, but not for input. While i understand that CV/UV are the ones that are semantically used when using a persistence layer manipulative call, but EVs can be used to simply transfer data.

For now, we have seen EVs as a (better) replacement DTOs in yet all cases. This would mean, that deserializing EVs is not possible at all. Esp. microservice to microservice communication can be strongly affected by this limitation.

What are your thoughts on this?