-3

I have two classes which has bidirectional relationship and having recursive object structure issue due to the way it is being set.

Employer employer = new Employer(); 
employer.setName("sample1");

Employee empl = new Employee();

List<Employer> listOfEmployers = new ArrayList<Employer>();
listOfEmployers.add(employer); //i am assuming this part of code is causing recursion issue

 empl.setEmployers(listOfEmployers);
 employer.setEmployee(empl); //will have recursive object structure

It causes issue while conversion of java object to JSON (org.codehaus.jackson.map.JsonMappingException: Infinite recursion). Because of this, jackson is not able to process the java object into JSON.

However,Can you please help me understand how exactly its happening behind the scenes in Java to fix the root-cause?

And what is the right object model to form this kind of mapping between Employer and Employee without getting this recursion issue in java layer?

RVR
  • 97
  • 2
  • 13
  • What is the use of the structure? Are you trying to associate an order with a LineItem? Or are you trying to associate two Orders with each other? – Joey Pinto Jul 10 '17 at 08:16
  • Your `orderCopied` isn't a copy. It's just a new object. – slim Jul 10 '17 at 08:16
  • @slim : yes, I agree. I meant that the values set to "Order" object was copied to new "orderCopied". But my question was regarding how the recursive structure got created behind the scenes in JAVA. What was wrong about the initial approach? – RVR Jul 10 '17 at 08:27
  • "must include the desired behavior, a specific problem or error and the shortest code necessary to reproduce it in the question itself" -- "causes issue" isn't enough. Show us the error. – slim Jul 10 '17 at 08:28
  • It doesn't make sense anyway. An order can have more than one line item, but a line item can't be on more than one order. You've got it wrong already. Rethink. – user207421 Jul 10 '17 at 08:34
  • @EJP Hi..thanks for taking time-out. I am just trying to understand the technical issue in JAVA behind the object association which is created to explain the issue. Not really bothered if lineItem can/cannot be on more than one order. Guess we do not have to look into that aspect. – RVR Jul 10 '17 at 08:44
  • @slim Hi Slim.. I have modifed the question a bit. You can re-create the issue by just copying the first set of code into a main class and debug the line of code with comments mentioned in the question. Do you want me to copy the entity class of "Order" and "LineItem" created as well? I just wanted to keep the question readable. – RVR Jul 10 '17 at 08:47
  • At least you now tell us the error message. But you don't give enough code to recreate the error - there is no code in there that asks to encode to JSON. https://stackoverflow.com/help/mcve - you should put together the smallest code you can that actually shows the problem. – slim Jul 10 '17 at 08:50
  • @JoeyPinto I have modified the question. I just want to understand the root cause behind the recursion being created with my first approach – RVR Jul 10 '17 at 09:27
  • I suggest you get your object model *right,* rather than worrying about why the wrong object model is wrong. – user207421 Jul 10 '17 at 10:35
  • @EJP that's where i need help..to get the right object model which will not create cyclic dependency and recursive formation. Pls let me know if there is a better approach to achieve proper association between Employer and Employee? What i need is -> "Employee associated with an Employer" and "list of employers associated with an employee"? – RVR Jul 10 '17 at 12:30
  • I've *given* you that help. – user207421 Jul 10 '17 at 18:33

1 Answers1

3

If you have two objects, a and b, both of which have a v member that points at the other:

A a = new A();
B b = new B();
a.name = "a";
a.v = b;
b.name = "b"
b.v = a;

Well, how are you going to represent this as JSON? Or as any other serial data format?:

{
   "name": "a",
   "v": {
       "name": "b",
       "v": {
          "name": "a",
          "v": {
             "name": "b",
             "v": {
                "name": "a",
                "v": {
                   "name": "b",
                   "v": {
                      "name": "a",
                      "v": {
                         "name": "b",
                         "v": {

... forever

JSON has no standard way of dealing with this. You can solve it by making the references indirect, via an explicit key:

{
    "key1": {
          "name": "a",
          "v_key" : "key2"
    },
    "key2": {
          "name": "b",
          "v_key": "key1"
    }
}

In Java this could be achieved with something like:

Map<String,Object> map = new HashMap<String,Object>();
A a = new A();
a.name = "a";
map.add("a", a);

B b = new B();
b.name = "b";
map.add("b", b);

a.v_key = "b";
b.v_key = "a";

You haven't told us what JSON library you are using. It may have approaches to automatically handle cyclic dependencies with an approach similar to the above. Search for the word "cyclic" in its documentation.

(For Jackson, see: Infinite Recursion with Jackson JSON and Hibernate JPA issue )

slim
  • 36,139
  • 10
  • 83
  • 117
  • There's nothing wrong with it, except that it creates a cycle. It doesn't create that cycle on its own, but in conjunction with the other lines, so it's no more "the root cause" than those other lines. – slim Jul 10 '17 at 12:16
  • is there a better way to create right object model form between Employer and Employee in java layer to avoid such recursive formation? – RVR Jul 10 '17 at 12:23
  • "Employee associated with an Employer" and "list of employers associated with an employee" – RVR Jul 10 '17 at 12:32
  • You could omit the link in one direction when serializing (perhaps with `@JsonIgnore`) and add those links back programatically when you deserialize. – slim Jul 10 '17 at 13:03
  • You are right. `@JsonIgnore` helps to resolve the json error. But the expectation is to fix the object association at the java layer itself without having a recursive formation. So was thinking for a solution in object association level. – RVR Jul 10 '17 at 13:09
  • Either you need the bi-directional references or you don't. If you don't need them, get rid of them. If you do need them, **then the Java model is not broken**. But you can't store them in JSON directly. So use one of the several approaches that have been described here. – slim Jul 10 '17 at 13:15
  • I realize this is the right answer, the graphic relationship is infinite looping, So, I just record the node.id, that solve my problem, thanks. – meadlai Aug 10 '17 at 08:26