Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Objectify - how to @Load a List<Ref<?>>?

I have an entity, with a field containing a list to Refs to other entities (always 4). I'm trying to get some entities, and dispatch them for a jsp for display. I want all the Refs in the field to be loaded as well, and to access them in the jsp.

Here is my basic structure:

@Entity
public class Question {
    @Id Long id;
    @Index String question;
    @Load List<Ref<Answer>> answers = new ArrayList<Ref<Answer>>();
}

When I'm fetching question like this, obviously there's an error in the jsp. Makes sense, because answers field is not a list of answers, but of refs:

ObjectifyService.register(Question.class);
ObjectifyService.register(Answer.class);

List<Question> questions = ofy().load().type(Question.class).limit(50).list();

req.setAttribute("questions", questions);
try { 
    getServletContext().getRequestDispatcher("/admin/view-questions.jsp").forward(req, resp); 
} catch (ServletException e) {
    System.out.println (e.getMessage());
}

So how do access the answers in the jsp? is the only way to manually loop through the questions and do a get() for the answers field?

like image 340
Moshe Shaham Avatar asked Nov 11 '12 19:11

Moshe Shaham


1 Answers

You might find this handy:

public class Deref {
    public static class Func<T> implements Function<Ref<T>, T> {
        public static Func<Object> INSTANCE = new Func<Object>();

        @Override
        public T apply(Ref<T> ref) {
            return deref(ref);
        }
    }

    public static <T> T deref(Ref<T> ref) {
        return ref == null ? null : ref.get();
    }

    @SuppressWarnings({ "unchecked", "rawtypes" })
    public static <T> List<T> deref(List<Ref<T>> reflist) {
        return Lists.transform(reflist, (Func)Func.INSTANCE);
    }
}

Using this, you can provide a method like:

@Entity
public class Question {
    @Id Long id;
    @Index String question;
    @Load List<Ref<Answer>> answers = new ArrayList<Ref<Answer>>();
    public List<Answer> getAnswers() { return Deref.deref(answers); }
}

One caveat is that it's a readonly list. With a little creativity you can create a writeable list, but it requires creating a ReversibleFunction and a new List.transform() method. If you just want something simple for JSPs, you might not want to worry about it.

Alternatively, you can use the 'value' property of a Ref in most expression languages.

like image 188
stickfigure Avatar answered Sep 18 '22 23:09

stickfigure