|
Blogs
In the previous blog, you saw how Scala could do similar things to Java (even compiling to the same bytecode), but in a more compact and readable form. In this blog you’ll learn more about some of the things that make Scala unique as we write an application to read XML feeds from Twitter and SDN, using them to produce a web page with a list of blog entries written by Twitter friends. We’ll step through the code a few lines at a time so you can see how the whole thing is built up. At the start of our application, we declare the package name and the list of imports, just like Java. You can see that Scala does not require a semicolon at the end of each line. The underscore character “_” is Scala’s wildcard character, so the first import gives access to all the classes in package scala.xml. The second import shows a handy bit of Scala syntax to allow access to several named classes in the java.net package without requiring a separate line for each one. Next, we declare our class along with the main() method which will be executed when we run our program from the command line. In this case, we are declaring a singleton class, which in Scala is declared as an object. Next, we declare the main() method with the command-line arguments being passed in as an array of strings. So, that’s the language-level housekeeping out of the way, and it’s time to write some useful code. Let’s load up the XML feed for SCN blogs.
There are a few interesting things happening in this few lines of code. First of all, we’re declaring a new value, sdnBlogs, to hold the result of the following code block. “val” declares an entity which, once assigned, cannot be reassigned. This is just like using the “final” qualifier in Java. The code block (in braces after the = sign) is basically an in-line anonymous function, where the result of the last line is returned as the function value. So this is what the whole snippet of code does: defines the URL of the SCN blogs’ RSS feed; opens a connection to that URL; reads the data from that connection into a Scala XML object (class scala.xml.Elem); and assigns that object to the identifier sdnBlogs. Incidentally, if this XML was stored in a local file instead of a remote web server, the whole three-line block would be replaced with just one line of code: val sdnBlogs = XML.load(“SAPNetworkWeblogs.xml”) The XML code below shows the kind of data we get from the RSS feed:
Although it’s not too clear from the feed’s layout, the XML stream has a top-level <rdf:RDF> element (invisible here because it’s at the end of the second line), containing a <channel> element followed by a number of <item> elements. Each <item> contains elements describing the <title>, <link>, <description>, and so on, with the <dc:creator> element (highlighted) containing the name of the blog’s author. This is the name that we’ll be matching against the Twitter feed later. Next, we load up the XML feed from Twitter, using the 1st and 2nd command-line arguments as our Twitter username and password:
This is basically the same code as we used to get the SCN blog feed, except for a few lines of boilerplate code converted from Java which we use to set our Twitter login credentials. The XML code below shows you what we get back from Twitter when we ask it for a list of friends:
The Twitter feed gives us XML with a top-level <users> element, containing a list of <user> elements. Within these are <id>, <name>, <screen_name>, etc. with <name> (highlighted) showing the real name of the user. This is what we’ll try to match with the name of the blog author from the SCN feed. Let’s recap where we are now: we have used 5 lines of code to do the basic housekeeping of declaring our Scala program, and a further 13 lines to load up feeds from two remote web services, one of them requiring authentication. The next step is to get a list of our friends’ names from the Twitter XML, which is just one line of Scala: This one line of code does quite a lot of work, so let’s break it down into chunks. val friendNames you should be familiar with by now – that declares an entity to hold the result of what comes next. In simple terms, the rest of the line says “for each <user> element in the XML file, get the contents of the <name> element and add it to a list”. Let’s drill down into the detail of the line to see how it does that: First we define a for() loop. twitterFriends\”user” is the syntax to get a sequence of <user> nodes from the twitterFriends XML object. val user <- then binds the value user to each node in the sequence as the for() loop runs. The yield keyword after the loop definition tells Scala, for each iteration of the loop, to add the result of the following expression to a list. This expression is (user\”name”).text, which gets us the inner text of the <name> element from the user. So, to summarise that one line of code: it extracts the text content of the <name> element for each <user> element in our XML, and returns the result as a list of String objects into the value friendNames. Our next chunk of code loops through the items in the sdnBlogs XML object which have a <creator> element matching one of our Twitter friends’ names, producing an HTML link for each one:
This bit of code starts off in a similar way to the previous chunk – declaring a result object and kicking off a for() loop. There’s a slight difference to the for() syntax here – instead of for(elem <- collection) we have for (elem <- collection; condition). This formulation only iterates over the members of the collection that satisfy the condition (rather like a WHERE clause in SQL). In this case, the condition is friendNames.contains((item\”creator”).text) – in other words, only perform this iteration if the blog item’s creator is in our list of friends. The yield clause is also interesting: you can see here one of the unique aspects of Scala in that XML is a core part of the language syntax. Here, instead of yielding a list of names, we are yielding a collection of XHTML fragments – a list of links to the blog entries of our friends. Within XML used literally in Scala you can include normal Scala code in braces. In the code above, you can see that we are inserting the text of the <link> and <title> elements from each sdnBlogs <item> into the XHTML we are generating. Time for another quick recap, because we’ve covered a lot of ground here: we have just got a list of our friends from an XML feed and cross-referenced that against another XML feed, to produce a third stream of XML, and we’ve done all of that in just 5 lines of code. Now we have our list of links, we need to embed that within a properly-formatted HTML page:
This is pretty straightforward now that we know we can use raw XML in our Scala – in fact we could just copy and paste the code from the HTML editor of our choice and insert {friendBlogs} at the point where we want our links to appear. Finally, just for polish, we’ll format and indent the HTML using a pretty printer object and print it out to the console:
When compiled and run: Our program produces similar HTML to this (depending on who your Twitter friends are, and how many blogs they’ve written recently):
This whole program, excluding the 7 lines of HTML, is 27 lines of code. Pretty powerful stuff, huh? :-) If you want to try this yourself, the code is here: https://wiki.sdn.sap.com/wiki/display/Community/ScnTwitterBlog.scala
Darren Hague is an SAP Mentor, a member of the Cross Applications team in SAP IT, and has written a book on the Universal Worklist for SAP Press.
| |||||||||||||||||||||||||||||||||||