Java Web Programming with Eclipse contents
Last modified April 24, 2013 07:48 pm

back next

A Simple News Feed Application

Objectives

References

Video

The following video contains an out-dated procedure for obtaining the ROME jar file and source code. See the text in this chapter for an explanation of how to get these files or see the video addendum.

Overview

People interpret the acronym RSS in several ways. For example, you may hear that RSS stands for Rich Site Summary, or Really Simple Syndication, or even RDF Site Summary. Most people simply refer to the technology as RSS. In all cases, RSS is a protocol for providing news summaries in XML format over the Internet.

The following is an examlpe of an XML document that is a news feed. It contains a root element called rss. Under the rss element, there is a single child element called channel. The title, description and language elements within the channel element are properties of the entire news feed. Following these elements are a sequence of zero or more item elements. Each item element represents a summary of a news story. In our example, we include for each news story item, the title of the news article, a link to the web page with the complete new article, and a short description of the article.

<rss version="2.0"> 
<channel>
  <title>My News</title> 
  <description>This is my news</description> 
  <language>en-us</language> 
  <item> 
    <title>Hello</title> 
    <link>http://csusb.edu/</link> 
    <description>Hello there.</description> 
  </item> 
  <item> 
    <title>Bye</title> 
    <link>http://cse.csusb.edu/</link>  
    <description>Come here, go any where.</description> 
   </item> 
</channel> 
</rss> 

In this chapter, we incorporate a news feed provided by yahoo in the home page of our website application. The following diagram illustrates the flow of information that will take place.

Flow of information for RSS

Flow of information for RSS

First, the user issues the command to his browser to retrieve the home page of the website application. In response, the browser sends an HTTP GET request to the website application to request the home page. The website application sends an HTTP GET request to the yahoo news feed server to request a current summary of news. The yahoo news feed server returns to the website application an XML document (in RSS format) that contains a list of news items. The website application parses the XML document to extract the news items. It then uses this information to construct the HTML that it returns to the browser.

Install Libraries

The code in this chapter depends on ROME, which is a Java API (or library) to parse and create news feeds in the various versions of RSS and Atom. The ROME project website provides links to the ROME jar file and source code. This book assumes that you use version 1.0 of ROME.

Place the ROME jar file in the web/WEB-INF/lib folder of the website project, and add it to the build path. Attach the source code to the ROME library using the proceedure described in the Java Servlets chapter.

ROME is not a stand-alone library: it depends on another library called JDOM, which is an API for manipulating XML documents. So, go to the JDOM website and download the most recent release of JDOM. The jar file can be found in the build folder inside the archive. Add the JDOM jar file to the lib folder in your project and add it to the build path.

Modify HomeServlet

The next step is to modify HomeServlet, so that it retrieves an RSS news feed and makes the content available to the JSP.

Replace the body of the doGet method with the following.

logger.debug("Retrieving yahoo news feed");
URL url = new URL("http://rss.news.yahoo.com/rss/tech");
SyndFeedInput syndFeedInput = new SyndFeedInput();
SyndFeed syndFeed = null;
XmlReader xmlReader = new XmlReader(url);
syndFeed = syndFeedInput.build(xmlReader);
logger.debug("Forwarding to home.jsp");
req.setAttribute("syndFeed", syndFeed);
homeJsp.forward(req, resp);

After replacing the body of doGet with the new code you will get icons indicating compilation errors. Most of these errors are due to the fact that the class names being used are not fully qualified (prefixed by their package names) or not imported in the import section at the top of the file. To fix this problem, you should invoke the organize imports operation in the source menu. However, when you do this, eclipse will not be able to determine the package for the InputStream class, because several different packages include an InputStream class. Eclipse will present to you a list of possible fully qualified class names to choose from. The following list shows the choices you should make in this step.

  1. com.sun.syndication.io.XmlReader
  2. java.net.URL

After organizing imports, there will still be a compilation error. In particular, there will be an error icon identifying a problem with the following line.

syndFeed = syndFeedInput.build(xmlReader);

If you hover the mouse pointer over the error icon, you will see that there is an unhandled Exception of type FeedException. Use Eclipse to generate exception catching code by doing the following.

  1. Highlight the entire line that is marked with the error.
  2. Select Source ... Surround with ... Try/catch block.

Eclipse generated two catch phrases: one to catch an IllegalArgumentException, and another to catch a FeedException. The code invokes the printStackTrace method of the caught exception. This method will print a stack trace to the standard output stream (System.out). However, in our code, we want to report these and other exceptions in the application log file. To do this, replace the lines that invoke the printStackTrace method with the following.

logger.error("", e);

The following listing shows the modified HomeServlet.java file.

Modified HomeServlet.java for RSS News

package website.web;

import java.io.IOException;
import java.net.URL;

import javax.servlet.RequestDispatcher;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.FeedException;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

public class HomeServlet extends HttpServlet {

	private Logger logger = Logger.getLogger(this.getClass());
	private RequestDispatcher homeJsp;
	
	@Override
	public void init(ServletConfig config) throws ServletException {
		ServletContext context = config.getServletContext();
		homeJsp = context.getRequestDispatcher("/WEB-INF/jsp/home.jsp");
	}

