Apr 23, 2014

Coming Around a Full Circle

Less than nineteen years back, I took my first trip abroad to the US. Still remember day 1 in US and my first bite of food at JFK airport - a baked potato loaded with cream cheese. 

From then on I've been fortunate enough to have got a chance to visit various parts of the world and experience different cuisines. Along the way chicken became one of my favorite foods to eat. Whenever we ate out while in India or abroad, I would seek out chicken in various forms. 

Thai cuisine has been one of my favorites. A month back I got my first visit to Bangkok and I was pretty excited to be in the land of Thai food. Tried to blend in during the first couple of weeks and eat along with my colleagues at the local restaurants. Just couldn't stand the sights and smells of the various kinds of meats and sea food there. 

At some point I thought about trying out only vegetarian. It was quite an effort ordering vegetarian food at the more traditional restaurants but it was okay at the more international ones. It's been over 2 weeks now eating only veggie stuff. This week I've been eating MTR packaged food for lunch. 

And guess what... I am feeling great. It's great to know I don't have to worry about what I am putting into my mouth. 

So whereas 19 years back I made a choice to each chicken meals to have a variety of choices, I think now I am making a choice to eat vegetarian and keeping it simple and real. Let's see how it goes. 

चलो सात्विक भोजन खाऐं। 

Apr 6, 2014

A Gentle Introduction to Peak Oil

Recently I picked up this book "The Third Curve - The End of Growth as we know it". The book is written by Mansoor Khan, an alumnus of IIT Mumbai, Cornell University and MIT, Boston. For those of us smitten by celebrities, he is the director of two of my favorite Hindi movies: QSQT & Jo Jeeta Wohi Sikandar. 

The book explores Peak Oil in detail and how it impacts our lives. Very simply put:

  1. Growth based economies of the world demand Perpetual Exponential Quantitative Growth (PEQG).
  2. Growth is directly or indirectly related to Oil and its byproducts which are a finite resource. 
  3. World Oil production has peaked around 2008 and from there on, the amount of Oil we are able to extract from the Earth has been declining. 
  4. Just because we are at half way mark does not mean that we have many more years before Oil runs out. Our consumption rate has increased exponentially so if we continue the same consumption pattern, Oil will run out in 3 to 5 decades. Remember the king who granted the wish of one grain of rice on one square of a chessboard and doubling it on each square until the entire chessboard is full - only now, its the reverse: we started from abundance and are consuming exponentially towards 0. The book has a quote on this by Prof. A.A. Bartlett, University of Colorado who says The greatest shortcoming of the human race is our inability to understand the exponential function.
  5. Alternative energies such as Solar also depend upon Oil for setup and maintenance and do not provide us the byproducts, e.g. plastic, fertilizer, etc., which our economies rely on. Also alternative energies are not as energy-dense as Oil and other hydrocarbons. 
  6. Summary: Growth based economy, as we know it, is not sustainable. 
Source: http://www.thefuture.net.nz/peakoil.htm

The book confirmed a few of my theories and also opened up my eyes to a few facts which I was not aware of. Always used to wonder at the wisdom, or lack of it, of transporting common vegetables, fruits and flowers across large distances. Never understood complex financial instruments. Always thought we can survive without oil or reduced oil by reducing consumption and using alternative energies - definitely not possible considering our reliance on oil byproducts. 

So, where do we go from here? Is it all doom and gloom? 
Fortunately no. There is a better and more wholesome world out there but it does require us to change our outlook drastically. It has to be back to grass roots - local as against global and community as against individual. We have to rebuild the social capital which we so far have been systematically destroying for achieving growth. 

There is some historical proof of this as well. The dissolution of Soviet Union in 1991 led to a severe economic crisis in Cuba; this period is called The Special Period. Oil imports dropped by 75% and food by 80% resulting in rationing of food and fuel. GDP dropped 34% and consumption reduced by 20% of previous levels within first two years. Cubans dealt with this crisis by developing a local system and tackling their situation with a community approach. Agriculture transformed from industrial to organic farming and local food markets. Today 80% of Cuba's food production is organic. This has improved soil quality as well as the general health of the people. 

Who does it? The governments? 
No, each of us have to build the awareness among our communities about what is coming. We have to engage our school teachers and college professors in Peak Oil discussions and enable them to educate our children and youth on the subject as part of their regular curriculum. Business and Banking community has to be engaged to make them understand that economic shrinkage is the new reality. This will then lead to involvement of the local authorities and governments. 

