The Kahimyang Project Logo
Primo's Code Blog
Howtos tips and tricks
The Kahimyang Project

Generating XML RSS 2 feeds with JDOM 2 with a servlet

To better demonstrate how to generate XML RSS 2 feeds, we will use a servlet with JDOM 2 library. In this short blog, we will generate only the required elements plus a few options for feed reader interoperability. Please refer to the RSS 2 documentation for more of the optional elements and to learn more about the RSS 2 specifications. JDOM 2 is available for download here http://www.jdom.org/.

Below is a sample RSS 2 feed generated by the servlet that follows further down (contents edited for clarity).

<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <!-- title, link, description are required -->
    <title>Primo's code blogs feeds</title>
    <description>Feeds from  Kahimyang Projects Primo's code blogs</description>
    <link>http://kahimyang.info/kauswagan/RssFeeds.xml?type=howto</link>
    <language>en</language>

    <!-- Only for feed reader interoperability -->
    <atom:link rel="self" href="http://kahimyang.info/kauswagan/RssFeeds.xml?type=howto" 
            type="application/rss+xml" />

    <!-- Contents of the feed -->
    <item>
      <title>
         Title of the story item.
      </title>
      <link>
         URL that points to the full content.
      </link>
      <description>
        <![CDATA[
        Description of the item.  In the case of a blog or 
            news item, this can be the synopsis.  
        ]]>
      </description>
      <guid>
         unique_id_of_the_feed_item
      </guid>
      
      <!-- Required format.  Publication date -->
      <pubDate>Fri, 16 Sep 2011 14:31:01 EDT</pubDate>

    </item>

    <!-- more items -->

  </channel>
</rss>

The sample feed above was generated based on the recommendation of the Feed Validator Service from w3.org.

Elements <link /> and <atom:link /> in lines 7 and 11 should point to the URL of the feed. Sub-element <link /> of <item /> points to the URL of the item itself.  Date and time values should conform to RFC #822.  Wrapping the description with CDATA is required if the content has HTML formatting.

Here is the servlet that generated the above sample feed.  Please refer to the inline comments for more information. In this servlet, items are drawn from a database. Please note that some lines were removed for clarity.


package pname;

import java.io.IOException;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;
import java.text.SimpleDateFormat;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jdom2.CDATA;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.Namespace;
import org.jdom2.output.Format;
import org.jdom2.output.XMLOutputter;
import org.jsoup.Jsoup;
import org.jsoup.safety.Whitelist;

@WebServlet(name = "RssFeeds", urlPatterns = {"/RssFeeds.xml"})
public class RssFeeds extends HttpServlet {

    @Override
    protected void doGet (HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
                
        response.setContentType("application/xml;charset=UTF-8");
        PrintWriter servlet = response.getWriter();
        
        try {
            // Create the root rss element            
            Element rssRoot = new Element("rss");


            // Required attribute
            rssRoot.setAttribute("version", "2.0");
            
            // Create the XML document
            Document feed = new Document();
            feed.setRootElement(rssRoot);
                        
            Element channel = new Element("channel");
            
            rssRoot.addContent(channel);


            channel.addContent(new Element("title").
                     addContent("Title of the Feed"));
            channel.addContent(new Element("description").
                 addContent("Description of the entire feed"));
            
            final String url=
                    "http://kahimyang.info/kauswagan/RssFeeds.xml?type=howto";
            
            channel.addContent(new Element ("link").addContent (url));                 
            channel.addContent(new Element("language").addContent("en"));


            // Create the atom namespace
            Namespace atom = 
                   Namespace.getNamespace("atom","http://www.w3.org/2005/Atom");
            rssRoot.addNamespaceDeclaration(atom);            
                       
            Element link = new Element ("link",atom);  // atom:link
            link.setAttribute("rel","self").setAttribute("href",url).
                 setAttribute("type","application/rss+xml");

            channel.addContent(link);
                        
            addRssItems (channel); // the actual feeds
                       
            // Write the document to the servlet response
            XMLOutputter output = new XMLOutputter();
            output.setFormat(Format.getPrettyFormat().setEncoding("UTF-8"));
            output.output(feed, servlet);

        }  
        finally {
            servlet.flush();
            servlet.close();
        }
    }


    void addRssItems (Element channel) {

        // Build the query 
        StringBuilder q = new StringBuilder("select ...");

        try (
                // Change the way you connect to database.
                Connection conn = DatasourceConnection.getConnection();
                Statement stmt = conn.createStatement();
                ResultSet result = stmt.executeQuery(q.toString())) {


            while (result.next()) {

                Element item = new Element("item");
                item.addContent(new Element("title").
                        addContent(result.getString(1)));

                // link to the item itself
                item.addContent(new Element("link").
                          addContent(result.getString(2)));

                // This can be a sysnopsis
                // Strip off risky attributes from html tags
                String teaser=Jsoup.clean(result.getString(3),Whitelist.basic());
                item.addContent(new Element("description").
                         addContent(new CDATA(teaser)));

                // Unique ID, usually this is the same as link 
                item.addContent(new Element("guid").addContent("the_unique_id"));
                    
                // Required format
                SimpleDateFormat f = 
                       new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz");
                item.addContent(new Element("pubDate").
                       addContent(f.format(result.getTimestamp(4))));

                channel.addContent(item);

            }
            

        } catch (Exception e) {
            // return an empty channel
        }
    }


    @Override
    public String getServletInfo() {
        return "Short description";
    }
}

Character encoding specified in lines 30 and 77 should match.  Application type application/xml should also be used for some browsers to render the feed correctly.

Additional library used in this servlet (line 112 above) is Jsoup. It can be downloaded here http://jsoup.org/.

That's it Good Luck.

RSS Logo



Related articles

Comment icon   Comments (Newest first)

Recent posts in Java/JSF category
Blue dot icon Using Rhinoslider with image and youtube content in JSF pages
Blue dot icon A dynamic standard sitemap.xml with Google image extension implemented as a Java Servlet
Blue dot icon Creating a Facebook-like panel with slim scrollbars and infinite scrolling in PrimeFaces
Blue dot icon Generating XML RSS 2 feeds with JDOM 2 with a servlet
Blue dot icon Building a page with infinite scroll in PrimeFaces using Waypoints jQuery plugin
Blue dot icon Implementing a collapsible ui:repeat rows in JSF
Blue dot icon Validating an email address in PrimeFaces p:inputText field with p:ajax





Most popular articles
Blue dot icon Using Expect script to automate SSH logins and do routine tasks accross multiple hosts   (15404)
Blue dot icon How to setup Tomcat 7 as your primary webserver on Debian Squeeze    (14083)
Blue dot icon How to setup FLV streaming with crtmpserver C++ RTMP server   (9862)
Blue dot icon A Java class for sending multipart Email messages through your Gmail account    (6980)
Blue dot icon How to use Google Translate's Text to Speech (TTS) services in your web page using Servlet   (5679)
Blue dot icon Speed up Primefaces page load with p:remoteCommand partial update   (5553)
Blue dot icon Building a mobile website with JSF 2 core and JQuery Mobile 1.0   (5333)
Blue dot icon Google Map-Adding markers, info window, circle, small control, and events in Javascript    (5240)