I’m no psychic but I bet you two things: This holiday you already took a bunch of pictures that went straight into facebook and you drank A LOT. Now you’ll probably edit your photos in the morning, but it seems a shame to lose those drunken shots. What if you could save them? Let’s see how you can do that using Mule. We’ll see how we can make an app that pulls all our facebook photos and upload them into box.
Getting Started On Facebook
So, we’ll need to consume both the facebook API and the Box API. This requires to register new applications on both services, get api keys, etc… I will not go over these topics in this post since they have already been covered previously. There’s a great post by Tom Stroobants about how to set a facebook application and connecting to it using Mule’s Facebook cloud connector. If you are familiar with it you may continue reading, otherwise I suggest to take a look at this post.
Get yourself in the box
As for Box, the process of setting up a Box application and authenticating to it was also covered in this post. Again, you can go ahead if familiar with it, reading is suggested before continuing.
Install the connectors in Studio
Last thing before we begin: You need to install the latest versions of the box and facebook connectors in Mule Studio. They’re available through Studio’s cloud connectors update site. To install simply:
- Open Studio and go to the Help menu -> Install new software
- Select the mule cloud connector update site and check the box and facebook connectors
- Click ok and follow the wizard
Creating the Flow
Let’s first take a look at the complete flow and then let’s analyze each step. Now if your head is still hurting and you want to just skip this for now and cut n’ paste the code you can grab the Mule config here and paste into your flow. Note that you’ll need to add your API keys, so use this template for the file in src/main/mule-app.properties and fill in the blanks with the information above.
Step 1: Listen to others
So, we begin with a simple http inbound endpoint. This is just for starting the process. In this example, this is a request-response endpoint since we’d like to provide the user with a friendly message saying that the synchronization has started. We will elaborate on this on step 2.
Step 2: Don’t keep people waiting
This process requires downloading quite a few photos and then upload them back to Box. This is a process that can take a while and we don’t want to hold up resources by maintaining the http connection alive, and most importantly we don’t want to hold up the user waiting for a response. The <async> processor comes handy for this end. We’ll use it by wrapping the message processors that make for this long running processing. What Mule will do next is to begin execution of those processors in a background thread, while the main thread that is attending the original http call will jump to the next processor that’s not contained into the <async> construct (in this case, it will jump straight to step 9)
Step 3: Know yourself
We begin the cloud party by pulling down your photos. So we go to the Cloud Connectors pallete in Studio and throw in a Facebook component into the flow. Then double click in it and configure the Get User Photos operation as shown in this pic:
A couple of notes on this config:
- This processor sets the message payload to a list of pojos of class com.restfb.types.Photo. Each one of these instances represent a photo on facebook and contain the necessary information to manipulate the photo such as id, source URL, etc., but it does not contain the photo’s byte stream.
- This config actually works! Values like “me”, “last year” and “today” are actually valid on Facebook API and mean exactly what you imagine they mean. How cool is that?!!
- I’m not such a big facebook user so I took a wide range in order to get a lot of pics. Moving forward, you could consider setting the since-until parameters to “yesterday”-“now” and have this flow execute automatically every night… Whatever is the most useful for you
Step 4: You need repeatable routines
Now we need to iterate through this photo collection and download/upload each one of them. The <foreach> processor introduced in Mule 3.3 is just what you need for this. Since the collection to be iterated is placed on the message payload, you can just drag & drop it from the scopes pallete without the need of setting up anything else. What you shouldn’t loose sight of is that just as step 3 and 4 are embedded inside an <async> component, steps 5 to 8 will be embedded inside the <for-each> and thus the payload those message processors are going to receive are one single instance of com.restfb.types.Photo.
Step 5: Call things by their name
Just as in any other storage system, each file in the Box must have a name. Using the goodies of the Mule Expression Language (MEL) also introduced in Mule 3.3, we will easily generate a filename using the photo’s id and we’ll store it into a flow variable. Just go to the transformers pallete, throw in a Variable component and configure it like this:
NOTE: The decision of generating the filename using the photo’s id is merely a simplicity call. You can use whatever criteria you’d like!
Step 6: Go get what you want
As we said before, the Photo object we have only contains information about the photo but not the photo’s bytes. In version 2.0 of the facebook connector we are introducing a new operation called Download Image that provides a Byte of any given image. It is very easy to use, just drop another facebook box on the flow and set it like this:
Step 7: Don’t cross the streams!
The message payload is now the photo’s Byte array. On the other hand, the Box connector needs an InputStream to upload the photo. So, we go to the transformers pallete and drop a Groovy transformer. This transformer will have a very simple configuration that looks like this:
Step 8: Learn to share
Ok, this is it, now it’s time to upload the photo. Go to the cloud connectors pallete, throw a Box component and make it look like this:
Step 9: Always be polite!
So, we are now out of the <for-each> block and also out of the <async> block. However, notice that it wouldn’t be acqurate to say that the execution flow has reached step 9, because as explained before the execution of the <async> flow moved to another thread and the main one moved immediately to this last step. This last processor is just about letting the user know we’re working on his request. We’ll just set the payload to a nice and polite string using the Set Payload component in the transformers pallette like this:
This is when the beauty of the <async> processor manifest itself. The user gets this response before the API request in Step 3 even reaches facebook!
And this is it! A 9 step program to upload your facebook photos to Box. As an example of the end result, here’s a screenshoot from my Box account showing my wife an I getting married. Wait, did anybody say wedding?. Bring in more Alcohol!
- Remember that you need the authentication flows. Again, this is explained in the prior posts referenced at the beginning of this article.
- When configuring the facebook connector, keep in mind that you need to request the “user_photos” and “friends_photos” scopes while doing the OAuth2 authorization.
- For reference, you can download this sample application here. To install, do a git clone and then File-> Import in Mule Studio.
I hope you feel this exited about the simplicity of it as I do. Feel free to reach in if you have any comments or questions.