	@Override
	protected void doGet(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		logger.debug("Retrieving yahoo news feed");
		URL url = new URL("http://rss.news.yahoo.com/rss/tech");
		SyndFeedInput syndFeedInput = new SyndFeedInput();
		SyndFeed syndFeed = null;
		XmlReader xmlReader = new XmlReader(url);
		try {
			syndFeed = syndFeedInput.build(xmlReader);
		} catch (IllegalArgumentException e) {
			logger.error("", e);
		} catch (FeedException e) {
			logger.error("", e);
		}
		logger.debug("Forwarding to home.jsp");
		req.setAttribute("syndFeed", syndFeed);
		homeJsp.forward(req, resp);
	}
}

Whenever the doGet method of the HomeServlet is invoked, the servlet requests a news feed from yahoo related to technical news. The servlet uses the SyndFeedInput class of the ROME library to parse the RSS document into a SyndFeed object. The SyndFeed interface allows us to conveniently access the information in the news feed using standard Java idioms. The servlet exposes the SyndFeed object to the JSP by placing it in request scope with the setAttribute method of the request object. After doing this, it passes execution to the JSP, which will extract the news data from the SyndFeed object and embed it into the HTML that it returns to the browser.

Modify the JSP

Now, we will create the JSP file that constructs the HTML, which is sent to the browser. Replace the contents of home.jsp with the contents of the following listing.

Modified home.jsp for RSS News

<%@ page import="com.sun.syndication.feed.synd.SyndFeed" %> 
<%@ page import="com.sun.syndication.feed.synd.SyndEntry" %> 
<%@ page import="java.util.Iterator" %> 
<jsp:useBean id="syndFeed" scope="request" type="SyndFeed" />
<html>
   <head>
      <title>website</title>
   </head>
   <body>
      <h1>Home</h1>
      <h2><%=syndFeed.getTitle()%></h2>
      <ul>
         <% 
           Iterator it = syndFeed.getEntries().iterator();
           while (it.hasNext())
           {
              SyndEntry entry = (SyndEntry) it.next();
         %>
            <li>
               <a href="<%=entry.getLink()%>"><%=entry.getTitle()%></a>
            </li>
         <% } %>
      </ul>
   </body>
</html>

The code in our JSP file includes references to classes, such as SyndFeed, that need to be either fully-qualified or imported. In our example code, we import these names by using a JSP tag that starts with <%@ page import=... These lines tell the JSP translator which Java imports it needs to include in the code that it generates. For example, the JSP translator will translate the first line in the previous listing to the following.

import com.sun.syndication.feed.synd.SyndFeed;

You can confirm this by looking in the file home_jsp.java under ${TOMCAT_HOME}/work.

Test

Test your application by reloading the website application in the the manager application and going to http://localhost:8080/website/home.

Create Publisher Project

At this point, we will begin to develop another web application called publisher that will publish news feeds. Initially, this application will simply return an XML document that is stored in the file system. In a subsequent chapter, we will generate this XML document from the database rather than reading it directly from the file system.

For this purpose, create a new project in Eclipse called publisher and set it up in a manner similar to how you set up the website project. In particular, you should specify publisher/web/WEB-INF/classes as the default build folder. You don't need to add any libraries at this point, but we will eventually need to add servlet-api.jar and others in later chapters.

Add the following deployment descriptor to the publisher application. We add the following web.xml file to ensure that Tomcat recognizes our project as a dynamic web application. If we don't do this, some versions of Tomcat will not process JSP files.

Initial web.xml file for the publisher project

<?xml version="1.0"?>
<web-app
     xmlns="http://java.sun.com/xml/ns/j2ee"
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">
</web-app>

Within the web directory, create a new file called news.rss with the following contents.

<rss version="2.0"> 
<channel>
  <title>My News</title> 
  <description>This is my news</description> 
  <language>en-us</language> 
  <item> 
    <title>Hello</title> 
    <link>http://csusb.edu/</link> 
    <description>Hello there.</description> 
  </item> 
  <item> 
    <title>Bye</title> 
    <link>http://cse.csusb.edu/</link>  
    <description>Come here, go any where.</description> 
   </item> 
</channel> 
</rss> 

Deploy the publisher application in the same manner that you deployed the website application and verify that you can access news.rss through your browser by going to http://localhost:8080/publisher/news.rss.

Finally, modify the url in the website project so that it points to your news feed in the publisher application. Verify that the website application is now displaying your news through the following link: http://localhost:8080/website/home. Remember to examine your log files if the application doesn't work as expected.

Note that the website application is communicating with the publisher application by sending XML over HTTP. This inter-application communication is a form of web services, and applications built in this way are said to follow a service-oriented architecture.

Exercises

(1) Include someone else's news

Modify the URL in HomeServlet so that you include another student's news into your home page.

(2) Display More Information

If you go to http://rss.news.yahoo.com/rss/tech in your browser, you will see the document that the website application retrieves. (You may want to select the View Source operation of your browser to see the XML document.) Notice the use of the pubDate field in each news item. Add a pubDate field to your news.rss file, and display the pubDate element in the home page of the website project by adding the following code to your home.jsp file.

   entry.getPublishedDate()

back next

Copyright 2007-2009 David Turner and Jinseok Chae. All rights reserved.