I'm doing a library that populates a random model with random values, to be used in tests, but it happens that when I have a relation like below, I get a StackOverflowException
Author
@Entity
public class Author implements Serializable {
private static final long serialVersionUID = 1L;
@Id
private Long id;
private String name;
@OneToMany
private List<Book> books = new ArrayList<Book>();
and Book
@Entity
public class Book implements Serializable {
@ManyToOne
private Author author;
The code that reads the fields is like this
public <T> T fakeIt(Class<T> clazz) throws FakerException {
if(clazz.getAnnotation(Entity.class) == null){
throw new FakerException("The class "+ clazz.getName()+ "is not an entity");
}
try {
T faked = clazz.newInstance();
for(Field f : clazz.getDeclaredFields()){
if(f.getName().equals("serialVersionUID"))
continue;
System.out.println("Genearting value for "+f.getName() + " on " + f.getDeclaringClass());
f.setAccessible(true);
f.set(faked, getValueForField(f));
}
return faked;
} catch(Exception e){
throw new FakerException(e);
}
}
private Object getValueForField(Field f) throws Exception {
if(f.isAnnotationPresent(UseGenerator.class)){
Generator<?> gen = (Generator<?>) f.getAnnotation(UseGenerator.class).generator().newInstance();
return gen.genearte();
} else if(f.isAnnotationPresent(ManyToOne.class)){
return fakeIt(f.getType());
} else if(f.isAnnotationPresent(OneToMany.class)){
Class<?> toFake = extractTypeFromList(f);
List<Object> fakedObjects = new ArrayList<Object>();
for(int i = 0; i < 6; i++){
fakedObjects.add(fakeIt(toFake));
}
return fakedObjects;
}
// Other types
String clazzType = f.getType().getSimpleName();
Generator<?> generator = defaultGenerators.get(clazzType.toLowerCase());
if(generator != null)
return generator.genearte();
return null;
}
private Class<?> extractTypeFromList(Field f) {
ParameterizedType parameterizedType = (ParameterizedType) f.getGenericType();
Class<?> type = (Class<?>) parameterizedType.getActualTypeArguments()[0];
return type;
}
In this case, fakeIt
is the function that generates the random values. In this case, it drops in the books
field and when it calls the fakeIt
again, it will try to create a new Author
that will fall in the books
field, and so on.
What is the best way to avoid this?