Pages

Monday, March 9, 2015

Dito Directory integration with Google Apps

Editors Note: This post was written by Jim McNelis and Vinay Thakker of Dito, a provider of Google Apps deployment, training, integration, and support services, and makers of Dito Directory. We invited Dito to share their experiences building an application for the Google Apps Marketplace on top of Google Apps utilizing some of our APIs. You can meet Dito at Google I/O May 19 - 20 in San Francisco where they will be in the Developers Sandbox.

The Google Apps Marketplace is a great sales channel that allows us to market our products to millions of Google Apps users. Dito Directory for Google Apps is just the first step for Ditos custom application development on Google technologies like Google App Engine, Google Apps APIs, and Google Web Toolkit. We are excited that Google is now providing us with an advantageous delivery platform for 3rd party apps.

Dito, an IT solution provider specializing in Google Apps, was founded in 2007 by brothers Jim and Dan McNelis to help small and medium sized business enhance their IT infrastructure with cloud-based solutions. Since then, upwards of 40% of our customers have found us on the Google Apps Marketplace, so it was a logical choice to list our application there as well.

The Google Apps Marketplace allows domain administrators to install Dito Directory with a couple easy clicks, making the purchase as painless as possible. Dito Directory uses OpenID for user authentication, which means no additional login is necessary. Once installed via the Marketplace, Dito Directory becomes accessible instantly for Google Apps users via Googles universal navigation.

Dito Directory was developed as a result of customer demand for better contact management. We make it easy to import your existing contacts in bulk via the Google Spreadsheets API, which polls an admins spreadsheets and allows them to easily import existing contacts. As with all of our interactions with user and company data, we leverage 2-legged OAuth for authentication and OpenID for single sign-on. This allows our application to safely and securely access your information without the risk of compromising it to 3rd parties.

Sometimes, Google Apps users need more direct access to a domain shared contacts information. With the "Copy to My Contacts" feature in Dito Directory, admins and users can copy any domain shared contact to their personal contacts, instantly. If a users contacts are synced with their mobile device, the contact will show up on their device nearly as fast. Dito Directory interacts directly with a users contacts via the Contacts API.

Enough about the what and the why...lets talk about how we developed Dito Directory. For that, Vinay Thakker, our Google App Engine-eer, is going to give you his perspective.

Leveraging Google scalability

A week before the launch, we decided to gut the app and start fresh. Despite my successes with application architecture in the past, there was one big thing, from a developers standpoint, that I didnt like with our first attempt:

It didnt scale well.

Of course, I mean that in terms of adding features to it, since App Engine effortlessly handles the load distribution and scaling for us. As the client-side of our app grew, its statefulness became exponentially more difficult to manage. Most of our widgets needed to know about the state of other widgets. Generally, for UI elements, we do this using events. The number of event handlers required to obtain complete state communication in the application grows like the graph of a factorial with each additional widget (no kidding, its painful).

My initial design was the bomb, though. So, why change?

The ease of using GWT makes developing event handlers a breeze, so in the beginning you may not realize what youre signing yourself up for. You can make a monstrous improvement by centralizing your event bus. In doing this, you should consider using the command pattern design. Its benefits are ridiculously awesome, and how you would implement it is probably better to be left to Wikipedia to explain, since thats what I would paraphrase.

Browser history and state related issues

The second big thing that helped us was when we decided to account for browser history. You have to do this from the beginning of your design, but the good news is its freakin easy to implement. Ill show you how in a minute, but first let me mention that implementing GWTs History class is a forcing function for state in your application. By virtue of implementing history across our application, we solved 91% of our state-related issues. On top of that, the user gets their beloved back and forward browser buttons back, as well as some other cool stuff, like the ability to bookmark and link to states of Directory. Using GWTs built-in History class is a two-and-a-half step process. Heres how you do it:

Step 1: Create a class that implements the HistoryListener interface. Its really just one function, onHistoryChanged, in which you tell the app how it should render itself, based on the incoming state. Make it short; have your main class that does onModuleLoad implement HistoryListener.

public class MyApp implements EntryPoint, HistoryListener
{


public void onModuleLoad()
{
}
public void onHistoryChanged(String historyToken)
{
}
}// MyApp

Step 2: Tell the History class that you have a class that wants to listen to changes in the History state. Lets do this in onModuleLoad(). Also, you can choose to fire off the current history state so your onHistoryChange method from above gets called on load. If it makes sense for your app, force it into an initial state, also shown here.

public void onModuleLoad()
{
if (History.getToken().isEmpty())
History.newItem(“myInitialState”);


History.addHistoryListener(this);
History.fireCurrentHistoryState(this);
}

Step 2.5: This isnt really a step. This part belongs to all of the development you would have been doing anyway. This is where you actually add code to your onHistoryChanged method to make it do something useful based on the state.

public void onHistoryChanged(String historyToken)
{
if (“myInitialState”.equals(historyToken))
{
// render the app appropriately for this state.
// this state is accessible at thisPage.html#myInitialState
}
if (“myOtherStateName”.equals(historyToken))
{
// render it another way..
}
}


You can see how this would force state on your app. Youll find that in a lot of cases, you will be able to use traditional anchor links where you might have otherwise created a new Java function and binded it to the onClick event of some object or widget.

Cool stuff. Let us know what you think, or ask Vinay a question, email vinay@ditoweb.com.

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.