0

I wrote some generic bean conversion that used together to convert a complex bean. Sometimes the input bean has bi-directional reference, and the converter traps in an infinite loop. How can I manage that?

For example the input is A bean that has relation to B bean and B bean has relation to exactly the A instance. When converting the A object starts, the B converter invokes to convert the b field in A, and also on converting the B object, A converter invokes to convert the a field in the B class, and as you know, the converter traps on infinite loop. Think about a more complex relation between beans that the relation graph has more than two nodes.

How can I avoid this infinite recursion in the converters?

slartidan
  • 20,403
  • 15
  • 83
  • 131
Pooya
  • 4,385
  • 6
  • 45
  • 73
  • 2
    Use an `IdentityHashMap` to keep a reference to the objects already transformed, and check in the `IdentityHashMap` before transforming a new object if it's not already in it. – Florent Bayle Jan 12 '15 at 14:26
  • 1
    @fardjad `IdentityHashMap` doesn't use `hashCode()` and `equals()`. – Florent Bayle Jan 12 '15 at 14:30

1 Answers1

1

Object references form a net.

A -------> B
^--- C <---'

When serializing to XML, JSON or similar, you are building a tree. Since a tree is a simpler form of a net you can not simply copy one into the other.

A
'--> B
     '--> C
          '--> A (recursion alarm!)
               '--> ...

A common solution is to

  • either stop serializing, as soon as recursion is detected (just keep track of all objects that are already serialized)

    A
    '--> B
         '--> C
    
  • or, when detecting recursion, add a stub reference to another node in the serialized tree. A unique identifier of nodes is required.

    A(1)
    '--> B(2)
         '--> C(3)
              '--> Stub that links to (1)
    

For the technical detail of storing the already serialized objects:

  • using a HashSet might seem handy as it does not contain duplicates - but since it requires hashCode and equals methods for all items this is generally not a good idea
  • using the keys in IdentityHashMap can be used, it will compare keys using == and not contain duplicates
  • but since you usually check if the collection already contains the item before to add it, you can also use ArrayList with this code: collection.stream().anyMatch(x -> x == key)
Community
  • 1
  • 1
slartidan
  • 20,403
  • 15
  • 83
  • 131