Scared? Interested? Want to know more?
I am sold that this is the next opportunity... one where each one of us have to play a role, it's almost as profound as providing one the Purpose of Life. The goal is how to make our lives sustainable in the post Peak Oil period. 

Awareness is the first step. Build it using the following resources:

Jan 2, 2014

2013 - The Year That Was

Year 2013 turned out to be a difficult and trying one - both on the home and work front.

Much of the year was spent in trying hard to survive and deliver in a very difficult work environment at Thomson Reuters. Fortunately for me, one of my social contacts made through Cloudspokes helped me land an interview at Salesforce Services in early August. A speedy interview process and early relief at Thomson Reuters enabled me to join Salesforce Services in early October. 

It's been close to three months at Salesforce now and I have to say that this truly is a #dreamjob. In the few months I have been here, I have been part of multiple successful customer projects. I have been a key contributor in the migration of Salesforce developer discussion forums from Lithium to Chatter Answers. Check out the new forums. What tops the work is the team dynamics - blessed to be part of the wonderful team at Salesforce. 

On the home front, demise of my father in law in September after a short bout of critical illness meant a lot of stress and pain in the extended family. Support came from within and outside the family. This has been my closest encounter with death so far. Strangely I was quite calm and my belief that death is just a part of the whole cycle helps deal with the loss. 

Few more highlights of the year: 

  1. Road trip to Chennai and Mahabalipuram with Sanjeev was wonderful and truly the only time I really felt free this past year. 
  2. Got my Royal Enfield Thunderbird 500 in June. Haven't gone on any really long trips myself but my brother and his friend took it out to Karwar and back during last week of December and enjoyed it. 
  3. Sanjana got enrolled in German Exchange program at her school. We had a German student from Augsburg stay with us for two weeks in Sep/Oct. Sanjana herself will be visiting Germany in April this year for two weeks. What a wonderful experience at this young age. 
  4. Shobha is getting better at her drawings and paintings. I still have to build a site for her - need to get on with it quick!

A recap of my wishes for 2013:

  • Improve fitness and restart cycling - failed miserably - just 387 Kms cycled in 2013 
  • Learn to play Guitar - failed - didn't even start
  • Be a better person - I sure tried but others have to say whether I succeeded
  • Decide between getting a Royal Enfield Thunderbird or Harley Iron 883 - Got the Thunderbird
I've been pretty bad this year in connecting with friends and family. There's just been so much going on. Need to get better at this. 

Some wishes for 2014:

  • Improve fitness - cycling or otherwise
  • Learn to plan an instrument
  • Improve professional competence and credentials
  • Blog more often
  • Contribute more at home
Wish you all a very Happy New Year - 2014. May the year bring with it your share of joy, happiness, opportunities, challenges and the strength & resolve to deal with them. Be different, be adventurous and above all have fun.

Feb 17, 2013

On Cloudspokes Home Page

Cloudspokes just underwent a complete re-design. Found myself on one of the home pages of the redesigned website. Capturing a screen shot of the same here. Feels good.

Jan 1, 2013

2012 - The Year That Was

Year 2012 turned out to be quite an eventful one. 

Began the year with helping my parents move to the same apartment complex where I stay. April brought with it a trip to parts of North India - Jim Corbet National Park, Haridwar and Agra. 

Spent close to two weeks in June in the USA crewing for Race Across America (RAAM) team - The Beefeaters. Though I wanted to blog in detail about the experience, the fact that I was awake for over 22 hours each day of the 7 day race and I did not bother to take brief notes during the period, I did not remember enough at the end of the race to write about it. All that I had were the pictures and memories of the time spent with the new friends. 

August saw me traveling to London for a couple of weeks. This was my second trip and traveling alone this time let me enjoy the city more than I had on the previous trip with 3 colleagues. Arrived on a Saturday night just a day before the closing of London Olympics 2012. Was fortunate to stay at the Tower Hotel right next to the Tower Bridge which allowed me to catch some of the Olympics spirit by seeing the Marathon runners in person. 

Attended the Startup Weekend in September - while I had no spectacular idea, just being part of the event helped kindle the entrepreneurial spirit. September brought more cheer and rejuvenation as I got my large public speaking opportunity when I spoke at Google DevFest. The talk was very well received and made me think 'I need to do more of this'. 

October to December has been a whirlwind of tech conferences - Mobile Developers Conference, SpringOne, DroidCon & AWS Summit. Participated in quite a few Cloudspokes challenges - won few :-) Also developing a registration and checking software for Oxfam Trailwalker event. 

