Skip to content

Some considerations on Beans... #396

@gamerover98

Description

@gamerover98

Foreword

These days, I spend a lot of time testing the behavior of the BeanProperty.
As I read in the wiki:

ConfigMe will never return a bean in which a field is null. If it does not succeed to set a field's value, the mapping is considered to have failed and the default object is used. It is therefore important to initialize fields as shown with the country name above if you don't want the absence of one field to make ConfigMe ignore all fields and use the default bean object provided on initialization.

And

As with all other properties, bean properties never resolve to null, i.e. when you do settingsManager.getProperty(property) it is guaranteed to never return null.

But I think I broke these rules in a simple way, let me explain:
I have two bean classes called A and B, where B is used twice in A like the following code:

@Getter @Setter // lombok
public class A {
    private B b1;
    private B b2;
}
...
@Getter @Setter // lombok
public class B {
    private boolean enabled;
    private String value;
}

I have defined a SettingsHolder class that has only one property:

public class ConfigHolder implements SettingsHolder {
    private static final A DEF_VALUE;

    static {
        B b1 = new B();
        b1.setEnabled(true);
        b1.setValue("");

        B b2 = new B();
        b2.setEnabled(true);
        b2.setValue("");

        DEF_VALUE = new A();
        DEF_VALUE.setB1(b1);
        DEF_VALUE.setB2(b2);
    }

    public static final BeanProperty<A> TEST_PROP =
            newBeanProperty(A.class, "a", DEF_VALUE);
}

As you can see, the DEF_VALUE has no null references.

The tests

So, I have created the following unit test to put under pressure the BeanProperty.

@Test
void test() {
    // first file load
    File yamlFile = new File(tempDir.toFile(), "test.yml");
    SettingsManager settingsManager =
            SettingsManagerBuilder
                    .withYamlFile(yamlFile)
                    .configurationData(ConfigHolder.class)
                    .useDefaultMigrationService()
                    .create();

    B b1 = new B();
    b1.setEnabled(true);
    b1.setValue("test1");

    // I don't set B2, so the Bean will be serialized without B2.
    A a = new A();
    a.setB1(b1);

    // At this time, ConfigMe should not save the Bean that has
    // a null reference, but ok it is serialized without that null field.
    settingsManager.setProperty(ConfigHolder.TEST_PROP, a);
    settingsManager.save();

    // Read A from the current settings manager
    a = settingsManager.getProperty(ConfigHolder.TEST_PROP);

    Assertions.assertNotNull(a); // Ok
    Assertions.assertNotNull(a.getB1()); // Ok
    Assertions.assertEquals("test1", a.getB1().getValue()); // Ok
    Assertions.assertNull(a.getB2()); // Ok as I expected.

    // Now try to reload the configuration by recreating the new settings manager instance.
    settingsManager =
            SettingsManagerBuilder
                    .withYamlFile(yamlFile)
                    .configurationData(ConfigHolder.class)
                    .useDefaultMigrationService()
                    .create();

    // Read again A but this time from the new settings manager instance.
    a = settingsManager.getProperty(ConfigHolder.TEST_PROP);

    // What is expected: The reader won't recognize 
    // the Bean (A), and it will set the default value.
    Assertions.assertNotNull(a); // Ok
    Assertions.assertNotNull(a.getB1()); // Ok
    Assertions.assertEquals("", a.getB1().getValue()); // Ok
    Assertions.assertNotNull(a.getB2()); // Ok
    Assertions.assertEquals("", a.getB2().getValue()); // Ok
} 

Considerations

So, did I lose all the data just because of a missing field? Is that correct?
Imagine a user who misses a simple detail while setting up the bean. Will he lose all the data due to that mistake? Perhaps this should be revisited.

Thanks a lot ljacqu 💯

Metadata

Metadata

Assignees

No one assigned

    Labels

    beanmapperIssues that relate to the bean mapper

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions