Understanding “The RequestFactory ValidationTool must be run” Exception

RequestFactoryInterfaceValidation entry on official GWT wiki (this is also the place where you can learn more on the topic) begins with announcement:

Starting with GWT 2.4, RequestFactory interfaces must be validated before they can be used by the RequestFactory server code or JVM-based clients.

“must” is a key word here, as bypassing mentioned validation ends up in exception like that:

java.lang.RuntimeException: The RequestFactory ValidationTool must be run for the XYZ RequestFactory type
at com.google.web.bindery.requestfactory.vm.impl.Deobfuscator$Builder.load(Deobfuscator.java:59)

This exception costed me a lot of nerves so let’s take a closer look to the topic of RF (RequestFactory) validation to save yours :-)

Why must I perform validation?

We can can pick one of two tools to perform the validation:

(more on both approaches in the mentioned wiki entry)

But why is it now necessary to invoke one of these tools? Didn’t earlier versions of RF work  well without doing it? Invoking validation has two effects:

  1. As we may guess it, contracts between proxies and entities and between RequestContextS and services (learn more in docs) are checked and errors are displayed if something doesn’t match.
  2. RequestFactoryNameDeobfuscatorBuilder class sources are generated

And what is DeobfuscatorBuilder?

For RF client-server communication to work, RF protocol need to pass over the wire information about what method to invoke on which server-side service and what properties should be transfered between EntityProxyS/ValueProxyS and their server-side counterparts (e.g. domain objects). In pre 2.4 RF versions all that class, method and properties names were present in RF request/response payload just as they are. But in that form, they were quite verbose and unnecessarily revealed implementation of application to the outside world.

So it was requested to obfuscate these names. But obviously they need to be deobfuscated by framework at some point so that it can make use of them. And guess what? This is where our DeobfuscatorBuilder comes in and takes care of this deobfuscation stuff. So now we know, why running one of validation tools (which generate deobfuscator, don’t forget) is required, not just recommended.

Knowing all of that, how to fix that dreaded exception?

First of all, the message may be misleading. It may suggest that it has something to do with RF interfaces not being valid and having some mismatches. So you run validation and make sure there are no validation errors reported, but if you are out of luck the exception is thrown again. So what’s going on?

If we take a dive into GWT source code to the line indicated by stack trace we can see similar fragment (I simplified it a bit):

/**
 * Load a pre-computed Builder from the classpath. The builder
 * implementation is expected to have been generated by the annotation
 * processor as part of the build process.
 * (...)
 */
 public static Builder load(Class clazz, ClassLoader resolveClassesWith) {
   try {
     //stuff trying to load DeobfuscatorBuilder from classpath...
   } catch (ClassNotFoundException e) {
     throw new RuntimeException("The RequestFactory ValidationTool must be run for the "
       + clazz.getCanonicalName() + " RequestFactory type");
   }
   //...
 }

(Text search of GWT sources ensured me that this is one and only place from which this exception may be thrown)

So the exception is really trying to tell us something like:

I can’t find DeobfuscatorBuilder on classpath!

So you have to make sure that following three requirements are satisfied in your build process:

  1. You actually runned APT/ValidationTool and have DeobfuscatorBuilder sources generated
  2. In case if you don’t do APT and compilation in single run (e.g. using maven-processor-plugin), generated source file is compiled after it’s generated
  3. Compiled DeobfuscatorBuilder class ends up in the place where it can be found on client-side classpath (path). (It should sit next to of our RequestFactory implementation class file, because code generator will give it the same package)

I had problems because I took care only about 1. (after all, that’s was exception message was asking me to do) but somehow in my build process 2. and/or 3. were not fullfilled.

Side note: when to run validation?

Even though theoretically you don’t need to run validation by each build (if RF-related classes weren’t changed), it’s a safe choice to run it every time (it’s fast).

Reason? Things may go bad if you forget to run validation after RF-related classes were modified. After such change the contracts may no longer be valid. But you won’t be informed about it. And what’s worse, if you already have deobfuscator generated, you won’t even be reminded about invoking validation with “The RequestFactory ValidationTool must be run” exception. But as existing deobfuscator it’s not up-to-date it won’t be able to do its job correct. Both issues may lead to some very strange and hard to diagnose runtime problems. The easiest way to avoid them is just running validation regularly.

PS. Thanks for Thomas Broyer for helping me define what DeobfuscatorBuider is.

4 thoughts on “Understanding “The RequestFactory ValidationTool must be run” Exception

  1. ValidationTool (or the annotation processor; ValidationTool is actually only a wrapper around it) is so fast there’s little to no reason not to run it continuously!

  2. Hello Piotr,
    your post is the most valuable resources I have found so far on the net for “understanding” the problem. Really a good job. Unfortunately, the part regarding “fixing” is not so effective, at least for me. I’m still stuck on that.
    I’m using Eclipse, GWT EntityFactory, Hibernate, Openshift as production runtime environment (so, maven as builder tool). I’m trying to make my GWT module run locally as GWT “Web Application”, which does not trigger maven build, so I need to run the validator manually once every change. I’m trying to update my pom.xml for adding a build profile able to run the validator. Do you have ani hint on that?
    Bye.
    CT

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>