question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Comparison of Set of Set non-deterministic

See original GitHub issue

I have a data structure which contains a set of set. When comparing with javers I sometimes get a diff, sometimes not. The test data is static so I would expect an identical output.

Steps To Reproduce

When I run this class containing the two identical objects a1 and a2:

import lombok.Builder;
import lombok.Data;
import org.javers.core.Javers;
import org.javers.core.JaversBuilder;

import java.util.Set;

public class MyTest {

    @Data
    @Builder
    public static class A {
        private Set<B> bs;
    }

    @Data
    @Builder
    public static class B {
        private Set<C> cs;
    }

    @Data
    @Builder
    public static class C {
        private String foo;
    }

    public static void main(String[] args) {
        Javers javers = JaversBuilder.javers().build();

        A a1 = A.builder().bs(Set.of(
                        B.builder()
                            .cs(
                                Set.of(
                                    C.builder().foo("a").build(),
                                    C.builder().foo("b").build()
                                        )).build())).build();

        A a2 = A.builder().bs(Set.of(
                B.builder()
                        .cs(
                                Set.of(
                                        C.builder().foo("a").build(),
                                        C.builder().foo("b").build()
                                )).build())).build();


        for (int i = 0; i < 10; i++) {
            var diff = javers.compare(a1, a2);
            if (diff.hasChanges()) {
                System.out.printf("\n===== Diff at round %d ======\n", i);
                System.out.println(diff);
            }
        }
    }
}

… I receive the following output:

20:51:47.647 [main] DEBUG org.javers.core.JaversBuilder - starting up JaVers ...
20:51:47.724 [main] INFO org.javers.core.JaversBuilder - mappingStyle: FIELD
20:51:47.732 [main] INFO org.javers.core.JaversBuilder - loading JodaAddOns ...
20:51:47.786 [main] INFO org.javers.core.JaversBuilder - loading GuavaAddOns ...
20:51:47.841 [main] DEBUG org.javers.TypeMapper - javersType of 'LocalDateTime' mapped explicitly to ValueType
20:51:47.841 [main] DEBUG org.javers.TypeMapper - javersType of 'LocalDate' mapped explicitly to ValueType
20:51:47.842 [main] INFO org.javers.core.JaversBuilder - using fake InMemoryRepository, register actual Repository implementation via JaversBuilder.registerJaversRepository()
20:51:47.870 [main] INFO org.javers.core.JaversBuilder - JaVers instance started in 225 ms
20:51:47.890 [main] DEBUG org.javers.TypeMapper - javersType for 'class MyTest$A' defaulted to ValueObjectType
20:51:47.903 [main] DEBUG org.javers.TypeMapper - javersType for 'java.util.Set<MyTest$B>' spawned as SetType from prototype SetType{ baseType: 'interface java.util.Set' }
20:51:47.905 [main] DEBUG org.javers.TypeMapper - javersType for 'class MyTest$B' defaulted to ValueObjectType
20:51:47.907 [main] DEBUG org.javers.TypeMapper - javersType for 'java.util.Set<MyTest$C>' spawned as SetType from prototype SetType{ baseType: 'interface java.util.Set' }
20:51:47.908 [main] DEBUG org.javers.TypeMapper - javersType for 'class MyTest$C' defaulted to ValueObjectType
20:51:47.909 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.938 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.949 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.951 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3

===== Diff at round 1 ======
Diff:
* changes on MyTest$A/ :
  - 'bs' collection changes :
     . 'MyTest$A/#bs/9f83e3c27e7b610b0a0317a0f008f195' removed
     · 'MyTest$A/#bs/f80bbd079e4ee10592dc0f6f850bacb7' added
  - 'bs/9f83e3c27e7b610b0a0317a0f008f195.cs' collection changes :
     . 'MyTest$A/#bs/{hashPlaceholder}/cs/74a563c16582541b5f7d011fe538602a' removed
     . 'MyTest$A/#bs/{hashPlaceholder}/cs/7f2b9fa7d40fb28ae704fb57f5db54ee' removed
  - 'bs/f80bbd079e4ee10592dc0f6f850bacb7.cs' collection changes :
     · 'MyTest$A/#bs/{hashPlaceholder}/cs/74a563c16582541b5f7d011fe538602a' added
     · 'MyTest$A/#bs/{hashPlaceholder}/cs/7f2b9fa7d40fb28ae704fb57f5db54ee' added

20:51:47.971 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.972 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3