On the family front, wife (Shobha) started focusing on her one passion - art and has been making wonderful progress. Check out some of the work here. Elder daughter (Sanjana) started blogging - amazed at some of the wonderful pictures she has taken and the quality of her writing. Check out some of her work here.The surprise package has been the younger one (Ananya). While being the wild one and with the least attention span, she continues to amaze us with some very thoughtful gestures, her learning ability when she wants to and her shy creative side - she made this awesome iPad video reviewing one of the Geronimo Stilton's book which we were all amazed to see. Parents are happy to be living close to us and that makes us happy as well. 

A great year meeting friends from school, college and ex colleagues. Few which come to mind: Two days spent with Ashu in New Jersey when he would go to work and I would stay back at home and go out shopping in his car - Harsha quipped 'not much has changed - you were using his bike in college, now his car :-)', meeting Harsha's family in New Jersey and a teeny-weeny Aditi greeting me with 'Hello Shashi', road trip to Mysore with Varma and Deepak and meeting Charlie, Varuna, Shashidhar T.S. and Meena, running into Maiya and family at Pascucci on a Friday evening, meeting my school friend Meenakshi for lunch on a Friday afternoon in Bangalore - literally after 23-25 years, catching up with Sanjay and Himanshu for drinks in Ghaziabad, catching up with Alka and family at Gurgaon on the way to Delhi airport, few hours spent with Ashu's family at Charlie's place, meeting Madhu, Charlie and Deepak for lunch (and not being able to meet Madhu again before he left for US), lunch with Sharwari on a rainy Bangalore Friday afternoon at a wonderful Vietnamese restaurant. 

Highlights: RAAM crewing, email from my Wipro colleague (Indu) saying how I was a positive influence on her and she had spoken about me in one of the management trainings she had attended. 

Regrets: Weight gain as I did very less cycling - only around 1100 Km as compared to 5000+ & 7000+ Km during the previous two years. Quite a forgettable year at office - both on relationships and work front. 

Some wishes for 2013

Wish you all a very Happy New Year - 2013. May the year bring with it your share of joy, happiness, opportunities, challenges and the strength & resolve to deal with them. Be different, be adventurous and above all have fun. 

Now this should leave you with a smile. Was fooling around with daughters' earrings and turns out both my ear piercings from childhood are still open - check out the pic below.

Jun 15, 2012

RAAM 2012: Friday 15-June-2012

Around April this year I heard of the opportunity to crew for a RAAM team. I jumped at it and after a few mail exchanges with the team got the confirmation that I am in. Last couple months have been a nervous preparation for the event. On the morning of Wed, 13th June 2012, I left for the US and two connections and 30 hours later landed in Los Angeles. Picked up the rental car and drove down to San Diego to catch up with a college mate. After breakfast on 14th morning, took a train up to Oceanside... almost there. 


Got into Oceanside early afternoon and met up with my team - The 4 Beefeaters from UK. We then proceeded to the pier for inspections. The scene at the pier was amazing - feverish preparations of the vehicles, bikes and kits to get ready for the inspections, the actual inspections, riders taking small rides, meeting with other teams, people at the beach - in all an invigorating and happy environment. We got our inspections done and headed back to the hotel. 


Evening brought with it what turned out to be a long 3 hour crew meeting. The crew chief, Jim Rankin went over the work assignments. I will be in the RV with Jim - working the schedule. We then went over the entire route with details of what to look out for between each set of time stations. The level of detail in the RAAM routing is just plain amazing. Check out the official 2012 directions here


Hit the bed at around 10.00 PM watching Crocodile Dundee on the TV. Woke up at 5.30 AM and writing this post. Hopefully the sleep cycle is now adjusted to the US times. 


Stay tuned for more updates once we start the race tomorrow at 12.00 PM pacific time. 
Inspection
Inspection
The support & follow vans with their bears
The RV

May 18, 2012

My "Better know a Cloudspoker" interview on YouTube

Cloudspokes' Jeff Douglas interviewed me some time ago as part of the Better know a Cloudspoker series. Check out the interview on YouTube. 

May 12, 2012

Lego Mindstorms Nxt Strider

