Páginas

2011-10-13

Fuck off death reaper! Dennis Ritchie too?!

Despite the commotion about Jobs’s death, many probably don’t know about the death of Dennis Ritchie (even that being in second on Twitter Worldwide Trend Topics while I was writing this post). Yeah, who the hell is Dennis Ritchie? I had no idea either, but his legacy is much bigger than Jobs’s.

What?! Wait a minute! How so someone I’ve never heard about is more important than Steve Jobs? That is the difference to real geniuses: their legacy is even greater than their fame. Dennis Ritchie was the designer and developer of C language, not that would be enough mind-blowing he also co-created Unix.
It’s like Newton’s famous quote: “If I have seen further it is by standing on the shoulders of giants”. I am not going to talk how internet, iOS and basically everything on IT relays in C, Unix or their legacy. But despite everything that other created, designed and built for Jobs to sell, Ritchie made things himself.
It is so sad people who worked in the greatest revolution of mankind are passing away. What are we going to do with all the transformation and power they gave us? I am going to finish this drop with much more philosofical statement than the usual “That is all for now. Until next post, with more drops of logs from a Computer Scientist’s life”:
Fame is not important. Let’s be ready to change the world and stay anonymous.

[+/-] show/hide

2011-10-05

[drops.log]: Life follows...

I was thinking in to entitle this post as “Apple loses jobs even no one was fired”. But I guess the main thing here is: life follows.Steve Jobs passed away but that means little. Better products weren’t going to stop of show up. Apple is not going to die tomorrow.

I don’t get the commotion. What really hit me was random black humor phrases like:
“Who would like to trade Apple stocks?”.
“I guess we don’t need to study iOS API anymore.”
“Jobs has just released his newest innovation, the iDead” (that was kinda obvious, but I didn’t read on Twitter).
“Is Apple going to put Jobs funeral tickets in the iTunes?”.
“Finally a really nice work spot opened in Silicon Valey”.
“Jobs is uncontrollable, even iDead he has already done millions purchase his final product: iSad”.
“Apple says: we don’t have enough e-mail addresses to spam, send yours to rememberingsteve@apple.com”.
My acquintaces came up some funny stuff too, but I am not going to copy them here.
I would also recommend watch Pirates of Silicon Valley and tweet to keep iDead in the Twitter Trend Topics for one more day at least. That is all for now. Until next post, with more drops of logs from a Computer Scientist’s life.

[+/-] show/hide

2011-09-30

[drops.log]: An inverse path, from photo to album

Wow! I’ve been absent since last week. My logs didn’t increase much in the while. I keep groping the Facebook Graph API with the restFB java wrapper.

It is easy to get the photos from a album. This post is about the inverse. The current task is to find what album a photo belongs. Let me put some context. Imagine you are using the Facebook Real-time Updates API to read feed and get every time user share/post something. Sometimes it is a new album. But when the feed is fired up with a new album you get only the cover photo from the album.
So now I need to check out what album holds that picture to iterate in it and do my app job. I read a comment in the StackOverflow saying the old REST API covered that easily, but the current graph api doesn’t do such a good job. Thankfully they already caught the album ID is encoded in the link attribute.
So... Let’s cut the talk and show where is the album ID in a Facebook Graph API Photo object. A photo object has a attribute link like this:
"link": "https://www.facebook.com/photo.php?fbid=255682667892372&set=a.255682644460941.54884.100000719217155&type=1",
If we think for a moment it could become clear the set parameter in the URL could provide something and even more the a could stand for album. That is it! Have you caught? Parse from set=a. until the next dot and you got the album id that keeps the photo. (Yeah. That easy.)
So, let's extract that field and retrieve the album, and iterate for the fellow photos in a album. Since my Facebook Graph API wrapper is restFB let’s use Java regular expression.
//posts is a Post list retrived from a user's feed
Post post = posts.get(i);
if(post.getType() != null && post.getType().equals("photo")) {
	//Got a photo
	if(post.getCaption() != null) {
		//it is from a new album
		
		//this regex compilation could be static
		final String ALBUM_REGEX = "(?<=set=a\\.)\\d+";
		Pattern pattern = Pattern.compile(ALBUM_REGEX);
		Matcher matcher = pattern.matcher(post.getLink());
		if(matcher.find()) {
			String albumId = matcher.group();
			Connection< Photo > photos = fbcClient.fetchConnection(albumId + "/photos", Photo.class);
			for(Photo photo : photos.getData()) {
				//do your job with the photos
			}
		}
	}
}
I would love the album ID would be encoded in the Photo object too. It would be much more Object Oriented and far easier. Enough of complains. I guess that is all. Until next post, with more drops of logs from a Computer Scientist’s life.

