Senior Software Developer at Citrix Systems Luis is a DZone MVB and is not an employee of DZone and has posted 10 posts at DZone. You can read more from them at their website. View Full User Profile

Google App Engine Java Capabilities and Namespaces API

03.28.2012
| 2938 views |
  • submit to reddit
With the Capabilities API, your application can detect outages and scheduled downtime for specific API capabilities. You can use this API to reduce downtime in your application by detecting when a capability is unavailable and then bypassing it.

How de we handle this, what’s the tradeoff?

  1. Elegantly: create an aspect that cross cuts all data store writes, and checks for capability. Fail with friendly error message.
  2. Not so elegantly: add capability checking into the repository code before every write. Fail with friendly error message.
  3. Quickly: write filter that wraps the entire transaction and checks for data store writes.

How can we test this on a local environment?

  1. No API hooks. Currently, I have not been able to find or use GAE Java proxies to test the capability call.
  2. The solution would be to create different builds one with a Mocked Capability Service that is able to return the CapabilityStatus.DISABLED flags and test.


Due to time reasons, I went for the quick approach. I will try to revisit this later and incorporate AspectJ or Google Juice to leverage aspects for this obvious cross-cutting concern.

Example:

Map<Capability, Boolean> apis = new HashMap<Capability, Boolean>();
     public void init(FilterConfig filterConfig) throws ServletException {
  
  apis.put(Capability.DATASTORE, true); 
  apis.put(Capability.MEMCACHE,  false);  
    }


    public void doFilter(ServletRequest req, ServletResponse res,
  FilterChain chain) throws IOException, ServletException {
  
 HttpServletResponse httpResponse = (HttpServletResponse)res;
 HttpServletRequest httpRequest = (HttpServletRequest)req;
  
 CapabilitiesService service =
  CapabilitiesServiceFactory.getCapabilitiesService();
  
 for(Map.Entry api : apis.entrySet()) {
   
  if(api.getValue()) {
         CapabilityStatus status =  service.getStatus(api.getKey()).getStatus();
    
      if (status != CapabilityStatus.ENABLED) {
   log.warn("API " + api.getKey().getPackageName() + ":" + 
                            api.getKey().getName() + " has been disabled!");
   httpResponse.sendRedirect(NEPAL_RES_HOST + "/html/read-only.html");
   return; 
       }
  }   
 }  
 chain.doFilter(req, res);  
   }

Namespaces API
Before we can talk about this API, let's introduce the concept of Multinenancy.

One of the most compelling uses of Namespaces API is multitenancy.
Multitenancy is the name given to a software architecture in which one instance of an application, running on a remote server, serves many client organizations (also known as tenants).
Multitenancy simplifies administration and provisioning of tenants. You can provide a more streamlined, customized user experience, and also aggregate different silos of data under a single database schema. As a result, your applications become more scalable as well as more cost-effective as you scale

Data becomes easier to segregate and analyze across tenants because all tenants share the same database schema.
Multitenancy is different than multi-instance:

  • In multi-instance different software instances are set up for different client organizations.
  • In multi-instance the application is typically not aware of the difference of customers, whereas in multitenancy the application is reposible for segregating and partitioning the data.


The Namespaces API in Google App Engine makes it easy to create silos of your Google App Engine data. This API is implemented via a new package called the Namespace Manager.

When you set a namespace in the namespace manager, these APIs get the current namespace and use it globally.

Any App Engine request can access any namespace, leaving the application to enforce an access control policy across namespaces. In this approach, it is the application which is responsible for setting the working namespace.


Namespace-aware APIs:
  1. Datastore
  2. Memcache
  3. Task Queue

Using the Namespaces API, you can easily partition data across tenants simply by specifying a unique namespace string for each tenant. You simply set the namespace for each tenant globally using the Namespace Manager. The namespace-enabled APIs always use the current namespace by default.

In the datastore, the Namespace Manager will apply the namespace to every Key and Query object.
There is no Java API to explicitly set the namespace of a Key or Query, all happens through the Namespace Manager.


Resources:
  1. Java Doc. http://code.google.com/appengine/docs/java/javadoc/com/google/appengine/api/capabilities/package-summary.html
  2. http://blog.notdot.net/2010/03/Handling-downtime-The-capabilities-API-and-testing
  3. http://code.google.com/appengine/docs/java/capabilities/
  4. http://code.google.com/appengine/docs/java/multitenancy/

 

 

Published at DZone with permission of Luis Atencio, author and DZone MVB. (source)

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)