It's been close to two years since I had purchased the Lego Mindstorms Nxt robotics set. Being alone at home yesterday evening, thought of putting together one of the robots. Decided to build the walking robot - or strider as named in the book. Stayed up till 3.00 AM this morning putting together the robot. Did the programming in the morning and am quite satisfied with the results. Interestingly, modified the mechanical design slightly to allow a better click of the touch sensors. Need to rubberize the leg tips so that the walking is non-slippery. 
The Strider
For those unfamiliar with Mindstorms robotics kit, it is one cool robotics set by Lego. Not only can you build cool robots, you can actually program it to do things. It includes 3 motors, 2 touch sensors, an ultrasonic sensor and a light sensor. Programming is done visually using the included software. The programs can be transferred to the robot either via a USB cable or wirelessly via Bluetooth. 


Highly recommended for kids 12 and above and of course the inner kid in every adult :-). Enjoy!

Jan 2, 2012

2011 Car / Bike Usages Statistics

It's been 2 years since I purchased my bike - Cannondale Quick 5. I have been keeping track of my car fuel usage since 2009 and bike usage since I got my bike. 

It's interesting to see the car statistics over the last 3 years. Average fuel price went up by over 25%, fuel consumption went down by 15%. Overall my fuel expenses went up by 7%. Let's see if I can reduce my fuel expenses this year. 

My total Kms on the bike went down by over 25% but cost reduction Kms went up by close to 13%. The aim for this year would be to increase both by around 15-20%. 

Dec 21, 2011

Failing Gracefully

No, this is not about how to design/build software which fails gracefully. This is a short commentary on my recent Did Not Finish (DNF) on the 300 Km Kolar Gold Fields (KGF) Brevet ride. 


For those not familiar with what a Brevet ride is: it is a self supported non competitive time bound bike ride. The 300 Km KGF Brevet ride would take us across 3 states and we had to cover 313 Km in 20 hours at an average speed of over 15 Kmph. I had previously done a 300 Km Brevet ride so was quite confident of completing this as well. 


But what a crazy ride it ended up to be. The ride started at 6.00 AM from MG Road metro station. It was great riding in the fog all the way up to Hoskote where we turned right towards Malur. This is where the state highways and village roads started. In addition to this had a consistent wind resistance for most of the ride. The weather was good and while there were bad stretches of roads, the tree cover on both sides of the road provided protection from the Sun. Rode through nice stretches but was always under the gun to keep moving - was averaging right around 15 Kmph including the breaks. Took only short breaks to eat and stretch. 


Reached Pernambut @ 3.00 PM but missed the SBI ATM which was the second control point. Went back in search of this and lost precious 30 minutes. Checked in to the control station just in the nick of time - had covered 143 Km in 9.5 hours. Reached Vaniambadi toll booth around 6.00 PM - had covered 182 Km in 12 hours. Took a rest break here and saw 7-8 riders pass by. While I was happy that I was not way behind the others till this point, I was worried about what lay ahead. I was averaging 15 Kmph at this point and the remaining 131 Km ride would be in cold, dark and include a tough 50 Km climbing ride from Krishnagiri to Hosur. This is where I decided to not ride in the dark but take a bus back to Bangalore from Krishnagiri instead. Reached Bargur around 8.00 PM and had dinner here. Thought I would try and get a bus right from here and waited for 30 minutes to get a bus but no luck. Again got into bike gear and rode to Krishnagiri and requested/argued with the conductors to take me & the bike to Bangalore. Thankfully had luck on the second try itself and after securing the bike on the top, deposited myself on an empty seat for a cold uncomfortable drive back to Bangalore. Reached at 00.30, got the bike down and rode home to reach around 1.20 to end a day of painful riding.


Fellow rider Parag later learnt about my DNF and enquired if I was okay. Informed him that I was okay but decided to quit as I did not want to ride in the night. My idea of a good bike ride is where you get to enjoy the ride and not just burn the Kms. Honestly I was in a pretty bad mood riding through the nice villages. Did not even exchange pleasantries with the village folks which I usually do on a ride. I guess no more Brevet rides for me... but hey! you never know :-). 


Couple of tech highlights of the ride:


Map My Ride: I developed an application using which a rider could mark one's location on a ride and anyone could track the progress of riders. I could not use the app very well as my iPhone did not seem to work very well but Devaraj marked his position throughout the ride - Thanks for checking out the app Devaraj. My thought now is that this app is better used by tourers and not in time bound events as time is of the essence in these rides and geolocation + marking location takes some time - I did end up wasting quite a bit of my time trying to locate myself and mark my location. You can check out the app here: Map My Ride. Suggestions for enhancements are welcome. 
Map My Ride - Mark Location Screen
Rider Progress - Devaraj & Shashi's Updates
Solar Charging Garmin: I had purchased a Solar Monkey solar charger on a recent trip to London but had never used it till now. I used this charger on this ride and am happy to report that my Garmin Forerunner 305, which usually runs out of battery in 13-14 hours, survived the entire ride - home to home - around 18 hours and still had some juice left in it. I think I can get it to work even more effectively if I am able to position the solar panel well. Check out the setup below. 
Solar Monkey & Solar Nut charging my Garmin Forerunner 305

