Skip to content

Deep custom bean validation can break saving of entity via REST #4684

@knstvk

Description

@knstvk

Environment

Jmix version: 2.6.1

Bug Description

There are 2 entities:

@JmixEntity
@Table(name = "REST_ROOT_ENTITY")
@Entity(name = "rest_RootEntity")
@ValidRootEntity
public class RootEntity {
    @JmixGeneratedValue
    @Column(name = "ID", nullable = false)
    @Id
    private UUID id;

    @NotNull
    @InstanceName
    @Column(name = "NAME")
    private String name;

    @NotNull
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "NESTED_ENTITY_ID")
    private NestedEntity nestedEntity;

@JmixEntity
@Table(name = "REST_NESTED_ENTITY")
@Entity(name = "rest_NestedEntity")
public class NestedEntity {
    @JmixGeneratedValue
    @Column(name = "ID", nullable = false)
    @Id
    private UUID id;

    @NotNull
    @InstanceName
    @Column(name = "NAME")
    private String name;

    @NotNull
    @Column(name = "CODE")
    private String code;

The root entity validation includes the nested state:

public class ValidRootEntityValidator implements ConstraintValidator<ValidRootEntity, RootEntity> {

    @Override
    public boolean isValid(RootEntity entity, ConstraintValidatorContext constraintValidatorContext) {
        return entity.getNestedEntity().getCode().equals("test");
    }
}

Trying to save the root entity using JSON which includes the link to nested entity:

{
  "id": "$ROOT_ID$",
  "name": "Entity 1",
  "nestedEntity": {
    "id": "$NESTED_ID$"
  }
}

Got exception:

jakarta.validation.ValidationException: HV000028: Unexpected exception during isValid call.
	at org.hibernate.validator.internal.engine.constraintvalidation.ConstraintTree.validateSingleConstraint(ConstraintTree.java:186) ~[hibernate-validator-8.0.2.Final.jar:8.0.2.Final]
	at ...
Caused by: java.lang.IllegalStateException: Cannot get unfetched attribute [code] from detached object io.jmix.samples.rest.entity.NestedEntity-cc2d10a7-8f7f-49be-be11-a7ef008c1376 [detached].
	at org.eclipse.persistence.internal.queries.EntityFetchGroup.onUnfetchedAttribute(EntityFetchGroup.java:100) ~[org.eclipse.persistence.core-4.0.6-2-jmix.jar:na]
	at io.jmix.eclipselink.impl.JmixEntityFetchGroup.onUnfetchedAttribute(JmixEntityFetchGroup.java:78) ~[jmix-eclipselink-2.7.999-SNAPSHOT.jar:na]
	at org.eclipse.persistence.internal.jpa.EntityManagerImpl.processUnfetchedAttribute(EntityManagerImpl.java:2996) ~[org.eclipse.persistence.jpa-4.0.6-2-jmix.jar:na]
	at io.jmix.samples.rest.entity.NestedEntity._persistence_checkFetched(NestedEntity.java) ~[main/:na]
	at io.jmix.samples.rest.entity.NestedEntity._persistence_get_code(NestedEntity.java) ~[main/:na]
	at io.jmix.samples.rest.entity.NestedEntity.getCode(NestedEntity.java:49) ~[main/:na]
	at io.jmix.samples.rest.entity.ValidRootEntityValidator.isValid(ValidRootEntityValidator.java:26) ~[main/:na]
	at io.jmix.samples.rest.entity.ValidRootEntityValidator.isValid(ValidRootEntityValidator.java:22) ~[main/:na]

Steps To Reproduce

See tests in the linked PR.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    No status

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions