Form data not saved for EmbeddedParameters with nullAllowed = true

When @Embedded is used, and it has @EmbeddedParameters(nullAllowed = true), no data will be saved for its (embedded) fields even if all the fields are entered in a view.

An example project:
component-with-embeddable.zip (1.0 MB)

How to reproduce:

a) Working example:

  • Open http://localhost:8080/test-entities
  • Click the “Create” button and enter 1 in all 4 fields.
  • Click the “OK” button.
  • A new line with 4 1s in all the columns is added.

b) Non-working example:

  • Stop the application.
  • Open com/company/componentwithembeddable/entity/TestEntity.java and change the only @EmbeddedParameters(nullAllowed = false) to @EmbeddedParameters(nullAllowed = true) <= changed to true
  • Open com/company/componentwithembeddable/entity/CodedText.java and change the only @EmbeddedParameters(nullAllowed = false) to @EmbeddedParameters(nullAllowed = true) <= changed to true
  • Run the application.
  • Open http://localhost:8080/test-entities
  • Click the “Create” button and enter 2 in all 4 fields.
  • Click the “OK” button.
  • A new line with 2 in the first column is added, but the other 3 columns are empty (the data was not saved for them).

A similar behavoir was reported in Entity inspector errors with embedded entity, but it relates to creating records using Entity Inspector. Dmitriy recommended: “Therefore, to edit this type of entity, you need to create your own views.” This is what I created in the attached project and it still doesn’t save the embedded fields. It lets you enter the values, but it doesn’t add them to the view’s DataContext.

The view can check that the nullable embedded property has values for some of its fields and it is not null. If I understand Dmitriy, the nullable embedded property (entity) is not created when the view is opened which is probably causing the problems. The embedded entity should be created and placed in the view’s DataContext. If upon saving the view’s DataContext, all the fields for the embedded entity are null, then the embedded entity should be set to null in the DataContext. Otherwise the values should be saved.

Can we please treat this as a bug :pray:


Jmix version: 2.5.1
Jmix Studio Plugin Version: 2.5.1-243
IntelliJ version: IntelliJ IDEA 2024.3.5 (Community Edition)

Hi Borut,

Thank you for the test project and detailed description.

But it works as designed: with @EmbeddedParameters(nullAllowed = true) it’s your responsibility to create instances of embedded objects. For example, you can do it in the view’s event (for newly created entities):

public class TestEntityDetailView extends StandardDetailView<TestEntity> {
    @Autowired
    private Metadata metadata;

    @Subscribe
    public void onInitEntity(final InitEntityEvent<TestEntity> event) {
        TestEntity testEntity = event.getEntity();
        CodedText codedValue = metadata.create(CodedText.class);
        Code code = metadata.create(Code.class);

        codedValue.setCode(code);
        testEntity.setCodedValue(codedValue);
    }
}

and in EntityLoadingEvent listener (for entities loaded from the database):

@Component
public class TestEntityEventListener {

    private final Metadata metadata;

    public TestEntityEventListener(Metadata metadata) {
        this.metadata = metadata;
    }

    @EventListener
    public void onTestEntityLoading(final EntityLoadingEvent<TestEntity> event) {
        TestEntity testEntity = event.getEntity();
        if (testEntity.getCodedValue() == null) {
            Code code = metadata.create(Code.class);
            CodedText codedText = metadata.create(CodedText.class);
            codedText.setCode(code);
            testEntity.setCodedValue(codedText);
        }
    }
}

The Jmix annotation @EmbeddedParameters(nullAllowed = false) saves you from writing this boilerplate code.

Regards,
Konstantin