Wednesday, January 30, 2013

#DifferentSpokes 1/30/13 Recap

For all of those who were unable to view #DifferentSpokes this morning with special guest host Andy Piper, you can watch the recording now. It was a jam packed show with a lot of great questions, and good laughs as usual. Huge thanks to Andy for joining and we definitely hope to have him back on soon.


Also make sure to stop by the Cloud Foundry blog to read their recent post on Node.js, which played perfectly into our discussion theme today.

As for the next one, we will be back in three weeks, on Wednesday February 20th at 8am PST which will feature special guest host Josh Birk from Salesforce.

Monday, January 28, 2013

#DifferentSpokes - With Guest Host Andy Piper from Cloud Foundry!

Hey CloudSpokers! Don't forget that this Wednesday, January 30th at 8am PST is our second #DifferentSpokes.

We will be going through the normal routine again, but also have some very special surprises for you, including our Special Guest Host, Andy Piper of VMware who is joining us to answer all your questions, talk about their recent Node.js blog, and all things Cloud Foundry! It is sure to be a good time, so make sure to tune in. Got questions now?... send em in before the show by tweeting using the hashtag #DifferentSpokes. We will be monitoring the stream and promise to answer all questions posted before the show airs, so it pays to be early!

A quick rundown of the agenda is as follows:
  • Intro
  • Guest Host: Andy Piper from VMware joins us to answer questions and bring some proper english to the hangout table
  • Bowemans Book Club - Kyle runs through "The Node Beginner Book
  • Dr. Douglas Demos - Jeff prescribes a heavy dose of Node.js and Ruby
  • McIlroy's Open Mic - Cory shares his thought of the day
  • Shoot The Spokes - Q&A
  • Wrap Up
For more info on our special guest, Andy Piper, follow him on Twitter

Learn to Write Single Page Web Applications by Competing for Ca$h!

Over the past six months or so single page applications have started to really gain traction. According to TechCrunch, enterprise apps are moving to this single page design. A testiment to this trend is the sheer number of frameworks available including Backbone, Batman, CanJS, Ember, Meteor, Knockout, and Spine.  Google recently threw their hat in the ring with 1.0 release of Angular.js last summer.

We've been a fan of Backbone.js for awhile and have run a number of challenges to build some really cool stuff (see the Backbone.js Kiva loan organizer challenge). Right now we are really excited about Angular.js and Meteor. Anything JavaScript related is extremely popular on CloudSpokes. Our First Time Submitter Challenge for January for Meteor currently has 16 registered members.

So if you are new to single page applications or want to dig a little deeper than a simple "hello world", we want to give you an extra incentive to get your hands dirty writing these type of app. So we've launched two challenges tailored with these goals in mind:

Learn Angular.js or Backbone.js -  A front-end only challenge so that you can focus on the framework without having to worry about persistence.

Build a Simple API with Node.js, Ruby or Java - Complete the round-trip with this challenge and build the API for your application using one of your favorite technologies. We suggest Node.js if you want to stay in JavaScript-land.

So not only do you have a use case for your app but we are offering some prize money for your efforts as well. You have no excuses now. Enjoy and go learn something new.


Guest Blog: "Predicting Migration Times With Google Prediction API" by Eugenio Cuevas Pozuelo

Guest Blogger: Eugenio Cuevas Pozuelo

A Java developer hailing from Valencia Spain, Eugenio Cuevas Pozuelo aka eucuepo, has been a staple as of late in the CloudSpokes community. Rising up through the 2013 leaderboards and making quite a name for himself, eucuepo has won many recent challenges, especially the GAMME ones, which he offered to guest blog about! When he isn't writing awesome code, or guest blogs, he enjoys going on runs (he just completed his first half marathon) and taking pictures with his DSLR. You can also head over to his personal blog to see more great posts.

