mardi 28 juillet 2015

avoid stackoverflow exceptions when populating relations

I'm building a library that populates an entity with random values to be used on tests, but when I try populate an relation like the following, I see 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;

this is the code that populates the relations

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 generate random values based on the Field type of the class. at that point, when I'm populating author, it tries to populate the books which has a relation to author that has books that...you got it.. stackoverflow exception. what is the best way to avoid this?





Aucun commentaire:

Enregistrer un commentaire