Accessing GWT Hosted Mode from the Internet
The final network-related issue is really a Google-Web-Toolkit issue. First some background: The test application I put together is a Google Web Toolkit (GWT) application, and you test GWT applications by running them as "Web Applications" from the Eclipse debugger. If you've never worked with GWT, this one feature should be enough for you to check it out.
GWT works this magic in two ways. First of all, when you test a GWT application, what you're really running under Eclipse is an instance of the Jetty web server that's been hacked up to know about GWT. Though, I suppose you could set breakpoints inside Jetty itself, you never do that. What you do do, however, is set breakpoints in the servlets that are running inside Jetty the servlets that comprise your application.
So here's the problem: The hacked up version of Jetty, by default, will only recognize HTTP requests that come from the local machine. When testing our OAuth application, however, HTTP requests to the GWT version of Jetty are coming from two places: from the local machine (when we launch the application from a browser), and from the Internet (when Google sends us the Auth token). The local URL that you typically use to test a GWT applictaion looks something like this:
Google, however, can't send the OAuth token to that address, because 127.0.0.1 (which means "the local machine") is not a public Internet address; and even if it could, Jetty wouldn't accept the external HTTP request.
Google wants to send the token to something like
or in my case
(the calendar/AuthTokenRegistrar part of the URL identifies the servlet that receives the token). However, Jetty refuses requests to 126.96.36.199 or timezer.com.
The fix is, fortunately, easy. In Eclipse, go to the Run:Run Configurations dialog. On the left, under Web Applications, select the OAuth application that you're testing. Now, click on the (x)= Arguments and add the argument -bindAddress 0.0.0.0 to the front of the Program Arguments, which holds the command-line arguments for Jetty itself. That 0.0.0.0 address causes Jetty to bind to the IP address of the current machine, whatever it is. You ould also bind ot the actual IP address (188.8.131.52, as aforementioned) if you like, but the 0.0.0.0 form lets you change the IP address of your machine without having to reconfigure Eclipse.
Install the Eclipse GData plugin
Now that the physical world is squared away, we need to think about software. The next step is to install the GData plugin into Eclipse, The plugin isn't essential, but it takes care of some of the busywork of downloading and installing the required jars for a given Google GData API. It also adjusts the Eclipse build-path configuration to accommodate the new jars it installs. That's all the plugin does, however. It doesn't help with the coding.
On the downside, the plugin, frustratingly, doesn't install all the jars you need. For example, if you ask for Calendar APIs, that's all you get. You don't get the additional jars that are required for OAuth.
Google doesn't document the dependencies between jars very well, so using the plugin can help resolve some of the non-obvious dependencies when you install an API jar, so it's worth going through the trouble of installing it.
The plugin works by adding an "Add Google API's" menu to the Google-plugin widget on the toolbar (see Figure 3).
You don't create an explicit GData project, you just add support to an existing project. If you've already installed the GWT plugin, then the widget is already there and installing the plugin just adds the menu item; otherwise, the widget is added.
The plugin also sets up the javadoc locations for the main high-level API (e.g., Calendar), but unfortunately, not for the packages that the high-level API uses (e.g., the Jsr305 Annotations jar or the Google Collections APIs).
Find the plugin at http://code.google.com/p/gdata-java-client-eclipse-plugin/. There's a link to a pretty good tutorial on that page, and there's also a useful YouTube video at http://www.youtube.com/watch?v=dz9Ny22M4V4. Both of these are a bit out of date, but you can follow along without much difficulty. If you've done this sort of thing before, installation is pretty easy: Just bring up Eclipse's Help->Install New Software menu and enter the following URL (which is annoyingly omitted from the video) as the update site to work with:
The plugin supports the following GData APIs, but using the others is a simple matter of putting an appropriate jar or jars on your CLASSPATH:
- Apps Provisioning
- Code Search
- Documents List
- Picasa Web Albums
Adding OAuth-Support jars
As I mentioned earlier, the Google GData plugin installs only those jars that you need for the specified API. It doesn't install all of the jars that you need to do OAuth. Google provides instructions for manual installation here. (You should read this file if you're deploying to the app engine. I'm not demonstrating app-engine-related configuration stuff in this article.)
To install the OAuth jars manually, go to the home directory for the java-client-wrapper project. From there, click on the "downloads" tab, and then download the jdata-src.java.1.45.0.zip file (or whatever version number is current).
Unpack the archive to create a directory called gdata. In that directory, the subdirectory .../gdata/java/lib contains compiled .jar files for all the various GData APIs. For OAuth, you need the following jars:
In addition, you'll also need the google-collect-1.0-rc1.jar, which is in the .../gdata/java/deps subdirectory in the zip file. You can find the javadoc for all the GData wrapper classes in the .../gdata/doc directory.
Once you have the jars in the right place, you need to add them to the Eclipse build path (Select "Project:Properties:Java Build Path," then pick the "Libraries" tab and click on the "Add External JARs" button. Navigate to the directory where you just copied the jar files and click "Open"). I typically change the name of the jar when I copy it into the lib directory to make it easier to update the jars later on. For example, I might copy gdata-client-1.0.jar into myproject/war/WEB-INF/lib/gdata-client.jar (without the version number in the name). That way, when the jar is updated to some other version, I can just copy the new version (with my nonstandard name) right on top of the old one in my .../lib directory, and I don't have to mess with the build path (because the file name hasn't changed).
For what it's worth, I've found that it's a lot easier to manually edit the Eclipse .classpath file at the root of your project directory than it is to use the GUI process I just described. Just shut down Eclipse, modify the file in an ASCII editor, then bring Eclipse back up.
Here are standard <classpathentry> elements for the required Google jars change the paths as necessary:
<classpath> ... <classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/gdata-client-meta.jar"/> <classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/gdata-client.jar"/> <classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/gdata-core.jar"/> <classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/gdata-docs-meta.jar"/> <classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/gdata-docs.jar"/> <classpathentry kind="lib" path="/Users/allen/projects/myProject/war/WEB-INF/lib/google-collect.jar"/> ... </classpath>
Make A Key Pair and Self-Signed Certificate
The next step is to make a certificate and private key that you can use to authenticate your OAuth request. I discussed this issue in last month's article in a nutshell, you create an RSA private key and a public-key certificate using openssl. The following command does the trick:
openssl req -x509 -nodes -days 365 -newkey rsa:1024 -sha1 \ -subj /C=US/ST=CA/L=Berkeley/CN=www.<em>myDomain</em>.com \ -keyout <em>myDomain</em>-rsakey.pem -out <em>myDomain</em>-cert.pem
You'll need to change myDomain to your actual domain name, and also change the -subj argument to correctly state your actual country, state, city, and domain name. This certificate is good for a year (-days 365), so you'll have to create a new one a year from now. Omit this argument if you don't want the certificate to expire.
Once you've created the cert (myDomain-cert.pem) you need to register it with Google. This step is actually optional, but you'll want to do it before you deploy to the real world in order to get rid of the scary looking warning that shows up on the User's grant-access request page. The long-form instructions are here, but the short form is that you go to your Manage Domains page (there's a link in the long-form instructions), where you'll see a screen like the one shown in Figure 4.
The "Target URL" should be a proper prefix of the URL that you'll be giving to Google. I just use the main domain name, but you could specify something like "http://www.myDomain.com/oauth" if you want to limit access to specific servlets. Once the registration is complete, Google will give you a screen like the one shown in Figure 5. You should note the Consumer Key and the Consumer Secret you'll need the key momentarily. Also note that you can change the certificate at any point (to register a new one after the current one expires, for example) from this page.
If you want to see what the permission-granting page will look like, you can click the "Test your AuthSub registration here" link at the bottom of the page. That link will get you through the Google login page (if you're not already logged in, to a page that looks like the one shown in Figure 6.) You can test that the authorization works by logging on to Google, clicking on "My Account," then choosing Authorizing applications & sites from the Security section.