Monday, January 21, 2013

Guest Blog: "Constantly Learning With CloudSpokes" by José Luis Almazán

Guest Blogger: José Luis Almazán

With a new year comes a new wave of CloudSpokers climbing up through the leaderboards and making a splash. While José, aka almopeluche has been a member for almost a year and built a very nice resume for himself, we have a feeling 2013 is going to be his breakout year. He is already stacking up nicely in the "Top Winners This Year" leaderboard including a hefty win for the Upload Documents to WatchDox from Salesforce challenge which led to him volunteering to author a guest blog, and us immediately accepting! For more great pieces by José check out his personal blog here!

Hi all from Spain.

My name is José Luis Almazán (aka almopeluche), I'm 42 years old and I'm the father of two beautiful children. I'm Aeronautical Technical Engineer, but my true passion is developing. Many years ago I left the aircrafts, to devote myself to what I like, developing applications. I've developed in .NET and SQL for over 10 years, I've done everything, applications and web services, desktop applications, windows services ... but since I learned Salesforce 4 years ago, I've only developed on Force.com. I currently work freelance from home, and I can say that my work is my hobby. I truly enjoy doing what I do.

I became a member of CloudSpokes about a year ago, by chance one day just surfing the internet. I thought crowdsourcing seemed like a very good idea, so I decided to sign up! My first challenge was Salesforce Mashup with jQuery and Google Maps. I didn't win anything, but it helped me learn a lot and to improve in many aspects. That challenge resulted in me needing to continue learning, of course in the little free time I have (which between my job and my family, is very little). I've submitted in 15 challenges and I have won in 10 of them. One of the things I like about CloudSpokes, is that every challenge is different, and in every challenge you have to give everything you have and more, to keep growing. I can say that I learned in this past year more than in years previous, not participating on CloudSpokes. CloudSpokes requires you to outdo yourself every day, and in every challenge. I must too say that CloudSpokes has extremely good members in the community, which makes for very difficult competition, because the level of their work is so high! Members like talesforcekenji776logontokartikwcheungavidev9Romin and many others challenge me to always push my limits.

The last challenge I participated in, and which I was first prize winner, was Upload Documents to WatchDox from Salesforce. I must say that this was the most complex challenge I've done so far! WatchDox enables organizations to access, share and control their critical documents wherever they go: on any tablet, smartphone, or PC, even those beyond the IT department’s control.

Due to the high level of competition in the challenges, I typically perform some additional functionality to excel and rise above my opponents. In this challenge, the extra features that I did were the power to upload multiple files to WatchDox at the same time (no limit on the number of files), drag and drop files, progress bar for each file, which indicated in each moment the upload state, management and display any errors that may occur, use custom settings to store access credentials to WatchDox and other basic options, compatibility with all browsers, etc...


From here I thank Jason Venable (TehNrd) by his code that served me as a starting point Multi File Uploader for Force.com, and which I have adapted and improved for this challenge. Most of these features are activated only in browsers that support HTML5.


The main problem that I found was poor documentation of integration with WatchDox, which made this a complex challenge. Especially because according to the documentation, the only way to upload a document using the WatchDox API was doing a POST with Mutipart/form-data to the endpoint URL /rooms/{roomId}/documents/{documentGuid}/upload, passing the file contents in binary form, as it is the only thing that supports this endpoint. Well I didn't think APEX could do that, until I saw that Enreeco, my opponent, had found a brilliant solution to this problem, which can be seen on his blog. In the end however, I found another solution. Rather than the endpoint URL above, I had to make the POST to this new endpoint URL/rooms/{roomId}/documents/{documentGuid}/uploadBase64, in this case this endpoint supports files encoded in base64. My code to upload files encoded in base64 is as follows:

public static HTTPResponse uploadFile(String fileName, Blob fileBody, String contentType){

    // Body
    String boundary = String.valueOf(DateTime.now().getTime());
    String body = '------------' + boundary + '\r\n';
    body+='Content-Disposition: form-data; name="data"; filename="' + fileName + '"\r\n';
    body+='Content-Transfer-Encoding: base64\r\n';
    if ((contentType == null) || (contentType == '')){contentType = 'application/octet-stream';}
    body+='Content-Type: ' + contentType + '\r\n\r\n';
    body+=EncodingUtil.base64Encode(fileBody);
    body+='\r\n------------' + boundary + '--';

    // Instantiate a new HTTP request, specify the method (POST) as well as the endpoint
    HttpRequest req = new HttpRequest();

    // Set headers
    req.setHeader('Content-Type', 'multipart/form-data; boundary=----------' + boundary);
    req.setHeader('Content-Length',String.valueof(body.length()));

    // Set body
    req.setBody(body);

    // Set method and endpoint
    req.setMethod('POST');
    req.setEndpoint('http://www.TuServidorExterno.com');

    // Send HTTP request and get HTTP response
    Http http = new Http();
    return(http.send(req));
}

Strangely, this is the key to this challenge, as well as the many headaches given to us who participated on this challenge! This is a key case for improvement and struggle to find a solution, when it seemed that it was impossible. Of course, I find more optimal the solution created by Enreeco, ie send a document in binary form, instead of sending a document encoded in base64, as we know which occupies approximately 30% more than in its binary form. This of course means that the size of files you can upload encoded in base64 is less than if sent in binary format, taking into account the limit imposed by Salesforce of 3MB (due to Callout Governor Limits, file size is limited to 3MB).

Another problem I had to suffer through in this challenge was that the WatchDox demo server had some errors. For example, not processed text files, and caused an error with the upload of the same. But until I knew it was a mistake of WatchDox, the headache it caused me was very big ;-).

You can see the video of my presentation (no audio, only video) on youtube. You can also check my blog in Spanish, which I started recently. I must say that there are very few blogs in Spanish on Salesforce, so I try to add my two cents.

Regards to the team of CloudSpokes that allows me to continue learning in each challenge. And of course, regards to all the members of this community.

P.S.: I recognize that the English language is a barrier for me, but that does not stop me doing challenges, and it shouldn't stop you either!

José Luis Almazán.

No comments:

Post a Comment