===== Diff at round 2 ======
Diff:
* changes on MyTest$A/ :
  - 'bs' collection changes :
     . 'MyTest$A/#bs/9f83e3c27e7b610b0a0317a0f008f195' removed
     · 'MyTest$A/#bs/f80bbd079e4ee10592dc0f6f850bacb7' added
  - 'bs/9f83e3c27e7b610b0a0317a0f008f195.cs' collection changes :
     . 'MyTest$A/#bs/{hashPlaceholder}/cs/74a563c16582541b5f7d011fe538602a' removed
     . 'MyTest$A/#bs/{hashPlaceholder}/cs/7f2b9fa7d40fb28ae704fb57f5db54ee' removed
  - 'bs/f80bbd079e4ee10592dc0f6f850bacb7.cs' collection changes :
     · 'MyTest$A/#bs/{hashPlaceholder}/cs/74a563c16582541b5f7d011fe538602a' added
     · 'MyTest$A/#bs/{hashPlaceholder}/cs/7f2b9fa7d40fb28ae704fb57f5db54ee' added

20:51:47.978 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.980 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.982 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.983 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.985 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.987 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.989 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.991 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3

===== Diff at round 6 ======
Diff:
* changes on MyTest$A/ :
  - 'bs' collection changes :
     . 'MyTest$A/#bs/9f83e3c27e7b610b0a0317a0f008f195' removed
     · 'MyTest$A/#bs/f80bbd079e4ee10592dc0f6f850bacb7' added
  - 'bs/9f83e3c27e7b610b0a0317a0f008f195.cs' collection changes :
     . 'MyTest$A/#bs/{hashPlaceholder}/cs/74a563c16582541b5f7d011fe538602a' removed
     . 'MyTest$A/#bs/{hashPlaceholder}/cs/7f2b9fa7d40fb28ae704fb57f5db54ee' removed
  - 'bs/f80bbd079e4ee10592dc0f6f850bacb7.cs' collection changes :
     · 'MyTest$A/#bs/{hashPlaceholder}/cs/74a563c16582541b5f7d011fe538602a' added
     · 'MyTest$A/#bs/{hashPlaceholder}/cs/7f2b9fa7d40fb28ae704fb57f5db54ee' added

20:51:47.994 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.996 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.997 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:47.998 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:48.000 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3
20:51:48.001 [main] DEBUG org.javers.core.graph.ObjectGraphBuilder - live graph assembled, object nodes: 4, entities: 0, valueObjects: 3

===== Diff at round 9 ======
Diff:
* changes on MyTest$A/ :
  - 'bs' collection changes :
     . 'MyTest$A/#bs/9f83e3c27e7b610b0a0317a0f008f195' removed
     · 'MyTest$A/#bs/f80bbd079e4ee10592dc0f6f850bacb7' added
  - 'bs/9f83e3c27e7b610b0a0317a0f008f195.cs' collection changes :
     . 'MyTest$A/#bs/{hashPlaceholder}/cs/74a563c16582541b5f7d011fe538602a' removed
     . 'MyTest$A/#bs/{hashPlaceholder}/cs/7f2b9fa7d40fb28ae704fb57f5db54ee' removed
  - 'bs/f80bbd079e4ee10592dc0f6f850bacb7.cs' collection changes :
     · 'MyTest$A/#bs/{hashPlaceholder}/cs/74a563c16582541b5f7d011fe538602a' added
     · 'MyTest$A/#bs/{hashPlaceholder}/cs/7f2b9fa7d40fb28ae704fb57f5db54ee' added


Process finished with exit code 0

Interestingly enough the diff appears (at least on my machine) always on the same rounds. When the inner set (Set of C) only contains one entry, the diff works as expected - there is no difference 😉

What do I miss?

Javers’ Version 6.42

Additional context

  • I am a JaVers newbie
  • I have tried the three different list comparison algorithms without a change of the output above.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:7 (4 by maintainers)

github_iconTop GitHub Comments

1reaction
samba2commented, Nov 3, 2021

Hi, I’ve tried to fumble together a failing test case: https://github.com/javers/javers/pull/1158

Please feel free to improve my copy + paste groovy code 😉

0reactions
bartoszwalacikcommented, Dec 6, 2021

it should, just try the new version 😃

Read more comments on GitHub >

github_iconTop Results From Across the Web

Difference between Deterministic and Non ... - GeeksforGeeks
In a deterministic algorithm, for a given particular input, the computer will always produce the same output going through the same states ...
Read more >
Deterministic and Nondeterministic Functions - SQL Server
Nondeterministic functions may return different results each time they're called with a specific set of input values even if the database state ...
Read more >
Matching two sets when you cannot do within-set comparisons
Suppose you have two lists, A and B , each with length n. The elements of A cannot be compared with other elements...
Read more >
Nondeterministic collations - PostgreSQL Notes
Starting with version 12, the new “deterministic” property can be set to false at CREATE COLLATION time to request that string comparisons ......
Read more >
Is set deterministic? [duplicate] - python - Stack Overflow
Sure, one can sort the outcome to enforce deterministic behavior, but you can get such idea once you observe you have non-deterministic code...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found