The Challenge:
After a series of challenges on the GAMME Estimation tool, I decided to do a blog post proudly showing my development, but when the CloudSpokes team told me I could do a guest post, I took it even more seriously! When I came across the GAMME Estimation contest, I had recently won my first challenge and I was just getting used to this awesome community. So, I read the description and started to do a proof of concept with the Google Prediction API. This API is awesome, as it works by “learning” samples and then predicting a result for given data. For a guy that has the sad record of failing an easy statistics course five times in college, this is gold! It can be really abstract, really complex statistics “under the hood” and let the developers focus on the functionality required for the app.

Diving In:
The challenge was to get an accurate estimate for the migration time of the GAMME tool, an app developed by Google to migrate from Outlook servers to Gmail, up in the clouds. The logs were provided with some sample data on the migration.

I started with a proof of concept with the prediction API, they provide some cool examples that can be used for free. After crafting a CSV from the challenge assets, I got successful results, so I dove into the coding!

I went with Google App Engine for the development, because it provides seamless access to the Google APIs, and this project is using three, Cloud Storage, Google Drive and of course, the Prediction API. Looking into the past, I think I wouldn’t chose it again, because of some constraints of the project, like the 60 second limit for requests, or the limited java classes usage allowed in the Java Whitelist, but I still think it is a great platform to develop in.