The power of Community Development

Over the past few months the cloudspokes.com site was rebuilt on Heroku and Database.com. Code contributed by developers across 8 countries over 22 challenges was used to rebuild the site. Proud to say that I have been a part of this journey. Read more on the Cloudspokes Blog

Dec 6, 2011

Bangalore to Chennai Ride

It's been a while since I did much of regular cycling. Since Aug 2011, couple of overseas travels, unseasonal and (often unpredictable) Bangalore rains, the time I have been spending lately learning and using cool and exciting cloud technologies and finally plain laziness have kept me off the bike. So much so that it started showing on the waistline as well. 


So when my parents and few other relatives decided to visit my cousin in Chennai, I figured why not ride to Chennai and return in bus along with them. Chennai appeared to be a good choice as I would be riding with loaded panniers and the route did not have many climbs. Thus the plan was born. 


The total distance to be covered was around 342 Km. My gameplan was as follows: 

  • Ride with minimal breaks
  • Start the ride early in the morning and end by early evening
  • Take rest during mid day when the Sun is at its scorching best
  • Ride as much as possible on Day 1 so that I reach Chennai early on Day 2 and spend more time with family. Vellore was the planned target for Day 1. 

Packed my two pannier bags as follows: 
  • Bag 1 - change of clothes at end of Day 1, fresh riding clothes for Day 2, two tubes and puncture kit. 
  • Bag 2 - Extra 1 litre bottle of water, 1/2 litre bottle of orange juice, sandwiches (packed by wife in the morning), air pump, tools, gatorade, torch, wet wipes, almonds and raisins. 
Day 1 - Saturday, 3/Dec/2011
Started from home at around 3.30 AM. Before long passed silk board and then stayed on the service lane all the way till past Electronic city. Stopped at the A2B before Krishnagiri at around 7.00 AM with the Garmin indicating 71 Km. Had a couple of sandwiches and a coffee and re started the ride around 7.30 AM. Saw Chiddu and Parag on the other side of the road returning from their Krishnagiri ride. Could wave and shout out only to Parag as Chiddu had passed me before I could react. We gave each other a thumbs up and moved on in our respective directions. Quite an uneventful ride till around 11.00 AM when the Sun started getting intense. The breeze which was against me was actually quite welcome due to the cooling effect. Passed by a town called Ambur which I later came to know is famous for leather and shoe works. Saw lots of small and large factories dealing with leather and shoes. Also passed by a small coir establishment - Could see some of the processing from road. It's a wonder how every part of the coconut plant is utilized in some form or other. I wanted to break for lunch only after completing half the distance to Chennai and also at a place where I could take some rest during the peak afternoon. Found a temple on the road side which had a resting area. Decided to take a break here for lunch. The Garmin showed 171 Km and the time was 12.25 PM. Washed up, had the remaining sandwiches and slept for some time after securing the bike. Left from here around 2.00 PM for the final leg of travel for the day. While the Sun still fell hot at 2.00 PM, post 3.00 PM, the heat was not that intense and was quite comfortable. Reached Vellore around 4.30 PM but decided to continue onto the next town Ranipet as there was still daylight and I was feeling strong. Reached Ranipet around 5.30 PM and found a hotel right at the edge of the town. The hotel was not so great and actually quite shady but I figured "will just be sleeping here and it is right on the highway" and so decided to stay there. Washed up, went out and had some food, got some water & bananas for next day. Got back to the hotel and after cleaning the bike and setting the alarm for the next day, went to sleep early at 9.00 PM. 

Day 2 - Sunday, 4/Dec/2011
Woke up around 3.45 AM and quickly got ready and hit the road at 4.18 AM. Was riding in a new area in dark so though I was using two sets of front and rear lights, was waiting for the dawn. The hints of daylight started around 5.45 AM but since the fog was rolling in, saw the first glimpse of Sun only around 7.00 AM. After passing Sriperumbudur, got off the main highway and took inside roads to head towards the Airport. I had another 30 odd Kms to cover. The roads were bad in stretches. Passed a glass recycling area - had never seen so much broken glass in one place. Crossed a stream of water on foot carrying the bike - contemplated removing my shoes but since it was only a short stretch to the destination I just walked through the water. Since it was a Sunday and feast day, saw several places selling pig meat - in fact at one place saw a whole pig head next to the meat - wow! Pretty soon I could see planes making their approach to landing - I was close to the destination. Covered the last few Kms quickly and with some directions from a traffic policeman arrived at my cousin's home in Nanganallur. Was received warmly by her family and thus ended my ride to Chennai. 

