Wednesday, June 23, 2010

Another parent child relationship pitfall (jdo)

Its a rookie's mistake but it stole an hour of my life, so at least I hope this will save someone else's time. I was making an experiment on AppEngine with big collections and I wrote these very simple parent and child classes to help in my test:
@PersistenceCapable
public class ParentWithBidiOwnedChildren {

 @Persistent(mappedBy="parent")
 private Set<ChildWithBidiOwningParent> children;

 public ParentWithBidiOwnedChildren() {
  children = new HashSet<ChildWithBidiOwningParent>();
 }

 @PrimaryKey
 @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
 public Key id;

 public void addNewChild() {
  children.add(new ChildWithBidiOwningParent(this));
 }

 public Set<ChildWithBidiOwningParent> getChildren() {
  return children;
 }
}
And child:
@PersistenceCapable
public class ChildWithBidiOwningParent { 
 
 @PrimaryKey 
 @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
 public Key id;
 
 @Persistent
 private final ParentWithBidiOwnedChildren parent;

 public ChildWithBidiOwningParent(ParentWithBidiOwnedChildren parent) {
  this.parent = parent;  
 }

 public ParentWithBidiOwnedChildren getParent() {
  return parent;
 }
}
In Eclipse IDE when you hit ctrl+1 you can quickly create a member field from a constructor parameter:

Eclipse generates a final field which is recommended and desirable in most cases:

What happens next, when you try to persist a parent, you get an exception:

javax.jdo.JDOUserException: Class "com.codeark.appengine.bigcollections.ParentWithBidiOwnedChildren" has collection field "children" and this has no mapping in the table for the element class "com.codeark.appengine.bigcollections.ChildWithBidiOwningParent" owner field "parent"

Immediately I started looking for an error in my annotations, but the smoking gun was that auto generated final keyword, so here is the correct child code:
@PersistenceCapable
public class ChildWithBidiOwningParent { 
 
 @PrimaryKey 
 @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
 public Key id;
 
 @Persistent
 private ParentWithBidiOwnedChildren parent;

 public ChildWithBidiOwningParent(ParentWithBidiOwnedChildren parent) {
  this.parent = parent;  
 }

 public ParentWithBidiOwnedChildren getParent() {
  return parent;
 }
}
That was a very unpleasent hour for me :-)

Friday, June 11, 2010

Tuesday, June 8, 2010

Lightweight JDO Persistence Filter using Guice

Here is a very lightweight and simple PersistenceFilter for your Guice powered webapps:
@Singleton
public class PersistenceFilter implements Filter {

 private final Provider<PersistenceManager> pmp;

 @Inject
 public PersistenceFilter(Provider<PersistenceManager> pmp) {
  this.pmp = pmp;
 }

 @Override
 public void destroy() {
 }

 @Override
 public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
  PersistenceManager pm = pmp.get();
  try {
   chain.doFilter(request, response);
  } finally {
   pm.close();
  }
 }

 @Override
 public void init(FilterConfig arg0) throws ServletException {
 }
}
This is no replacement for warp-persist and the soon to come guice persistence support, but look how simple it is, I love it! :-)