For the frontend I used Twitter Bootstrap, which I am a huge fan of (who isn't?), for its general awesomeness. I imagine this app being run by a consultant in front of the client prior to a migration, perhaps on a tablet, so its responsive design makes it also cool to run on a portable device. This is how it looks on iPad:


Nostra Gamme:
The initial task was simply to upload the CSV via upload to Google Drive, then trigger the prediction with the data provided. It should be able to predict the time spent migrating, depending on the server and thread numbers, for the number of emails, contacts and calendars given. It will also predict the other way around, it will give the number of servers required to migrate in a determinate time span. To achieve this, two groups of prediction models were created from the original data, as the output for the prediction changes. I thought it would be cool to visually display the data, so I added jqPlot, which is great, although a little tricky sometimes. Here is a screenshot of the first version:


The Great Refinement:
After some positive feedback from the judges, a follow-up contest was launched to make some enhancements. I really enjoyed doing the original one, so this was a possibility to do some enhancements of my own. The requirements were to add client maintenance to manage several models per client. That gave me the possibility to learn (and fight against) the App Engine Datastore. I am a traditional SQL guy, but the Google approach to store data has its advantages, as it is declarative and incredibly fast!

I thought it would be cool to expose some functionality to add the clients, so I added an Ajax-based maintenance, which works with a REST API so it could be called from a client program. This is a screenshot of the frontend:


Fully Entering The Clouds:
I was happy to know there was another challenge open for GAMME prediction, to polish it a bit more. An average calculation was added to compare it with the one given to the prediction API, to have a reference and have a better understanding of the data provided. It also pushed into the clouds the client program extracting the logs from GAMME, which rounded it up to be a fully cloud development! Here is a screenshot of the prediction for the final app:


I would like to thank all Cloudspokes team for the feedback during the development. You rock guys! Keep these cool challenges coming!

- eucuepo

Friday, January 25, 2013

CloudSpokes, A Heroku Case Study

If you missed the latest Heroku newsletter, then you likely missed the most recent partner spotlight:


That's right - CloudSpokes was the featured case study. Most importantly, the feature was largely around the work performed by the CloudSpokes community in migrating our old platform over to database.com and Heroku. To read up on the phenomenal amount of work performed by the CloudSpokes members to build the new CloudSpokes framework, check out our blog announcement on the new platform.

Last but not least, definitely check out the full Heroku Case Study on CloudSpokes. As a teaser, here are some of the noteworthy quotes from our very own Jeff Douglas:
  • "We need a true platform-as-a-service. We need a platform that facilitates daily deployments and that can respond to an agile development process without DBA and a team of developers", says Douglas. "Our 70,000 community members want features and expect a quick turnaround on our development cycles, just as we expect the same from them on our CloudSpokes development challenges. We quickly realized that we needed Heroku."
  • "One of the reasons we went with Heroku was the time we could get code out," says Douglas. "For example, early on we received feedback from one of our top members that our commenting process was difficult enough to negatively affect participation. We added this to our sprint planning and since it was an easy fix we had the process updated within days. This is a small example, but it's key to the health of our community to be able to respond in real-time to requests and bugs like these. Heroku gives us exactly the response time we require." [For reference, here was PaulKolbovich's excellent idea that we implemented].

Tuesday, January 22, 2013

JavaScript Workflow & Process Diagram Winners!

Diagrams, charts, workflows...they're all kinda boring, and not always very user friendly. But oh how they are necessary! Now, we have spent the past couple of months building a Rules Engine for Salesforce.com, and we needed a JavaScript application that generated Visio-Like diagrams for the rules that provided a visual representation of what they do.

It took some of the communities best JavaScript ninjas, to do so but we did it! We even did it with a couple of extra winners because there were so many #radtacular submissions. One of the best parts about this challenge is that it was JavaScript only, so you didn't even need any Salesforce.com knowledge to compete.

First place for this challenge comes to us via iCare, who just joined three weeks ago and has since put two first place wins in the bag! January Member Of The Month Enreeco, came in second continuing his tear through the leaderboards, followed up by long time CloudSpoker chok68 and new comer sonu12 rounding out the winning crew.

Check out the demo videos for each winner below and don't forget to read "The Node Beginner Book" By Manuel Kiessling for our next #DifferentSpokes Member Hangout on Wednesday January 30th, at 8amPST.

iCare
Place: 1
Money: $500
Enreeco
Place: 2
Money: $250
chok68
Place: 3
Money: $150
sonu12
Place: 3
Money: $150

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.

Friday, January 18, 2013

Reblog: A Call To All Students - Get On CloudSpokes Now! by Romin

Yesterday, one of our members, Romin, wrote a very flattering and eloquent post. It was a call to college students across the globe to use CloudSpokes as a marketplace for all the tools needed to grow as a professional, as well as how fantastic the CloudSpokes community is in general (insert us blushing here).

We certainly strive to have CloudSpokes be everything Romin says it is, and are most definitely ecstatic that he chose to write these thoughts down. Check out Romin's guest piece below and cruise over to his blog for more great posts:

A Call To All Students - Get On CloudSpokes Now!

Last week, I spent 2 days with the students of BITS Pilani, Goa and I am still energized by my interaction with them. The kind of stuff that they are able to learn and demonstrate is happening in “Internet time”, so to speak. For those of them who wanted to take the plunge into software development as a career, I started thinking what I could put down to get them building solid skills.

In this blog post, I want to talk about CloudSpokes and how it can possibly make all you students not just better programmers but teach you so many other things, if you want to be ready for the Software Industry when you graduate.

cloudspokes

An introduction to CloudSpokes is due first. I take the liberty of taking the definition from their website itself : “An independent crowdsourcing development community and marketplace that matches companies who need cloud development work with a worldwide community of cloud experts. The focus for CloudSpokes is solely on using public cloud platforms to build and deliver enterprise-class solutions.”

The words highlighted in bold are key ones. First up is that all the work is around public cloud platforms, ones that are available to all of us either for free (to try out) and then with a “pay as you use” policy. Key platforms from Google, Amazon, SalesForce, Heroku, CloudFoundry and others come in this category. Crowdsourcing over here can be loosely termed as telling all the developers (Cloudspokers) that here is a problem and let me know who comes up with the best possible solution within the given time frame. It is a marketplace because organizations come to Cloudspokes with what they want to build and Cloudspokes puts them up as “challenges” or “contests” which you can do. And best of all, no one cares where you live. Years back I remember the “Got Milk?” advertisements. I am pretty sure it can be substituted now with “Got Cloud Skills?”.

In short, you look at the various challenges. Pick any of them up. Deliver a solution as per the requirements and then hope to win. Don’t know how to proceed, ask a question in the challenge Q&A and you get enough pointers on references to get you started. A laptop, an Internet connection and a will to learn… those are the magic ingredients needed to qualify for CloudSpokes.

And here is why I think you need to take this seriously. The points below are the ones that I feel will get you ready to work as a software programmer in most places, even before you have graduated. And who knows, by participating in the challenges for months, it will trigger ideas in you that should be enough for you to even consider exploring on your own. The possibilities are endless.

So here we go:

Learn New Skills

A career in programming is unique in many respects. The only constant in this career is learning new stuff on a daily basis. The languages, frameworks, components that we know today are the ones which are replaced by newer (if not better) versions. If you have been reading articles around necessary skills needed by a programmer today, one word in all those articles will stand out. And the word is polyglot. The word has its roots in ancient Greece (well, what doesn’t ! ) and it means ‘many tongues’. An official definition of the word says “Speaking, writing, written in, or composed of several languages.” This is precisely what you need to be in order to succeed. Do not get into the debate of which language / framework is better. The creators (may their tribe increase!) of these frameworks saw a problem not addressed by their current set of tools and went about setting it right. So pick up new languages and frameworks. Each of them have gems that will broaden your skills and ability to address unique situations as you program more systems. The first language or two that you pick up will always be at the back of your mind as you spend years in the industry but do not limit yourself to that.

What has this got to do with CloudSpokes? Well, the challenges at CloudSpokes are across the spectrum. Client / Server languages, various frameworks … you have it all. Learn them, try the challenges. That is the best way to learn these.

Competition

Competition is important for all of us. Without that, we will not push the limits of our capabilities. CloudSpokes has some terrific contestants and by pitting yourself against the most committed of developers (who all want to learn and win) will harden you for the battles that come ahead in your programming journey. I have taken part in a handful of these contests and when I see the videos of folks who beat me, I had to put my hand up and say “Man ! This submission by XYZ rocks.” And I don’t even want to remind you of the major boost to your confidence, when you win a challenge. You are being judged by seasoned pros and getting that confirmation from them will do your confidence wonders. Trust me on that one. You have nothing to lose really. Any submission you make means an attempt made, an effort put in and submission uploaded. Those are signs of a winner to me.

Time Management

Software projects are fun to work on. We are in a fairly nascent industry and a favorite remark heaped on software projects is that they are usually late. The reasons for that are many : incomplete/changing requirements, resource issues, lack of skills … the list goes on and on. So one of the things that you need to get used while working in this industry is delivering under time pressure. There will always be less time on your hands, no matter what you do.

Each of the CloudSpokes challenges has a time deadline in which you are told to submit your solution. By deadline, it meets that you will be given 5 days or 10 days or whatever, by which to submit your solution. If you want to complete the challenge and do a great job, then you will have to do it within the time stipulated, no other ways about it. Over time, you will know your capacity and how to break up your work into smaller tasks so that you are within the deadline. Time waits for no man and definitely not for software deadlines. So getting under time pressure here at this stage of your life to complete a technical assignment will stand you in good stead moving forward.

Earn money

CloudSpokes rewards the winners for their efforts. Each challenge has multiple winners, who win some prize money or the other. The prize money is important because you can use it in ways to become better. How about putting some of that back to take an online course for learning a new technology? You have tons of Online universities now that offer technology courses. You could buy a new laptop or if you were me, you can bootstrap a training and small consulting firm. Look at the top 3 prize money winners on the CloudSpokes home page, that is no mean achievement. It is serious money. People have bootstrapped successful companies with that kind of cash. Think about it !

Meet Developers

When you take part in CloudSpokes contests, you will come across Developers in the challenge. Common interests bring all of us together to CloudSpokes, so why not know more about each other. Search them up on the Internet, follow them on Twitter. Open up conversations with them, it can lead to things that you could never imagine. Some of my interactions with fellow participants have been extremely positive. Interact with the CloudSpokes managers too. Extremely friendly and very knowledgeable. They have such a wealth of knowledge that just interacting with them introduces you to some new thing or the other in our fast paced developer ecosystem. And which could save you hours of research.

Community Participation

Programmers are often called introverts but I have seen many of us open up considerably when technology is being discussed. The Open Source movement has been a game changer for all of us. It is all about the community. You must participate. You must download and use stuff. You must give back, in whichever small way. Maybe via a bug fix, a documentation page, even a project but learn to give back. We learn more and faster by sharing and supporting.

At CloudSpokes, you could help out in many ways. If you feel requirements are not clear, tell them that. If participants ask questions about clarifications and you happen to know the answers, go ahead and share those points. If you win a few contests in a particular area, you could even be a judge on them. The more you participate, the more you will become better at playing a leading role in the community. And like any great community, changes happen bit by bit, every day by everyone and over a period of time, something wonderful is born out of that. So participate.

By the way, if you still feel that you are a really “quiet” person and are not cut out for this community stuff, maybe joining the Quiet Revolution might help?

Documentation

This is an area that is detested by most programmers that I have encountered. The funny part is that they are usually the first to complain when they read a badly written user help page. Documentation is a critical skill to have and if there is a component, framework or application that you have spent hours of your life on, give it some love and make sure that you describe and write about it in a manner that makes people want to use it. Remember, we live in an Internet age where people have shorter attention spans and won’t give you a second chance. It is brutal out there. So when it comes to documentation, we have enough successful examples out there to learn from. Keep in mind stuff like “Quick Start” that will cater to anyone who wants to get going with your software in the shortest possible time.

When you submit your entry to any CloudSpokes contest, you need to provide instructions on how to setup, compile, run, etc your code. The judges have limited time and they have other great entries to judge too. So one way to shine out is to give detailed documentation to make their task easier. In other words, by submitting multiple entries and analyzing the documentation that you sent across, you will know inside of you what you should have done to make it better. Listen to that voice and keep working on it.

In a recent survey conducted by ProgrammableWeb, the leading directory of public APIs, developers (like you and me) were unanimous that providing good documentation is among the most important features that they consider while evaluating any product. Don’t believe me .. please don’t. Instead, ask yourself honestly and you will never again ignore writing good documentation.

Presentation Skills

Closing out a sale is as much about presentation as it is about the real stuff. And by presentation, I do not mean creating empty slides that don’t have anything behind to support it. I am talking about video here, which is fast becoming the way people describe anything. Complete user guides are getting replaced with instructive videos. Learn using this medium, it can be powerful. If you feel that you are not cut off for writing thousands of words, remember the old adage that “A picture is worth a thousand words”. Maybe a video is worth a million.

When you submit your entry to CloudSpokes, one of the optional things to submit is a video. Do yourself one little favor: make that mandatory, not optional as far as you are concerned. Create a video, hear your own voice (it can sound funny at times!) , learn video recording tools, edit it as needed and before you realize you will have a powerful way to describe anything.

Ready to Hire Profile

It is 2013 now and your Microsoft Word resume is not going to cut it anymore. Every company wants to hire the best possible programmers and they tune their hiring process to find candidates who could best fit into their current openings. Do not be under any false impression, that they will hire you because you can be woken up from your sleep at 4AM and you can still write a complicated recursive function. That could be just one criteria. Some of the previous points like support work, presentation skills, community stuff could very well turn the tide in your favor. In spite of their best efforts, organizations have a tough time hiring the right resources. The best developers are courted, they are not hired. And you must do your bit to be in the former category.

Here is what I want to say. Your resume in 2013 has to be a “Browser Search”. That’s all you need to do and you will find that the companies will search you and get to you. But for that, you have to put in the efforts , build your skills, win some challenges, write some blog posts, post your projects on Github, earn some good karma on StackOverflow and so on.

You must have an online profile. Don’t have a domain name? Get One. Don’t have a web site / blog ? Get One. Start Blogging. Don’t know what to blog? Write about what you did today. Or hop over to Stack Overflow and answer some questions, if that is your style. There are various ways in which you can leave behind your online traces. Just make a start, the rest as they say will take care of itself.

Conclusion

I am sure there are other high level points but this should be enough to inspire you to get started today. Time is short and trust me when I say that 5 years later when you do a rewind, this simple decision of yours to be ready to learn new things in 2013 should be among the stand-out decisions that you took. I do not have the gambling instinct, but I would still bet on it.

Thanks for taking your valuable time to read this. All the Best. You folks are the future superstars and I am lucky enough to share what I feel would be in your best interests.

P.S: While my article is a call to current undergraduate students, it applies equally well to anyone interested in a programming career, experienced or even otherwise.

Tuesday, January 15, 2013

January CloudSpokes Platform Update

Last week we had our first #DifferentSpokes Member's Hangout and I talked about some of the recent and upcoming changes were are making to CloudSpokes. If you weren't able to attend, here's a recap of some of the new and upcoming features for the site.

Community Judging
We kicked off Community Judging in early December where members can judge challenges in which they do not participate. Members that have won at least three challenges can sign up to judge available challenges and be compensated per submission judged. The program is going well and we plan on implementing a certification process in order to judge certain types of challenges.

Referral Program
Late last month we announced our referral program where you can win some serious cash for referring your friends to CloudSpokes! When you refer someone you get 10% of all their winnings in their first year as a member! Now, you can win money, even if you don't win the challenge! So if a friend wins $1000 in a coding challenge, we'll give you an additional $100. Each member has their own unique referral URL plus we have a handy-dandy form for sending out invites for you. You can also track your referred members and see how well they are doing.

Private Messages
Late last year we ran a number of challenges to design and build a "notification service" that allows members to configure the notifications that they receive from CloudSpokes. We recently rolled out the first iteration of this service that allows members to send private messages to one another. Stay tuned as we'll be adding a preferences UI and more notifications.

New CloudSpokes.com Website
A new Cloudspokes.com website is in the works and should be done within a couple of months! We've launched a number of challenges to build out a new Rails site with our new API and the graphics team is working on the front end. We'll have a new scoring engine, a new dynamic requirements and scoring process, a much improved submission interface and even automated testing of submitted code. Plan on seeing more blogs post shortly about the new site.

Wednesday, January 9, 2013

#DifferentSpokes Recap

Earlier this morning we aired our first Member Hangout of the year, called #DifferentSpokes. If you weren't able to sit in on the live broadcast, don't worry...we got you covered!

You can see the recording of the show below, or head over to content.cloudspokes.com/different-spokes, which will be the home for the live broadcasts all year long as well an archive of the shows as we move forward.

Our next show will air live on Wednesday, January 30th, at 8am PST. For that show, make sure to have read "The Node Beginner Book" by Manuel Kiessling, as it will be the featured book for our segment "Bowerman's Book Club". The book is available on Amazon here and in a bundle pack here.

In the meantime, if you have any questions about today's show, or about the next one, send them in via Twitter using the hashtag #DifferentSpokes. We will save the questions in a queue to be answered live during our next Hangout.

See you next time!

Reblog: POST Multipart/form-data with HttpRequest by Enreeco

When you have a community of over 70,000 cloud experts, you are bound to have copious amounts of awesome members who have their own blogs. And every once in a while, we are blown away by said blogs. Today is one of those days.

This blog comes to us via Enreeco, who in the past few months has been tearing through the ranks, and is even our January Member of the Month!

Without further ado, check out Enreeco's killer blog post below, (inspired by a CloudSpokes challenge of course!) Also make sure to head over to Enreeco's blog to see even more great posts.

[Salesforce / Apex] POST Mutipart/form-data with HttpRequest

Grandma says you cannot post a Mutipart/form-data using an HttpRequest in APEX?
Well, if she says this now you can tell her this is no more true!

All comes from a CloudSpokes challenge (here is the link)...at the time of starting the challenge I was absolutely sure I would have ended up the challenge in less than a day: http gets/posts  are not a big problem in APEX...well so it seemed.

To complete the challenge you had to make 4 REST calls (login, book a new upload, upload the file, set permissions): during testing the last step always failed.

This was the first time I jumped in front of this issue.

If you don't want to know what I did, go directly here.
The first thing I noted was that you cannot send a base64 encoded file to a server expecting a binary file...It wans't that obvious to me, because I've never struggled with file encoding.

The first code was something like this:
01public static HTTPResponse uploadFile(Attachmnet file)
02 {
03  String boundary = '__boundary__xxx';
04  String header = '--'+boundary+'\n';
05     'Content-Disposition: form-data; name="data"; filename="'+file.name
06     +'"\nContent-Type: application/octet-stream\n\n';
07
08  String footer = '\n--'+boundary+'--';
09   
10  String body = EncodingUtil.base64Encode(file.Body); //encodes the blob into a base64 encoded String
11   
12  body = header + body + footer;
13   
14  HttpRequest req = new HttpRequest();
15  req.setHeader('Content-Type','multipart/form-data; boundary='+boundary);
16  req.setMethod('POST');
17  req.setEndpoint('http://posttestserver.com/post.php?dir=what_a_wonderful_post');   //COOL site to test form uploads
18  req.setBody(body);
19  req.setTimeout(60000);
20  req.setHeader('Content-Length',String.valueof(body.length()));
21   
22  Http http = new Http();
23      return http.send(req);
24 }

Then I was all "Eureka! An encoded string cannot be understood if the server needs a binary", so the only thing to do is to make a concatenation of header + file.Body.toString() + footer! This worksonly if the Blob comes from a text file (i.e. TXT, XML or CSV files): in these cases you don't have any problem...but with binary data all you have is the error:

Blob is not a valid UTF-8 string

I had to find another way.

Searching the web for "uploading binary data using apex" I found those bad links:
  • http://success.salesforce.com/ideaView?id=08730000000Kr80AAC
  • http://boards.developerforce.com/t5/Apex-Code-Development/Image-upload-using-multipart-form-data/td-p/243335
  • http://boards.developerforce.com/t5/Apex-Code-Development/sending-a-non-ascii-file-via-Http-POST/td-p/116662

That leaded to the block of comments you can see in the challenge's dashboard.

I didn't give up anyway. I had all data needed to send the request so I knew the solution was out there.

First thing was to understand if there was a way to merge Blobs types: it is not possible in APEX if you don't have the original data (in that case you use String concatenation or List of Integers concatenation, if you have bynary data in form of intergers list).
So I came up with the idea to merge header, body and footer using base64 encoded version, something like this:

1String encoded = EncodingUtil.base64Encode(Blob.valueOf(header))
+EncodingUtil.base64Encode(file.Body)+EncodingUtil.base64Encode
(Blob.valueOf(footer));
2 req.setBodyAsBlob(EncodingUtil.base64Decode(encoded));

I found that sometimes it worked (after a bit I understood that that times I was extremely lucky!!).

Debugging and searching the web (see this post for example) I came to know that a base64 encoded String could have padding characters because the base64 encoding is done using chunks of 3 bytes (see Google for details), and if data is not multiple of 3 bytes this padding in needed.

So I decided to remove the trailing "=" from each encoded chunck of the body request and paste them together. But it's not the proper way to play with encoded base64 strings, as removing trailing padding needs a reencoding of the original data.

The idea was to remove in some way, without messing with the encoded strings, all trailing padding "=".

For the header string it was simple, because it was simple text and I could have added some blank spaces to get an encoded string without "=". That's:

01String boundary = '__boundary__xxx';
02String header = '--'+boundary+'\n';
03   'Content-Disposition: form-data; name="data"; filename="'+file.name
04   +'"\nContent-Type: application/octet-stream';
05
06String headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'\n\n'));
07//this ensures no trailing "=" padding
08while(headerEncoded.endsWith('='))
09{
10 header+=' ';
11 headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'\n\n'));
12}

