2

I'm using Javers to compare two object having a String attribute. Since in my application an empty String and a null value in that attribute must be treated equal, I wrote a CustomValueComparator and registered it for the java.lang.String class.

But that comparator is not used, when the attribute is null in the old (or left) version. I wrote a JUnit test to show the issue, see below.

Of course, I could run through my old object and set the null attribute to empty string before comparing it, but probably you guys know a better solution. Neither can I change or override the equals method of MyClass.

Java 1.8.0_144; Javers 3.9.0

@Test
public void test() {
    MyClass old = MyClass.getBuilder()
            .anAttribute(null)
            .build();
    MyClass current = MyClass.getBuilder()
            .anAttribute("")
            .build();

    Javers javers = JaversBuilder.javers()
            .registerValueObject(ValueObjectDefinitionBuilder.valueObjectDefinition(MyClass.class)
                    .withIncludedProperties(Arrays.asList("anAttribute"))
                    .build())
            .registerValue(String.class, new StringValueComparator())
            .build();
    Diff diff = javers.compare(old, current);
    System.out.println(diff.prettyPrint());

    Assert.assertFalse(diff.hasChanges());
}

class MyClass {

    private String anAttribute;

    public static Builder getBuilder() {
        return new Builder();
    }

    static class Builder {

        MyClass resp = new MyClass();

        Builder anAttribute(String arg) {
            resp.anAttribute = arg;
            return this;
        }

        public MyClass build() {
            return resp;
        }

    }

}

class StringValueComparator implements CustomValueComparator<String> {

    @Override
    public boolean equals(String left, String right) {
        String defaultLeft = StringUtils.defaultString(left);
        String defaultRight = StringUtils.defaultString(right);

        return defaultLeft.equals(defaultRight);
    }

}

The output in the console is:

Diff:
* changes on com.test.TestJavers$MyClass/ :
  - 'anAttribute' changed from '' to ''
Moe
  • 23
  • 5

1 Answers1

0

There is a bug in JversBuilder. If you are registering an ValueObject using ValueObjectDefinition, it's registered with the default comparator. You can create a issue for that - https://github.com/javers/javers/issues

As a workaround, this or annotation-based mapping (@ValueObject) will work:

    Javers javers = JaversBuilder.javers()
            //.registerValueObject(ValueObjectDefinitionBuilder.valueObjectDefinition(MyClass.class)
            //.withIncludedProperties(Arrays.asList("anAttribute"))
            //.build())
            .registerValue(String.class, new StringValueComparator())
            .build()

You can create an issue for that

Bartek Walacik
  • 3,386
  • 1
  • 9
  • 14