Some Gyan
While the whole ride was quite uneventful - no punctures or breakdowns, no accidents or altercations, no wrong turns, no running out of water - the ride itself made me come to a few conclusions:
  • While it may sound like a cliché, it is true that the longest of journeys begin with that first step or in this case the first pedal. Till the time I came out of my home on Saturday morning, I was not sure whether I would start or no. But I just told myself "Lets go for it. You can always stop and return.". 
  • While touring, don't aim for speed and higher gears. Keep at lower gears and keep going. I was myself surprised that though I rode for long stretches in 2 x 3, 2 x 4 & 2 x 5 combinations, I still had an overall riding average of over 20 Kmph. 
  • Be prepared - food, drink and tools. Though I didn't have to use the tools, it was calming to know I had the tools to do basic fixes and puncture repair if I needed to. I always made sure I had a reserve of water with me and would stop to buy water before I ran out of it. 
  • It is difficult to keep riding on and on. On this route, the pedalling is not difficult as it is a fairly flat route with the few uphills being only the ramps to bypass the towns and cross the occasional stream and railway tracks. The catch is how do you motivate yourself to keep going. I just kept at it visualizing the bed at the end of the day, the nice food I would have at the end of the day and the get together with the family members after so many days. Visualizing a nice end or a goal is always a good motivation to keep you going - whether it is cycling or something you are aiming for in life. I have myself found this technique work for me many a time. 
Statistics
  • Day 1 - 238 Km - 11 Hours 20 Minutes riding time, 14 Hours elapsed time
  • Day 2 - 105 Km - 5 Hours 30 Minutes riding time, 6 Hours 10 Minutes elapsed time
  • Intake:
    • Food - 6 2-slice Potato sandwiches, 7 Bananas, 1 Orange, 3 Idlis, 1 Vada, handful of almonds and raisins
    • Fluids - 6 Litres of water, 1 small coke, 1/2 litre orange juice and 6 packs of Gatorade 
I did not take too many pictures on this trip to not lose time but here are a few. Not sure how many of you have seen this type of grasshoppers. They used to be a regular sight in U.P. where I grew up but haven't seen any here in Karnataka, Andhra or Maharashtra. 



Oct 3, 2011

Google+ to Salesforce Chatter Integration

This article describes my entry to the cloudspokes.com Google+ to Salesforce Chatter integration challenge. It covers using OAuth2 to connect to Google+ from Salesforce Apex, making call to the Google+ API to retrieve the Google+ posts to be posted to Chatter and then posting them to Chatter. 

Requirements

