Main menu

How to solve a java.lang.NoClassDefFoundError when using Google Spreadsheet API under Tomcat

I ran into the dreaded java.lang.NoClassDefFoundError when I was deploying a servlet that uses Google's gdata client library for Java to an instance of Tomcat 5.5. Here is the relevant line of the stack trace:

java.lang.NoClassDefFoundError: Could not initialize class 
                com.google.gdata.client.http.GoogleGDataRequest

The Tomcat FAQs pointed me to this post by Craig MacClanahan that discusses the main causes of class not found and class definition not found issues (note the difference!). Here is the part that was relevant for my problem:

"If a class itself cannot be found, you will usually get a
ClassNotFoundException.  You're getting a NoClassDefFoundError
exception instead, which means that your class was found,
but one of the classes *it* depends on (i.e. imports)
can not be found."

In this case, the problem was not that the dependend class wasn't there, the problem was that the dependend class could not be loaded due to the default access restrictions of the Tomcat servlet container. To solve this issue, you have to modify the policy file /etc/tomcat55/catalina.policy. Note: If you are using a Debian-based Linux-distro you should change one of the files in /etc/tomcat55/policy.d/* instead, because this is what the catalina.policy file is created from when starting it via the init.d script. I added the following lines to /etc/tomcat55/policy.d/10admin.policy:

// Permissions for the gdata client
grant {
  // Permission to access the Google servers
  permission java.net.SocketPermission "www.google.com:443", "connect, resolve";
  permission java.net.SocketPermission "spreadsheets.google.com:80", "connect,resolve";
  permission java.net.SocketPermission "docs.google.com:80", "connect,resolve";

  // Persmission to use get/setCoockieHandler
  permission java.net.NetPermission "getCookieHandler", "read";
  permission java.net.NetPermission "setCookieHandler", "write";

  // Permission to access a couple of system properties
  permission java.util.PropertyPermission "http.strictPostRedirect", "read,write";
  permission java.util.PropertyPermission "GoogleGDataRequest.disableVersionHeader", "read";
  permission java.util.PropertyPermission "com.google.gdata.DisableCookieHandler", "read";
};

Now restart Tomcat (i.e. '/etc/init.d/tomcat restart') to let those changes take effect and you're all set.  Please note that I am using the gdata client only for accessing Google Docs and Google Spreadsheets, so it is possible that you will need to add more permissions to your policy file if you are using other classes.

Let me know if this worked for you or if you had to make additional changes.

© 2011 Stefan Ukena.