[+/-] show/hide

2011-09-24

[drops.log]: To pay attention usually pays the effort

That title is a bit vague but can get handy. I commented I got stuck with Facebook Real-time Updates API. The problem was incompatibility between my subscription and user authorization. I subscribed to users feed, but never asked them (myself in the case) for the auth to read their feeds. Of course facebook would never pass me content users never allowed me to get even with a offline access token. By the way, I haven't tried yet, but I am pretty sure you will need one to handle updates processing since the updates are mere announces, no content is delivered.

After, I needed to figure out what is going wrong with my JSP in google appengine. That was very disturbing since this part was working in my develop environment. The case was my fool attempt to save in the session an not serializable Object. Yeah. That stupid! Since appengine doesn’t save on session objects not serializable, but my local development environment does I did that silliness and tried to save the restFB com.restfb.DefaultFacebookClient.
In short I could have finished this coding stage two days early if I have payed more attention in the f*cking documentation. Other damn thing is I needed to revise the code I posted with Facebook Auth Filter. But that was to show me: To pay attention usually pays the effort.
That is all. Until next post, with more drops of logs from a Computer Scientist’s life.

[+/-] show/hide

2011-09-23

[drops.log]: Facebook in Java

I started to do a small piece of code to interact with facebook. I spent some days wondering why the hell my application wasn’t working. The case is bad documentation on Facebook developers page. They say you should pass the authorization code and your app secret to the Graph API token endpoint from an URL like this:

https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE
That is very misleading since the URL contains a parameter redirect_uri that is useless. They never redirect from your page. You get the access_token not as parameter but as content.
I tested facebook-api and restfb and none made a good work to authenticate. You must lead with the initical oauth/dialog url, get and parse the content to retrive the access_token. There is a reasonable elegant way to do that on java servlets: create a Filter that redirect to the authorization page and retrieves the content on the URL above.
Here is the code:
public class FacebookAuthorizationFilter implements Filter {
    public static final String AUTH_URL_BASE = "https://www.facebook.com/dialog/oauth?client_id=%s&redirect_uri=%s&scope=%s";
    public static final String ACCESS_TOKEN_URL_BASE = "https://graph.facebook.com/oauth/access_token?client_id=%s&redirect_uri=%s&client_secret=%s&code=%s";
    
    @Override
    public void init(FilterConfig filterConfig) 
        throws ServletException 
    { /*init code*/ }
    
    @Override
    public void destroy() { /*destroy code*/ }

    @Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;
		
		String code = request.getParameter(MyConstants.CODE_PARAM_KEY);
		String accessToken = request.getParameter(MyConstants.ACCESS_TOKEN_PARAM_KEY);
		
		if(accessToken != null) {
			//there is one already let the application follow usually
			chain.doFilter(req, resp);
			return;
		}else {
			if(code == null) {
				//ask for authorization from facebook
				resp.sendRedirect(String.format(AUTH_URL_BASE, this.appKey, this.redirectURI, this.scope));
			} else {
				//already authorized, fetch the access_code
				accessToken = retriveAccessToken(code);
				//save the access_token
				req.getSession().setAttribute(MyConstants.ACCESS_TOKEN_KEY, accessToken);
				chain.doFilter(req, resp);
			}
		}
	}

    /**
     * Retrieves the content of the page with the access_code token 
     * @param code the code parameter passed to the redirect_uri from the oath/dialog page
     * @return The String access_token provided from facebook
     * @throws IOException
     */
    private String retriveAccessToken(String code) throws IOException {
	    URL url = new URL(String.format(ACCESS_TOKEN_URL_BASE, this.appKey, this.redirectURI, this.appSecret, code));
	    //TODO: Try to sintetize with CharStreams from guava-libraries 
	    ByteArrayOutputStream byteWriter = new ByteArrayOutputStream();
	    InputStream urlReader = url.openStream();
	    int r;
	    while((r = urlReader.read()) != -1) {
		    byteWriter.write(r);
	    }
	    String fetchedResult = new String(byteWriter.toByteArray());
	
	    String[] fields = fetchedResult.split("&");
	    //TODO: Make a regex to extract that
	    for(String field : fields) {
		    String[] pair = field.split("=");
		    if(pair.length == 2 && pair[0].equals("access_token")) {
			    return pair[1];
		    }
	    }
	    throw new RuntimeException(fetchedResult);
    }
}
Sumaring the process on a servlet:
  1. Make a filter that asks for the client object or access_token on the session objectc
  2. If there is no parameter in the session stops the request and redirect to:
  3. https://www.facebook.com/dialog/oauth?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&scope=email,read_stream
    1. Where scope are the permissions you want
    2. The redirect_uri is going to work this case and you must to have a filter in the redirect_uri able to get the code parameter (line 30 in the snippet above)
  4. Fetch the content of the follow URL:
  5. https://graph.facebook.com/oauth/access_token?client_id=YOUR_APP_ID&redirect_uri=YOUR_URL&client_secret=YOUR_APP_SECRET&code=THE_CODE_FROM_ABOVE
    1. (Lines 48 to 56 in the snippet above)
  6. Parse the content to extract the parameters (at least acess_token) (lines 60 to 65 on the snippet above)
  7. With access_token you can create the actual client object to access facebook data (line 37 on the snippet above)
  8. Put the object where you can retrieve it (line 35 in the snippet above)

