= Google Service example

This example shows how one would implement an API like Google
Search that uses lots of structured types.

There are examples for "Direct" and "Delegated" dispatching
modes.

There is also an example for API definition file autoloading.


= Running the examples

  1. Add the files to an Action Web Service enabled Rails project.

    "Direct" example:

      * Copy direct/search_controller.rb to "app/controllers"
        in a Rails project.
      * Copy direct/google_search_api.rb to "app/apis"
        in a Rails project

    "Delegated" example:

      * Copy delegated/search_controller.rb to "app/controllers"
        in a Rails project.
      * Copy delegated/google_search_service.rb to "lib"
        in a Rails project.

     "Autoloading" example:

      * Copy autoloading/google_search_api.rb to "app/apis" (create the directory
        if it doesn't exist) in a Rails project.

      * Copy autoloading/google_search_controller.rb "app/controllers"
        in a Rails project.
  

  2. Go to the WSDL url in a browser, and check that it looks correct.

      "Direct" and "Delegated" examples:
        http://url_to_project/search/wsdl

      "Autoloading" example:
        http://url_to_project/google_search/wsdl
     
     You can compare it to Google's hand-coded WSDL at http://api.google.com/GoogleSearch.wsdl
     and see how close (or not) the generated version is. 
     
     Note that I used GoogleSearch as the canonical "best practice"
     interoperable example when implementing WSDL/SOAP support, which might
     explain extreme similarities :)


  3. Test that it works with .NET (Mono in this example):

        $ wget WSDL_URL
        $ mv wsdl GoogleSearch.wsdl
        $ wsdl -out:GoogleSearch.cs GoogleSearch.wsdl

     Add these lines to the GoogleSearchService class body (be mindful of the 
     wrapping):

        public static void Main(string[] args)
        {
            GoogleSearchResult result;
            GoogleSearchService service;
        
            service = new GoogleSearchService();
            result = service.doGoogleSearch("myApiKey", "my query", 10, 30, true, "restrict", false, "lr", "ie", "oe");
            System.Console.WriteLine("documentFiltering: {0}", result.documentFiltering);
            System.Console.WriteLine("searchComments: {0}", result.searchComments);
            System.Console.WriteLine("estimatedTotalResultsCount: {0}", result.estimatedTotalResultsCount);
            System.Console.WriteLine("estimateIsExact: {0}", result.estimateIsExact);
            System.Console.WriteLine("resultElements:");
            foreach (ResultElement element in result.resultElements) {
              System.Console.WriteLine("\tsummary: {0}", element.summary);
              System.Console.WriteLine("\tURL: {0}", element.URL);
              System.Console.WriteLine("\tsnippet: {0}", element.snippet);
              System.Console.WriteLine("\ttitle: {0}", element.title);
              System.Console.WriteLine("\tcachedSize: {0}", element.cachedSize);
              System.Console.WriteLine("\trelatedInformationPresent: {0}", element.relatedInformationPresent);
              System.Console.WriteLine("\thostName: {0}", element.hostName);
              System.Console.WriteLine("\tdirectoryCategory: {0}", element.directoryCategory.fullViewableName);
              System.Console.WriteLine("\tdirectoryTitle: {0}", element.directoryTitle);
            }
            System.Console.WriteLine("searchQuery: {0}", result.searchQuery);
            System.Console.WriteLine("startIndex: {0}", result.startIndex);
            System.Console.WriteLine("endIndex: {0}", result.endIndex);
            System.Console.WriteLine("searchTips: {0}", result.searchTips);
            System.Console.WriteLine("directoryCategories:");
            foreach (DirectoryCategory cat in result.directoryCategories) {
              System.Console.WriteLine("\t{0} ({1})", cat.fullViewableName, cat.specialEncoding);
            }
            System.Console.WriteLine("searchTime: {0}", result.searchTime);
        }

    Now compile and run:

      $ mcs -reference:System.Web.Services GoogleSearch.cs
      $ mono GoogleSearch.exe


    If you had the application running (on the same host you got
    the WSDL from), you should see something like this:


        documentFiltering: True
        searchComments:
        estimatedTotalResultsCount: 322000
        estimateIsExact: False
        resultElements:
                summary: ONlamp.com: Rolling with Ruby on Rails
                URL: http://www.onlamp.com/pub/a/onlamp/2005/01/20/rails.html
                snippet: Curt Hibbs shows off Ruby on Rails by building a simple ...
                title: Teh Railz0r
                cachedSize: Almost no lines of code!
                relatedInformationPresent: True
                hostName: rubyonrails.com
                directoryCategory: Web Development
                directoryTitle:
        searchQuery: http://www.google.com/search?q=ruby+on+rails
        startIndex: 10
        endIndex: 40
        searchTips: "on" is a very common word and was not included in your search [details]
        directoryCategories:
                Web Development (UTF-8)
                Programming (US-ASCII)
        searchTime: 1E-06


    Also, if an API method throws an exception, it will be sent back to the
    caller in the protocol's exception format, so they should get an exception
    thrown on their side with a meaningful error message.

    If you don't like this behaviour, you can do:

      class MyController < ActionController::Base
        web_service_exception_reporting false
      end

  4. Crack open a beer. Publishing APIs for working with the same model as
     your Rails web app should be easy from now on :)