So in practice I add extra spaces before the "\n\n" ending characters till I have an encoded string without padding.

The Blob file is the main problem. I need the unencoded data to get the needed trailing, so I need a String value of the body: even if with that String how can I change the file to avoid the "=" ? As this data can be anything (form txt files to encoded zips), it is not so simple to add some padding character to avoid the "=" padding (not clear I know)...

If the encoded body doesn't contain any trailing "=", now the problem is over, the sum of the encoded header, body and footer works.

The problem is the last 4 bytes of the encoded body. That is from the 0th byte to the N-4th byte of the file I have no problem, becase it is an encoded version without "=" trailing.

How do I encode those last 4 bytes merging them with the footer?

I discovered that the HttpRequest class has a strange behavior: the setBodyAsBlob() and getBody() are complementary for the use I need. That is the following code doens't throw a "Blob is not a valid UTF-8 string" exception:

1Blob body = file.body;
2HttpRequest tmp = new HttpRequest();
3tmp.setBodyAsBlob(body);
4String bodyString = tmp.getBody();
5System.debug('## Output body:'+bodyString );

The result is a messing sequence of characters. Are they properly encoded? Yes they are, this is a kind of test:

1Blob decoded4Bytes = EncodingUtil.base64Decode('AA==');
2System.debug('FIRST ENCODING: '+EncodingUtil.base64Encode(decoded4Bytes));
3HttpRequest tmp = new HttpRequest();
4tmp.setBodyAsBlob(decoded4Bytes);
5System.debug('LAST ENCODING: '+EncodingUtil.base64Encode(tmp.getBodyAsBlob()));

