views:

941

answers:

2

My question is more of a best practices question on how to implement unowned relationships with Google App Engine. I am using JDO to do my persistence and like recommended in the google docs I'm persisting my list of unowned relationships like so:

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class User implements Serializable, UserDetails {
...

    @Persistent
    private List<Key> groups;
...
}

Now I came across my predicament when I went to query that list of objects using they Key object. So when I get my list of group keys in order to actually return a list of Group objects I have to do a look up on that key to get the object. My question is what is the recommended way of doing a unowned look up on a model object?

Should I have an instance of the PersistanceManagerFactory on my Model object so I can do a lookup?

Should I have an instance of my GroupDAO object on my Model object so I can do a look up?

Should I have a Utility to do this type of lookup?

I'm new to this so I just want to know which is the best way to do this. Thanks.

A: 

Google recommends creating a singleton PersistenceManagerFactory. I wouldn't stick a PMF in your model.

Peter Recore
Yeah I stated that incorrectly. I have a singleton for the factory I just didn't know where it was best to actually convert the keys into the actual groups. If I should do it in the owning object or maybe the DAO.
nwallman
+1  A: 

Ideally, the User object would have a method that returns a List<UnownedObject> so that the callers get a clean API. One way to do that is for the User object to have an instance of the DAO so it could ask the DAO to do the query.

In order to do this, the PersistenceManager can't be closed until the end of the request. One way to do this is to create a servlet filter:

public class PersistenceManagerFilter implements Filter { 
  public void init(FilterConfig filterConfig) throws ServletException {
  }

  public void destroy() {
  }

  public void doFilter(ServletRequest request, ServletResponse response,
      FilterChain chain)  throws IOException, ServletException {
    PersistenceManager pm = PMF.get().getPersistenceManager();
    try {
      request.setAttribute("pm", pm);
      chain.doFilter(request, response);
    } finally {
      pm.close();
    }
  }
}

Then you can injected the PersistenceManager into your DAO. If you use Guice you can do:

@RequestScoped
public class UserDao {
  private final PersistenceManager pm;

  @Inject
  UserDao(PersistenceManager pm) {
    this.pm = pm;
  }

  public User getUser(parameters) {
    Key key = createKey(parameters);
    User user = pm.getObjectById(User.class, key);
    user.setUserDao(this);
    return user;
  }
}

This works best when UserDao is in the same package as User so User.setUserDao() can be package scope. You could decide to set the PersistenceManager into the User object instead of the UserDao.

Next you need to create a Guice module to bind PersistenceManager:

public class PersistenceManagerModule extends AbstractModule {
  @Override 
  protected void configure() {
  }

  @Provides @RequestScoped
  PersistenceManager providePersistenceManager(HttpServletRequest request) {
    return (PersistenceManager) request.getAttribute("pm");
  }
}

Finally you need to configure Google App Engine to use Guice.

This is just one possible way to do it. You could be more clever had have providePersistenceManager create the PersistenceManager and store it as a request attribute instead of having the servlet filter create the PersistenceManager (the filter would still close it). You could also have the servlet filter get the Guice Injector so you can avoid using setAttribute() and getAttribute() and instead use a more type-safe API.

NamshubWriter
If you use Guice's ServletModule, this is even easier, because you can have Guice inject the PersistenceManager into PersistenceManagerFilter so you don't have to use request.getAttribute(). In this case, PersistenceManagerModule would just call PMF.get()
NamshubWriter