[+/-] show/hide

2011-09-20

[drops.log]: Google+ API roadmap (and shortcuts...)


Well, my foreplay with Google+ API, launched past week, was too rush and to practical. Let’s make some notes useful for the next time.

First observations:
  • To work with Google+ API we need the Google Client API to get access to user google account and the Google Plus Service API. Make sure to download both
  • We need to get permission from our apps access Google services and data. SO you need to sign in Google API Console
  • Create the app by creating a Client ID, providing type of app, hostname address
  • Switch to ON the status of the services you will need to access from our app
One note for JAVA users, when I was writing this post the documentation was a bit misleading. The feature version of the JAVA wrapper for the Client API was 1.4.3 but version of the google plus API in the Developer’s Guide page was 1.2.1 which is incompatible with the 1.4.3 version, so download the 1.5.0 version
There are start sample code provided for some languages wrappers, the one for JAVA is quite good. It shows for instance how get the access token. Let’s make a Servlet Filter (analogous to drps.log about authentication of FB apps that I showed) to do the job of checking or authorising, retrieving access token... It is very simple, but a bit verbose:

public class GoogleAuthFilter implements Filter {
	
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
	}

	@Override
	public void destroy() {
		// TODO Auto-generated method stub
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;
		AccessTokenResponse accessToken = (AccessTokenResponse)req.getSession().getAttribute(MyConstants.ACCESS_TOKEN_RESPONCE_KEY);
		//test to check access credential 
		if(accessToken == null) {
			String code = req.getParameter(MyConstants.CODE_KEY);
			if(code == null) {
				//no code means the user must allow the app access their data
				AuthorizationRequestUrl authUrl = new GoogleAuthorizationRequestUrl(
														MyConstants.CLIENT_ID, 
														MyConstants.REDIRECT_URI, 
														MyConstants.GOOGLE_PLUS_SCOPE_URL);
				resp.sendRedirect(authUrl.build());
			} else {
				//use the code to generate access token
				accessToken = new GoogleAccessTokenRequest.
										GoogleAuthorizationCodeGrant(
												new NetHttpTransport(), 
												new GsonFactory(), 
												MyConstants.CLIENT_ID, 
												MyConstants.CLIENT_SECRET, 
												code, 
												MyConstants.REDIRECT_URI
										).execute();
				req.getSession().setAttribute(MyConstants.ACCESS_TOKEN_RESPONCE_KEY, accessToken);
				resp.sendRedirect(MyConstants.SERVLET_PATH);
			}
		}
		chain.doFilter(req, resp);
	}
}
To get the Plus service client object is also simple and verbose, just snip of a servlet to exemplify:
AccessTokenResponse accessToken = (AccessTokenResponse)req.getSession().getAttribute(MyConstants.ACCESS_TOKEN_RESPONCE_KEY);
GoogleAccessProtectedResource requestInitializer = new GoogleAccessProtectedResource(
					accessToken.accessToken, 
					new NetHttpTransport(), 
					new GsonFactory(), 
					MyConstants.CLIENT_ID, 
					MyConstants.CLIENT_SECRET, 
					accessToken.refreshToken);
Plus plus = new Plus(new NetHttpTransport(), requestInitializer, new GsonFactory());
With the Plus object you can make requests to access people data
String who = req.getParameter(MyConstants.WHO_KEY);
who = who == null ? "me" : who; 
Person me = plus.people.get(who).execute();
You could access the activities too, but just the public.
We are almost finishing. Let’s list (or relist) useful links too:
That is it. Enjoy the Google+ small set of accessible data. And let’s hope we get more soon.

[+/-] show/hide