The Blogapps Project Blog

Version 2


    RSS and Atom development kit, server, and example applications


    My new book RSS and Atom in Action (now available at fine booksellers everywhere) was originally known by the somewhat odd title Blogapps. We called it that because the book focused on providing a useful set of blog applications and we thought Blogapps sounded quite clever. Turns out that "blogapps" was a little too confusing to our early reviewers, so we re-titled the book, as you can see in Figure 1.

    The book
    Figure 1. The book

    Fortunately for lovers of odd words, the term "blogapps" lives on. It's the name of Part II of the book and it's the name of the open source project I started to host, maintain, and support the book's example code. So why should you care about bunch of example code listings? Well, the Blogapps project is much more than just that.

    The project provides what is essentially a complete RSS and Atom development kit, which includes feed parsers, generators, blog client libraries, an Atom protocol implementation, a set of ten useful blogapps, and an easy-to-install blog and wiki server. This article explains the project's purpose and how to install and use the project's products, the Blogapps Examples and Blogapps Server, to jump-start your RSS and Atom development. But first, let me explain why Blogapps is an open source project.

    An Open Source Project?

    The easiest way to release the book's code would have been to create a .zip file and upload it to the Manning Publications website. That would have worked just fine, but I want to make it really easy for people to use the code, easy for me to maintain and release new versions of the code, and possible for others to help. The best way to do that is to release the code under the commercial-friendly Apache Software License and use open source project hosting to manage the code, track bugs, provide a wiki, and offer downloads. I chose, which offers all of those features and more free of charge.

    Open source project hosting makes it easy for me to maintain and release one branch of code that stays true to what's in the book, changing only to fix bugs and to respond to changing API and protocols (e.g. the Windows RSS Platform and the Atom Publishing Protocol). At the same time, I can create a new branch, which can diverge from the book with redesigns, rewrites and, I hope, reader-contributed enhancements.

    You'll find links to the Blogapps project resources in the Resources section at the end of the article. Now, let's take a look at the project's products, starting with the server.

    Getting Started with the Blogapps Server

    If you'd like to take Roller for a spin, check out JSPWiki, or experiment with a server that supports both the MetaWeblog API and the Atom protocol, try the Blogapps Server. This is a full-featured blog and wiki server, specially packaged to be easy to install. It's based on Roller, the blog server that powers Sun and IBM corporate blogs, and JSPWiki, one of the most popular Java-based wikis.

    We were able to make the Blogapps Server fairly easy to install by including with it web and database servers. But you do have to know how to install a Java development kit and set environment variables. If you're comfortable with that, then here's what you have to do to install and run the server:

    1. If you don't already have a Java J2SE development kit, version 1.4.2 or later, then download and install the one from Sun (from On Windows, the installer should set the JAVA_HOMEenvironment variable to the directory in which the kit is installed. You might want to check that. On Unix, you'll probably have to set the environment variable yourself (e.g. inbash, you'd export JAVA_HOME=/path/to/jdk).

    2. Download the latest version of the Blogapps Server from the files area of the Blogapps project.

    3. Use tar on Unix, or Winzip on Windows, to unzip the file into a directory on your hard drive. On Windows, you may have problems if the directory name contains spaces.

    4. Ensure that the JAVA_HOME environment variable is set to point to your directory of your J2SE development kit.

    5. Do you already have Tomcat installed on your computer? If so, be sure to shut it down before you start Blogapps Server. Also ensure that the Tomcat environment variables CATALINA_HOMEand CATALINA_BASE are not set in your environment.

    6. Start the server.

      1. To start Roller on Windows: open the Blogapps Serverbin directory and double-click onstartup.bat.

      2. To start Roller on Unix: cd to the Blogapps Serverbin directory, chmod +x on all files, and run./ to start it up. Assuming that all worked, you should now be able to browse to http:// localhost:8080/roller and starting using Roller. Figure 2 illustrates what you should see.

    The Blogapp Server front-page
    Figure 2. The Blogapp Server front page

    The Blogapps Server includes a handful of web applications. Here are the URLs at which you can find them:

    Now that we've mastered the server, let's move on to the examples.

    Guide to the Blogapps Examples

    If you'd like to jump-start your RSS and Atom development with numerous examples, re-usable code, and a dozen ready-to-use blogapps, then try the Blogapps Examples.

    As you'd expect, the Blogapps Examples includes all of the example code from the book. But among the dozens of simple little examples, there are a bunch of useful nuggets--libraries for use in your projects and the blogapps, which are complete applications ready for use on your network. For example, in Part I we develop a simple Feed Parser, which can parse any RSS 1.0, RSS 2.0 or Atom feed. And we develop a Blog Client library that you can use in your projects to automate blogging and web publishing. Here's a list of re-usable libraries and applications provided by the project:

    AnyFeedParserSimple JDOM-based RSS/Atom feed parser (Chapter 5)
    BlogClientBlog client library supporting MetaWeblog API and Atom (Chapters 8 and 9)
    PlanetToolPlanet-style blog aggregator (Chapter 11)
    TechnoratiJSimple Technorati API client library (Chapter 12)
    Cross PosterParses feeds, posts to blog (Chapter 13)
    Mail BloggerReceives mail, posts it to blog (Chapter 14)
    Blog DigestParses feeds, sends daily digest by email (Chapter 15)
    Ant BloggerBlog and upload files from build scripts (Chapter 16)
    BlogbotIRC chat robot that blogs on command (Chapter 17)
    File CasterSimple file/podcast server with file upload (Chapter 18)
    File CatcherSimple command-line file/podcast downloader (Chapter 19)
    Feed PosterParses feeds, posts daily digest via Blog Client (not in book)
    GrabberDownloads all posts from a blog and saves them each separately (not in book)

    Now that you know what's available, let's discuss how to work with the Java versions of the examples.

    Building and Running the Examples

    Before you can start working with the examples, you need to install and build them on your computer. It's a lot easier than installing the Blogapps Server, but the examples are basically the same; i.e., you need the J2SE SDK Version 1.4.2 or later.

    First, you've got to download and install the Blogapps Examples. Download the latest version from the blogapps-serverfolder in the files area of the Blogapps project and decompress as before.

    To build the Java examples, use the Ant script located in thejava directory. Assuming you've got a Java development kit and you've got Ant, then all you need to do to build the examples is to open a console window,cd to the blogapps java directory, and run Ant. For example, on Windows:

     c> cd \blogapps\java c> ant

    Or on UNIX:

     $ cd ~/blogapps/java $ ant

    As Ant runs, it will visit all of the chapter sub-directories under the java directory, from ch02 toch18, running the Ant script in each. After Ant finished, you'll find that each chapter directory is organized as follows:

    • chXX/build.xml : Ant build script for chapter.
    • chXX/etc: Miscellaneous startup and configuration files.
    • chXX/src: The example Java source code.
    • chXX/lib: The .jars required by the example.
    • chXX/build: Temporary build files.
    • chXX/dist/[example-name]: Complete and ready-to-run example.

    The dist directory contains the complete and ready-to-run example, packaged for distribution; thus the directory name. If you want to run an example, go to its distdirectory. For example, if you'd like to run the Chapter 2 example, which posts to a blog server via MetaWeblog API, you'd do something like this:

    • Start the Blogapps Server using the instructions above (because we'll need to post to a blog server and Blogapps Server supports the MetaWeblog API).

    • Change directories to the blogposter directory, which lives in the dist directory of the ch02 examples. For example, if you've installed Blogapps Examples under Windows in the directory c:\blogapps, here's what you'd do:

       c> cd \blogapps\java\ch02\dist\blogposter c> blogposter "this is the title" "this is the content"

      In Unix, it would look like this:

       $ cd ~/blogapps/ch02/dist/blogposter $ ./ "this is the title" "this is the content"

    You can find instructions for building and running all of the examples on the Blogapps website. There is a README for each chapter, and you can find them all on the Blogapps project page. That's all you need to know about building and running the examples; now let's discuss how to use them in your own projects.

    Using the Blog Client

    Let's look at Blog Client, a client library for publishing to blog servers that support either the XML-RPC-based MetaWeblog API or the Atom protocol. The library is defined by a set of interfaces, shown in Figure 3.

    The Blog Client library interfaces
    Figure 3. The Blog Client library interfaces

    Now let's take a look at an example that shows how to post a blog entry via Atom protocol and the Blog Client library.

     import com.manning.blogapps.chapter10.blogclient.*; // class and method declaration omitted String endpointURL = // URL of your blog server String username = // your username on the blog server String password = // your password String title = // title of the new blog entry String content = // content of the new blog entry BlogConnection con = #1 BlogConnectionFactory.getBlogConnection( "atom", endpointURL, username, password); Blog blog = (Blog)con.getBlogs().get(0); #2 BlogEntry entry = blog.newEntry(); #3 entry.setTitle(title); #4 entry.setContent(new BlogEntry.Content(content)); #5; #6

    Let's review that code. First we get a connection from the factory by specifying the Atom protocol, our Blog Server's endpoint URL, and login credentials (#1). From the connection, we get the first blog that's available (#2). Next, we create a new entry in the blog's primary collection (#3), set its title (#4), set its content (#5), and post it to the blog server by calling itssave() method (#5).

    Before you can use the Blog Client library in your application, you need to add the required .jars to your application's classpath. You can find those .jars in the dist/blogclient/libdirectory in the Chapter 10 directory. Now let's move on to the Blogapps parser.

    Using theAnyFeedParser

    In RSS and Atom in Action, we recommend that you use a parser library like ROMEfor Java, but we also show you how to parse feeds "by hand" with the JDOM XML parser. To that end, we develop a simple parser called AnyFeedParserthat can handle RSS 0.9X, RSS 1.0, RSS 2.0, and Atom 1.0 feeds.

    So that we're not locked in to just one implementation of our simple parser, the parser implements an interface calledIFeedParser.

     package com.manning.blogapps.chapter05; import; import java.util.Map; public interface IFeedParser { public Map parseFeed(Reader is) throws Exception; public Map parseFeed(String fileName) throws Exception; }

    And to keep things simple, we don't parse to a Java object model. As you can see in the interface, we parse to a hashtable, which is keyed by RSS element names. That may seem like an oversimplification, but it works well and, in fact, it's the approach taken by the king of parsers, the Universal Feed Parser (the Python-based parser that lives at Our little parser pales in comparison to the king, but it's small, relatively easy to understand, and easy hack up if you have your own unique parsing needs. We only parse a subset of RSS and Atom elements. Here are the keys you can use to extract data from the hashtable:

    • title: String
    • link: String
    • description: String
    • items: List of Hashtables with these keys:
      • guid: String
      • title: String
      • pubDate: Date
      • description: String
      • content: String
      • summary: String
      • enclosure: Hashtable with these keys:
        • url: String
        • type: String
        • length: Integer

    Using AnyFeedParser is simple too. All you have to do is copy two .jars to your application's classpath, add animport statement, and add a call to the parser. You can find the parser in the Chapter 5 examples directory and the .jars are located there too, in the dist/parsers/libsubdirectory. You'll need two .jars: ch05.jar andjdom.jar.

    Once you've got the .jars in your classpath, you should be able to write code like this, which parses a feed and prints it out to the console:

     IFeedParser parser = new AnyFeedParser(); Map feed = parser.parseFeed(filePath); System.out.println("Feed title: " + feed.get("title")); List items = (List)feed.get("items"); for (int i=0; i<items.size(); i++) { Map item = (Map)items.get(i); System.out.println("Item #" + i); System.out.println(" title: " + item.get("title")); System.out.println(" link: " + item.get("link")); System.out.println(" pubDate: " + item.get("pubDate")); }

    There's also a version of the parser calledAnyFeedParserCaching that parses feeds specified by URL and maintains a local cache via HTTP Conditional Get, which is a bandwidth-saving best-practice for fetching feeds. To use the caching parser you need to provide a cache directory, afeedURL from which to fetch the feed and some code like this to create the parser:

     AnyFeedParserCaching parser = new AnyFeedParserCaching(); parser.setCacheDir(cacheDirectoryPath); Map feed = parser.parseFeed(feedURL);

    That's it for the simple feed parser, now let's talk about the future.

    Future Plans

    What's next for the Blogapps project? That depends on the branch. In the Blogapps 1.0 branch, which is supposed to remain true to the code in the book, I will only make changes to fix bugs and to update the code for the final Atom Publishing Protocol specification and for the final release of IE7.

    But the Blogapps 2.0 branch can run wild and free. It can deviate from the code in the book. So I (and maybe someday, we) can release new versions of the Blogapps Examples with completely new features and new versions of the Blogapps Server that use newer versions of Roller an JSPWiki. Here are some my ideas for future development.

    • Redesign the Blog Client library so that its interfaces use the ROME object model directly instead of its own model, which is not as robust or complete as ROME's.
    • Enhance the FileCaster podcast server to provide a password-protected administrative interface, to extract ID3 tags, and to support iTunes tags.
    • Get rid of those confusing chapter numbers in the directory and package names and use application names instead; i.e., "feedposter" and "blogclient." And switch the package instead ofcom.manning.blogapps.
    • Create a version of the Blogapps Server that uses Roller 3.0 instead of 2.4, GlassFish instead of Tomcat, and Derby instead of HSQL-DB. And upgrade to JSPWiki 2.4.


    You've learned that the Blogapps project is more than just a set of examples; it's an RSS and Atom development kit based on Java (and C#) with a set of immediately useful applications. Whether you're looking for a snippet of example RSS/Atom code or a complete blog application, I hope you'll find the project is a good starting point. And if you do find the project useful, get involved. Please help out your fellow readers by directing your bug reports, comments, patches, and suggestions for improvement to the project's issue tracker and mailing list.