How to Solve Circular Reference

How to solve circular reference?

In most cases when I've had to have two things reference each other, I've created an interface to remove the circular reference. For example:

BEFORE

public class Foo
{
Bar myBar;
}

public class Bar
{
Foo myFoo;
}

Dependency graph:

Foo     Bar
^ ^
| |
Bar Foo

Foo depends on Bar, but Bar also depends on Foo. If they are in separate assemblies, you will have problems building, particularly if you do a clean rebuild.

AFTER

public interface IBar
{
}

public class Foo
{
IBar myBar;
}

public class Bar : IBar
{
Foo myFoo;
}

Dependency graph:

Foo, IBar     IBar
^ ^
| |
Bar Foo

Both Foo and Bar depend on IBar. There is no circular dependency, and if IBar is placed in its own assembly, Foo and Bar being in separate assemblies will no longer be an issue.

How to resolve circular struct dependencies in C

The way to do this is to pre-define the structs using empty definition

typedef struct _A A;
typedef struct _B B;

typedef struct _A {
B *b;
} A;

typedef struct _B {
A a;
} B;

You can put the pre-definitions in a global include file to include from wherever you need.

`

How to solve circular reference in JPA associations?

Circular dependencies aren't a problem in themselves with JPA.

There are two potential problems with them:

From a software design perspective circular dependencies create a cluster of classes that you can't easily break up.
You can easily get rid of them in your case by making the relationship a unidirectional one and replace the other direction by a query, if you really have to.
Is it worth it in your case?
It depends how closely your two entities are really related.
I'd try to avoid bidirectional relationships, because it is easy to make mistakes, like not keeping both sides of the relationship in sync.
But in most cases I wouldn't sweat it.
Most software as way more serious design issues.

The other problem occurs when something tries to navigate this loop until its end, which obviously doesn't work. The typical scenarios are:

  • rendering it into JSON (or XML). This is what @JsonIgnore & Co takes care of by not including properties in the JSON.
  • equals, hashCode, toString are often implemented to call the respective methods of all referenced objects.
    Just as the JSON rendering this will lead to stack overflows.
    So make sure to break the cycle in these methods as well.

JPA itself doesn't have a problem with cycles because it will look up entities in the first level cache.
Assuming you load an Authority and everything is eagerly loaded, JPA will put it in the first level cache, before checking the referenced user id. If it is present in the cache it will use that instance.
If not it will load it from the database, put it in the cache and then check for the authorities ids in the cache. It will use the ones found and load the rest.
For those it will again check the user id, but those are the user we just loaded, so it is certainly in the cache.
Therefore JPA is done and won't get lost in a cycle.
It will just skip the annotated

R solving circular reference

Perhaps something like this?

dat <- data.frame(
indicator = rep(c(1,0,0), times = 4),
interest = c(0,54,33,678,987,544,321,345,678,907,567,0)
)

intersolve <- function(indicator, interest){
indicators = rev(cumsum(rev(indicator) == 1))
sums = rev(tapply(interest, indicators, sum))
interest_payment = rep(sums[-1], each = 3) * indicator
return(interest_payment)
}

dat$interest_payment = intersolve(indicator = dat$indicator, interest = dat$interest)
dat

# indicator interest interest_payment
# 1 1 0 765
# 2 0 54 0
# 3 0 33 0
# 4 1 678 1852
# 5 0 987 0
# 6 0 544 0
# 7 1 321 1930
# 8 0 345 0
# 9 0 678 0
# 10 1 907 567
# 11 0 567 0
# 12 0 0 0

Edit

The following function automatically detects the pattern of 1's.

intersolve2 <- function(indicator, interest){
n = length(interest)
indicators = rev(cumsum(rev(indicator) == 1))
sums = rev(tapply(interest, indicators, sum))
lens = rev(table(indicators))[-1]
lens[length(lens)] = lens[length(lens)] + 1
interest_payment = rep(sums[-1], times = lens) * indicator
if (indicator[n] == 1){interest_payment[n]=interest[n]}
return(interest_payment)
}

Value-equals and circular references: how to resolve infinite recursion?

For the general case that I am interested in

-- where we have classes C1, ..., Cn where each of these classes can have any number of VALUES (like int, string, ...) as well as any number of REFERENCES to any other classes of C1, ..., Cn (e.g. by having for each type Ci a field ICollection<Ci>) --

the question "Are two objects A and B equal?", in the sense of equality that I described here,

seems to be EQUIVALENT to

the question "For two finite, directed, connected, colored graphs G and H, does there exist an isomorphism from G to H?".

Here is the equivalence:

  • graph vertices correspond to objects (class instances)
  • graph edges correspond to references to objects
  • color corresponds to the conglomerate of values and the type itself (i.e. colors of two vertices are the same if their corresponding objects have the same type and the same values)

That's an NP-hard question, so I think I'm going to discard my plan to implement this and go with a circular-reference-free approach instead.

How to Resolve Circular Reference in Header File

You can move the definition of thiswontcompile to the end of the header file, you just need to make the function inline.

#include <vector>
class Box;
class Item {
int row;
int column;
Box *box;
public:
Item(Box *b) : box(b) {}
void thiswontcompile();
void foo();
};
class Box {
std::vector<Item*> items;
public:
Box() {}
void addsquare(Item *sq) { items.push_back(sq); }
void bar() { for (int i=0; i<items.size(); i++) items[i]->foo(); }
void dosomething();
};

inline void Item::thiswontcompile() { box->dosomething(); }

Solving circular reference

@Transient
private B messageOwner;

This does for the JSON serialization what the transient type modifier does for the normal serialization. If the JSON library supports it.

Of course the messageOwner will be null after deserialisation.

How to solve circular reference when serializing an object which have a class member with the same type of that object

I think using ExclusionStrategy is not the right approach to solve this problem.

I would rather suggest to use JsonSerializer and JsonDeserializer
customized for your StructId class.

(May be an approach using TypeAdapter would be even better,
but I didn't have enough Gson experience do get this working.)

So you would create your Gson instance by:

Gson gson = new GsonBuilder()
.registerTypeAdapter(StructId.class, new StructIdSerializer())
.registerTypeAdapter(StructId.class, new StructIdDeserializer())
.setPrettyPrinting()
.create();

The StructIdSerializer class below is responsible for converting a StructId to JSON.
It converts its properties Name, Type and ChildId to JSON.
Note that it does not convert the property ParentId to JSON,
because doing that would produce infinite recursion.

public class StructIdSerializer implements JsonSerializer<StructId> {

@Override
public JsonElement serialize(StructId src, Type typeOfSrc, JsonSerializationContext context) {
JsonObject jsonObject = new JsonObject();
jsonObject.addProperty("Name", src.Name);
jsonObject.add("Type", context.serialize(src.Type));
jsonObject.add("ChildId", context.serialize(src.ChildId)); // recursion!
return jsonObject;
}
}

The StructIdDeserializer class below is responsible for converting JSON to a StructId.
It converts the JSON properties Name, Type and ChildId
to corresponding Java fields in StructId.
Note that the ParentId Java field is reconstructed from the JSON nesting structure,
because it is not directly contained as a JSON property.

public class StructIdDeserializer implements JsonDeserializer<StructId> {

@Override
public StructId deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
StructId id = new StructId();
id.Name = json.getAsJsonObject().get("Name").getAsString();
id.Type = context.deserialize(json.getAsJsonObject().get("Type"), StructType.class);
JsonElement childJson = json.getAsJsonObject().get("ChildId");
if (childJson != null) {
id.ChildId = context.deserialize(childJson, StructId.class); // recursion!
id.ChildId.ParentId = id;
}
return id;
}
}

I tested the code above with this JSON input example

{
"Name": "John",
"Type": "A",
"ChildId": {
"Name": "Jane",
"Type": "B",
"ChildId": {
"Name": "Joe",
"Type": "A"
}
}
}

by deserializing it with

StructId root = gson.fromJson(new FileReader("example.json"), StructId.class);,

then by serializing that with

System.out.println(gson.toJson(root));
and got the original JSON again.

Excel Circular Reference error without circular reference

I'm not sure if I should delete this question, or if this is a valid answer. I guess I would like to have heard of this as a possible solution.

So I copied the formula in the question as text; deleted it (which removed the error if I close and open the sheet), I then pasted the same formula back into the sheet, close the sheet, re-open the sheet, and now, no more circular reference error. I wish I could say I understand why this would work - I was just desperately trying anything and it seemed the only option left.



Related Topics



Leave a reply



Submit