So how does this work? the "magic" is done by using Guice scoping, basically PersistenceManager is tied to the Request scope and all we have to do is close it at the end of the request. I'm going to show this in the context of an AppEngine application (cuz thats what I'm working on right now), so here is our web.xml:
<?xml version="1.0" encoding="utf-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
 version="2.5">

 <filter>
  <filter-name>guiceFilter</filter-name>
  <filter-class>com.google.inject.servlet.GuiceFilter</filter-class>
 </filter>

 <filter-mapping>
  <filter-name>guiceFilter</filter-name>
  <url-pattern>/*</url-pattern>
 </filter-mapping>

 <listener>
  <listener-class>com.codeark.persistencefilterexample.Bootstrap</listener-class>
 </listener>
</web-app>
Its an ordinary, run of the mill Guice powered webapp web.xml config file (see this post if you're using wicket, and why...)

The Bootstrap listener looks like this:
public final class Bootstrap extends GuiceServletContextListener {

 @Override
 protected Injector getInjector() {
  return buildInjector();
 }

 public Injector buildInjector() {  
  Injector infrastructure = Guice.createInjector(    
    new AppEngineModule(), 
    new PersistenceModule(), 
    new WebModule());

  return infrastructure;
 }
}
AppEngineModule handles the bindings of GAE specific services:
public class AppEngineModule extends AbstractModule {
 
 private static final PersistenceManagerFactory pmf = JDOHelper.getPersistenceManagerFactory("transactions-optional");
  
 public AppEngineModule() {  
 }

 @Override
 protected void configure() {
 }
 
 @Provides
 PersistenceManagerFactory providesPersistenceManagerFactory() {
  return pmf;
 }

 @Provides
 UserService providesUserService() {
  return UserServiceFactory.getUserService();
 }
 
 @Inject
 @Provides
 @SessionScoped
 User providesCurrentUser(UserService userService) {
  return userService.getCurrentUser();
 }
}
Please note the providesPersistenceManagerFactory() which localizes the use of static state to this module only. Additionally, diverging from the main topic of this post, take a look at providesCurrentUser(UserService userService) which simply allows you to Inject the current Google Account User (if one is logged in this session) anywhere in your code, its really handy.

Now comes the PersistenceModule:
public class PersistenceModule extends AbstractModule {
 
 public PersistenceModule() {  
 }

 @Override
 protected void configure() {
  bind(PersistenceManager.class).toProvider(PersistenceManagerProvider.class).in(RequestScoped.class);
  bind(DataService.class).to(DataServiceImpl.class); 
 } 
}
The most important line here is the first one where we bind PersistenceManager to the request scope. The provider follows:
public class PersistenceManagerProvider implements Provider<PersistenceManager> {

 private final PersistenceManagerFactory pmf;

 @Inject
 public PersistenceManagerProvider(PersistenceManagerFactory pmf) {
  this.pmf = pmf;  
 }

 @Override
 public PersistenceManager get() {
  return pmf.getPersistenceManager();
 }
}
I could have used a @Provides method in PersistenceModule instead, but that would force me to inject PersistenceManagerFactory into PersistenceModule and I like to avoid module injection where possible.

Last but not least, WebModule:
public class WebModule extends ServletModule {
 
 @Override
 protected void configureServlets() {
  filter("/*").through(PersistenceFilter.class);  
  serve("/test").with(TestServlet.class);  
 }   
}
It is important that PersistenceFilter will precede any other filters or servlets that need persistence (see Dispatch order in Guice documentation) otherwise you might end up with a closed persistence manager.

Finally, our test servlet which uses persistence via DataService:
@Singleton
public class TestServlet extends HttpServlet {

 private final DataService dataService;
 private final Provider<User> currentUser;

 @Inject
 public TestServlet(DataService dataService, Provider<User> currentUser) {
  this.dataService = dataService;
  this.currentUser = currentUser;
 }

 public void doGet(HttpServletRequest req, HttpServletResponse resp) throws IOException {

  resp.setContentType("text/plain");

  User current = currentUser.get();

  if (current == null) {
   resp.getWriter().println("You are not signed in to your google account, but Hello, world! anyways :-)");
  } else {
   resp.getWriter().println(String.format("Hello, %s", current.getNickname()));
   //records user and ip in datastore
   dataService.persist(new MyEntity(current, req.getRemoteAddr()));
  }
 }
}
The DataService implementation looks like this:
public final class DataServiceImpl implements DataService {
 
 private Provider<PersistenceManager> pmp;
 
 @Inject
 public DataServiceImpl(Provider<PersistenceManager> pmp) { 
  this.pmp = pmp; 
 }
 
 @Override
 public <T> T persist(T instance) {
  return pmp.get().makePersistent(instance);
 }

 @Override
 public void delete(Object instance) {
  pmp.get().deletePersistent(instance);
 } 
}
To summarize:
  1. PersistenceManager is bound to a Request Scope, each request has its own PersistenceManager instance.
  2. The PersistenceFilter is configured at the beginning of the request dispatch chain, its main role is to close the PersistenceManager at the end of each request.
  3. Data Aware classes like DataServiceImpl use PersistenceManager by means of a Guice Provider (direct injection of PersistenceManager will impose a scope restriction on when we can instantiate classes that use it, so I think its best to avoid it)
As explained at the beginning of the post, this implementation is good for prototyping and small projects, for large / complex projects I'd go with a more solid, tested and much more capable framework (like warp-persist and guice-persist when it comes out)

The source is available in the form of an eclipse project here:


You will need Google AppEngine Eclipse plugin to make it work.

Tuesday, June 1, 2010

Writing unit tests for Guice and Wicket

There are excellent frameworks out there for bringing the Guice power into your JUnit tests, like AtUnit or GuiceBerry, however, for the sake of simplicity, this post builds upon a simple Test Runner class described in another post written in 2008 by Gili Tzabari about Guice and JUnit4 integration.

Here is a very simple MyGuiceTestRunner implementation:
public class MyGuiceTestRunner extends GuiceTestRunner {
 public MyGuiceTestRunner(Class<?> classToRun) throws InitializationError {
  super(classToRun, new WebModule(), new MyModule(), new HibernateModule());
 }
}
And here is an abstract wicket test to ease our work later:
@RunWith(MyGuiceTestRunner.class)
public class AbstractWicketTest {
 
 private final WicketTester wicketTester;
 
 protected final WicketTester getWicketTester() {
  return wicketTester;
 }

 public AbstractWicketTest(Injector injector) {
  wicketTester = new WicketTester();
  WebApplication app = wicketTester.getApplication();
  app.addComponentInstantiationListener(new GuiceComponentInjector(app, injector));
 }
}
Some points of intrest in this implementation:
  • Class is annotated with @RunWith, this tells JUnit to use MyGuiceTestRunner to run this test (and subclasses too).
  • In the constructor we create a WicketTester which in turn will create a dummy wicket web application for us (BaseWicketTester.DummyWebApplication is the exact type). If we need a custom application we could simply use other WicketTester constructors that take an Application instance and use it instead of the inner dummy one.
  • Once a WicketTester instance was created, we add attach a GuiceComponentInjector just like we would in a normal guicey wicket web application.
In a typical test subclass of AbstractWicketTest we get a reference to the injector using constructor injection (remember this test is injectable because it is being run by MyGuiceTestRunner):
public class SampleWicketTest extends AbstractWicketTest {
 
 @Inject
 public SampleWicketTest(Injector injector) {
  super(injector);
 }

 @Test
 public void test() {
  WicketTester wicketTester = getWicketTester();
  wicketTester.startPage(TestPage.class);
  wicketTester.assertRenderedPage(TestPage.class);
  wicketTester.assertLabel("meow", "Testing 1 2 3");
 }
}
For the sake of completeness, here is the code for the test page itself (html markup omitted):
public class TestPage extends WebPage { 
 
 @Inject private IService service;
 
 public TestPage() {
  add(new Label("meow", "Testing 1 2 3"));
  service.doSomething();
 } 
}
Thats it, you are now free to write Guice powered tests for your Guicey Wicket pages.

Enjoy :-)