Using different kind of random encoded data (other that "AA==") the results of encoding, blobbing, httpRequesting (??!!), is always the same.
This is what i needed:

  1. decode the last 4 bytes in blob
  2. append it into an HttpRequest using the "setBodyAsBlob()"
  3. get the body as string with "getBody()"
  4. merge this string with the footer
  5. base64 encode the resulting string
  6. merge the base64 encoding of header, file body (from 0 to N-4th byte), previous merged string
  7. base64 unencoding the resulting string
  8. here you are the Blob you needed!
This is the resulting code:

01public static HTTPResponse uploadFile(Attachmnet file)
02{
03  String boundary = '__boundary__xxx';
04  String header = '--'+boundary+'\n';
05  body += 'Content-Disposition: form-data; name="data"; filename="'+file.name
06    +'"\nContent-Type: application/octet-stream';
07
08  String footer = '\n--'+boundary+'--';
09   
10  // no trailing padding on header by adding ' ' before the last "\n\n" characters
11  String headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'\n\n'));
12  //this ensures no trailing "=" padding
13  while(headerEncoded.endsWith('='))
14  {
15   header+=' ';
16   headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'\n\n'));
17  }
18  //base64 encoded body
19  String bodyEncoded = EncodingUtil.base64Encode(file.body);
20  //base64 encoded footer
21  String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
22   
23  Blob bodyBlob = null;
24  //last encoded body bytes
25  String last4Bytes = bodyEncoded.substring(bodyEncoded.length()-4,bodyEncoded.length());
26  //if the last 4 bytes encoded base64 ends with the padding character (= or ==) then re-encode those bytes with the footer
27  //to ensure the padding is added only at the end of the body
28  if(last4Bytes.endsWith('='))
29  {
30   Blob decoded4Bytes = EncodingUtil.base64Decode(last4Bytes);
31   HttpRequest tmp = new HttpRequest();
32   tmp.setBodyAsBlob(decoded4Bytes);
33   String last4BytesFooter = tmp.getBody()+footer;  
34   bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded.substring
(0,bodyEncoded.length()-4)+EncodingUtil.base64Encode
(Blob.valueOf(last4BytesFooter)));
35  }
36  else
37  {
38   bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
39  }
40   
41  if(bodyBlob.size()>3000000)
42  {
43   //this a "public class CustomException extends Exception{}"
44   throw new CustomException('File size limit is 3 MBytes');
45  }
46   
47  HttpRequest req = new HttpRequest();
48  req.setHeader('Content-Type','multipart/form-data; boundary='+boundary);
49  req.setMethod('POST');
51  req.setBodyAsBlob(bodyBlob);
52  req.setTimeout(60000);
53  req.setHeader('Content-Length',String.valueof(req.getBodyAsBlob().size()));
54  Http http = new Http();
55  HTTPResponse res = http.send(req);
56  return res;
57}

I tested it with different kind of files, dimensions and it always worked. I'd like to know your thoughts.
See ya!