Blogs

Darren Hague

An introduction to Scala, part 2: Scala and XML
Darren Hague SAP Employee 
Business Card
Company: SAP
Posted on Jun. 23, 2008 03:00 PM in Application Server, Emerging Technologies, Interoperability, Java Programming, Ruby, SAP NetWeaver Platform, Scripting Languages

URL: https://wiki.sdn.sap.com/wiki/pages/viewpage.action?pageId=21692556

Subscribe.Subscribe
Print. Print
Permalink Permalink
Share

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.

image

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.

image

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.

image

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:

image

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:

image

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:

image

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:

image

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:

image

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:

image

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:

image

When compiled and run:

image

Our program produces similar HTML to this (depending on who your Twitter friends are, and how many blogs they’ve written recently):

image

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.


Comment on this article
Comment on this weblog
Showing messages 1 through 4 of 4.

Titles Only Main Topics Oldest First

  • Wow. Pretty impressive
    2008-06-23 23:17:24 Richard Hirsch Business Card [Reply]

    Hi,


    Looks cool and it appears to be very compact. Have you had any luck embedding this in NetWeaver? Is there any Ajax-UI packages for Scala as well?


    Dick

    • Wow. Pretty impressive
      2008-06-24 01:39:59 Darren Hague SAP Employee Business Card [Reply]

      Hi Dick,


      Using Scala with NetWeaver is coming in a future blog, when I'll discuss the web development framework for Scala: /lift/. Right now though, Scala code can be compiled to Java 1.4 bytecode, and will therefore run on NetWeaver Java. I've not tried it yet, but the code above could just as easily extend javax.servlet.http.HttpServlet and implement doGet() instead of implementing main() - that should give a functioning web application which can be deployed to NetWeaver Java. I leave that as an exercise for the reader. :-)

  • Wow. Pretty impressive
    2008-06-23 23:17:22 Richard Hirsch Business Card [Reply]

    Hi,


    Looks cool and it appears to be very compact. Have you had any luck embedding this in NetWeaver? Is there any Ajax-UI packages for Scala as well?


    Dick

  • Scala Rules!
    2008-06-23 15:29:34 Alvaro Tejada Galindo SAP Employee Business Card [Reply]

    Darren:


    Thanks a lot for this awesome example of Scala capabilities...Can't wait to get home and test it -:D


    Greetings,


    Blag.


Showing messages 1 through 4 of 4.