Though the title says Google+ to Salesforce Chatter integration, the integration is initiated in reverse. From Salesforce end, we should be able to pull the user's Google+ posts targeted to be sent to the user's Chatter account using a specific hashtag (#ch). 

The Moving Parts
  1. Google OAuth2 - Authentication and Authorization to Google+ APIs. 
  2. Google+ API - Provides access to the user's Google+ posts. 
  3. JSON Parser by Ron Hess - Is used to parse the JSON returned by the Google OAuth2 for server-side web applications and the Google+ APIs. 
  4. Visualforce page and it's controller - Implements the integration logic and allows the user to fetch his Google+ posts and insert the same to Salesforce Chatter. 
Setting Up Google APIs Access
  • Navigate to Goole APIs Console. Create a new project, e.g. API Project. 
  • Navigate to Services tab of Google APIs Console and turn on the Google+ API service. 
  • Navigate to API Access tab of Google APIs Console. Click on Create an OAuth 2.0 client ID
  • Enter 'G+ Chatter Integration' in product name field. This information will be shown to users when your application requests access to their private data using your new client ID. Click Next. 
  • Select Web Application on the next screen. Click on more options link next to Authorized Redirect URIs and enter https:///apex/GooglePlusToChatter in Authorized Redirect URIs text box and https:// in Authorized JavaScript Origins text box. Replace  with your salesforce instance url. Click on Create client ID. Note the client ID and Client Secret. These will be required to setup the Apex connectivity to Google+ in later steps. 
  • See the pictures below for visuals of the above steps. 

Picture 1 - Initiate creation of client ID

    Picture 2 - Create Client ID Step 1
    Picture 3 - Create Client ID Step 2
Picture 4 - View of newly created Client ID
Google+ APIs
Google+ APIs were made available in Sep 2011. The initial set provides read access only. 


The three APIs provided in the initial set are: 

  • People:get - Get a person's profile - https://www.googleapis.com/plus/v1/people/{userId}
  • Activities:list - List all of the activities in the specified collection for a particular user. We will be using this API for our purpose - https://www.googleapis.com/plus/v1/people/{userId}/activities/{collection}
  • Activities: get - Get an activity - https://www.googleapis.com/plus/v1/activities/{activityId}

The userId referred to in the first two bullets above is not the google id used to login. It is an id which uniquely identifies each resource in Google+. You can find your userId by going to your google+ profile. The numeric text following plus.google.com/ is your userId. The picture below shows my Google+ profile with my userId enclosed in the blue rectangle. 
Picture 5 - Getting userId from Google+ profile
The Process
The overall integration works in the following manner: 
  1. The application passes the client id, redirect URI and requested scope of access to Google OAuth2 URL. 
  2. If the user is not logged into Google, user is presented with the authentication screen. Once the user logs in, the user is presented with a screen to authorize your application to access your data. If the user were already logged into Google, only the authorization screen is presented. 
  3. If the user declines to authorize the access, Google returns an access denied message. 
  4. If the user authorizes the access, Google returns and authorization code to the application. 
  5. The application then passes the code, client id, client secret and redirect URI to the Google OAuth2 token URL. 
  6. Google responds with an access token and a refresh token. 
  7. The application uses the access token and the Google userId to send an HTTP get request to Google+ activities list URL. 
  8. Google+ responds with the last 20 Google+ posts in JSON format. 
  9. Application uses JSONObject.cls to parse the response and find all Google+ posts with hashtag #ch which have not been posted to Chatter. 
  10. Application posts selected Google+ posts to Chatter as user's current status. 

Implementation Details


Integration Settings: The following data elements need to be stored in force.com Custom Settings: Google_Plus_to_Chatter_Settings__c under name 'MySettings':
  • Client ID
  • Client Secret
  • Google Plus User
  • Last Published
Picture 6 - Storing integration settings in Custom Settings
Constants used in the integration  
INTEGRATION_SETTINGS_KEY = 'MySettings';  
GOOGLE_OAUTH_URL_CODE = 'https://accounts.google.com/o/oauth2/auth';  
GOOGLE_OAUTH_URL_TOKEN = 'https://accounts.google.com/o/oauth2/token';  
GOOGLE_API_ACCESS_SCOPE = 'https://www.googleapis.com/auth/plus.me';  
GOOGLE_PLUS_REDIRECT_URI_SUFFIX = '/apex/GooglePlusToChatter';  
GOOGLE_PLUS_POSTINGS_URL = 'https://www.googleapis.com/plus/v1/people/';  

URL to Retrieve Authorization Code
 String url = GOOGLE_OAUTH_URL_CODE  
  + '?client_id=' + integrationSettings.Client_Id__c  
  + '&redirect_uri=' + getInstance() + GOOGLE_PLUS_REDIRECT_URI_SUFFIX   
  + '&scope=' + GOOGLE_API_ACCESS_SCOPE  
  + '&response_type=code'; //Retrieving code  


Code to Retrieve Access Token
 //Using the code, client_id and client_secret, get the access token.   
 HttpRequest req = new HttpRequest();  
 req.setEndpoint(GOOGLE_OAUTH_URL_TOKEN);  
 String postData = 'code=' + EncodingUtil.urlEncode(code, 'UTF-8');  
 postData = postData + '&client_id=' + EncodingUtil.urlEncode(integrationSettings.Client_Id__c, 'UTF-8');  
 postData = postData + '&client_secret=' + EncodingUtil.urlEncode(integrationSettings.Client_Secret__c, 'UTF-8');  
 postData = postData + '&redirect_uri=' + EncodingUtil.urlEncode(getInstance() + GOOGLE_PLUS_REDIRECT_URI_SUFFIX, 'UTF-8');  
 postData = postData + '&grant_type=' + EncodingUtil.urlEncode('authorization_code', 'UTF-8');  

Code to Invoke Google+ API to get Activities
 HttpRequest req = new HttpRequest();  
 req.setEndpoint(GOOGLE_PLUS_POSTINGS_URL   
  + integrationSettings.Google_Plus_User__c   
  + '/activities/public'   
  + '?access_token=' + EncodingUtil.urlEncode(accessToken, 'UTF-8'));  
        req.setMethod('GET');  

Code to parse JSON returned by Google
 String json = res.getBody().replace('\n', '');  
 JSONObject j = new JSONObject( json );  
 totalPostsRetrieved = j.getValue('items').values.size();  
 //Iterate through the post and select the chatter posts  
 for (Integer i = 0; i < totalPostsRetrieved; i++) {  
      //Use this post only if the post timestamp is after the last published timestamp and  
      //if it contains the #ch hashtag  
      datetime googlePlusPostTimestamp = convertGoogleTimestampToDatetime(j.getValue('items').values[i].obj.getString('published'));  
      String googlePlusPost = j.getValue('items').values[i].obj.getValue('object').obj.getString('content');  
      if (googlePlusPostTimestamp > integrationSettings.Last_Published__c && googlePlusPost.contains('#ch')) {  
           postsForChatter.add(googlePlusPost);  
      }  
 }  
 chatterPosts = postsForChatter.size();  
 //Update last published timestamp  
 integrationSettings.Last_Published__c = publishedDatetime;  
 try {  
   upsert(integrationSettings);  
 } catch(System.DMLException e) {  
   ApexPages.Message pageMsg = new ApexPages.Message(ApexPages.Severity.ERROR, 'Error updating last published timestamp: ' + e);  
   ApexPages.addMessage(pageMsg);  
 }  


Code to Post to Chatter
 //On first time page load, 'code' parameter is not set.   
 //'code' parameter is set by Google OAuth 2 on redirection back to this page.    
 if (parms.containsKey('code')) {  
   String accessToken = getAccessToken(parms.get('code'));  
   if (accessToken != null) {       
     List<String> postsForChatter = getGooglePlusPostsForChatter(accessToken);     
     for (String post : postsForChatter) {  
         User user = [select id, CurrentStatus from User where id = :UserInfo.getUserId()];  
         user.CurrentStatus = post;  
         update user;  
     }     
   }  
 }  


Application In Action
Picture 7 - Google+ Before posting new entry
Picture 8 - Chatter Before posting new entry
Picture 9 - Page to invoke Chatter integration

Picture 10 - Added New Post on Google+
Picture 11 - Google Authorization Challenge
Picture 12 - Shows 1 post to Chatter and updated Last Published Date

Picture 13 - Shows Google+ post made to Chatter
Improvement Areas
The following enhancements to this integration are possible:

  1. JSON Parser gives too many scripts exception if the number of posts retrieved is high. This needs to be addressed. 
  2. The retrieval of posts can be automated via a scheduled job. 
  3. The code currently requests new access tokens each time. It does not reuse existing token and on failure retrieve a new access token using refresh token. This can be implemented to make the code more in line with the Google OAuth2 design. 

References

I would appreciate feedback from the readers. I will be posting a short video of the application in action in a few days. For additional information and actual code, please get in touch with me.

      Sep 15, 2011

      Flying in the Cloud

      The last six weeks has been a whirlwind tour of new technology platforms on the cloud. Salesforce, Google Analytics, MailChimp, Amazon SES & Heroku... whew! 

      In the process learnt Salesforce configuration & setup, Apex and visualforce basics, attended Dreamforce 2011 conference @ San Francisco and got my Salesforce developer certification at the conference. Made three crowdsourcing challenge submissions on cloudspokes.com and won one so far. The empowerment of developing on the cloud based platforms as opposed to traditional environments feels good.

      The Dreamforce conference is the first large technology conference I attended in over three years. The energy at the conference was just plain awesome. The learning and exposure to salesforce and related technologies appeared to be better than similar technology conferences.
      The day before the start of Dreamforce 2011 @ Moscone Center
      The last day of the conference - still busy!

      As more and more cloud platforms are made available, the development community needs to understand the nuances of development on the cloud. Things which come to mind are responsive & stable internet connection, platform enforced limitations, platform integration capabilities, source code management, continuous integration, enforced testing and error handling. Add to this the socialization of enterprise applications and mobile client platforms outnumbering the traditional browser based clients, we have at our hands a heady concoction of technologies sure to challenge and satisfy even the geekiest of us all. In summary, I feel transported back 10 years. The difference: Java then and Cloud now.

      So let's Fly in the Clouds - चलो बादलों में उडें|