Google Cloud Endpoints - Watch for Missing Annotations

One of the early frustrations I had with Endpoints were run-time exceptions. Turns out, regardless of what the culprit is, the dev server (jetty 6) wouldn't reveal much details of what exactly went wrong. Whatever the problem bet the server fails with java.io.IOException: Failed to retrieve API configs with status: 500. If you are a newbie like I was, there is a good chance your code lacks a mandatory annotation. There is a little trick to it which helps you nail the issue down fairly quickly.

First of all, my general advice is to make running a dev server part of your development routine. Avoid writing extensive APIs upfront. Having a decent test coverage is nothing but a false sense of safety. Most of the errors happen at run-time. Unless you beef up on your integration tests, you better check the dev console every time you add a new method to your API.

Now, back to the problem. I found it's very easy to forget adding @Named to method parameters of a primitive type. To set an example (courtesy to Google's official tutorial):
 package com.example.helloworld;  
 
 import com.google.api.server.spi.config.Api;  
 import com.google.api.server.spi.config.ApiMethod;  
 import com.google.api.server.spi.config.ApiNamespace;  
 import com.google.api.server.spi.config.Named;  

 /** An endpoint class we are exposing */  
 @Api(name = "myApi",  
     version = "v1",  
     namespace = @ApiNamespace(ownerDomain = "helloworld.example.com",  
         ownerName = "helloworld.example.com",  
         packagePath=""))  
 public class MyFirstAPI {  
   /** A simple endpoint method that takes a name and says Hi back */  
   @ApiMethod(name = "sayHi")  
   public MyBean sayHi(@Named("name") String name) {  
     MyBean response = new MyBean();  
     response.setData("Hi, " + name);  
     return response;  
   }  
 }  
The example above works and runs just fine. Suppose you forget to annotate the name parameter of the sayHi() method:
 @ApiMethod(name = "sayHi")  
 public MyBean sayHi(String name) {..}  
At first glance there won't be any difference. Maven build succeeds and the dev server starts without any problems. However, when you try accessing the console you get to know there was an error:
 java.io.IOException: Failed to retrieve API configs with status: 500  
As you can see the message isn't too informative and it can take quite an effort to get to the bottom of the issue. What I found helpful was trying to generate client libraries:
 mvn appengine:endpoints_get_client_lib  
Not only does the build fail fast saving the effort you'd put into restarting and checking the dev server, but most importantly it tells you exactly what the problem is:
 [INFO] com.google.api.server.spi.config.validation.MissingParameterNameException: 
myApi.com.example.helloworld.MyFirstAPI.sayHi parameter 
(type class java.lang.String): Missing parameter name. 
Parameter type (class java.lang.String) is not an entity type 
and thus should be annotated with @Named.  
This practice proved invaluable and helped me reduce time which would otherwise be wasted on chasing basic configuration issues. I recommend running it as a sanity check before you go and push the latest code to the cloud.

This post is part of Google App Engine and Android - Pros and Cons, Challenges