![]() | Monkeys at Keyboards: Java-Fu © Michael James Heron | ||||
| Topic: Java Programming Level: 3 Version: beta | |||||
9 - Case Study 3 - Really Simple Syndication | |||||
| Previous | Table of Contents | Next |
| Forum |
| Chapter Objectives |
By the end of this chapter, the reader will be able to: |
In this case study, we are going to take what we have learned about XML, SAX and JavaBeans, and build our first genuinely useful bean - in this case, it will be an RSS parser bean. We will also look at incorporating a bean that someone else has written into our own component. RSS is an acronym for Really Simple Syndication, and it is very widely used amongst news agencies to allow for remote web-sites to provide up-to-date news headlines. The RSS standard carries with it a headline, a short description of the story, and a hyperlink address that will take the interested party to a fuller description of the story. There are many different versions of the RSS standard - we will be looking at version 0.91, which is used by the British Broadcasting Corporation. A list of references will be provided at the end of this chapter for the student who wishes to investigate further.
We're going to need an XML document - and if we want our bean to provide up-to-date news, it's going to have to come from an internet resource. Luckily, during the course of the Javanomicon we looked at how to make a connection with a remote internet resource through the use of URL objects. We'll be making use of that knowledge through the course of this case study. We need an object that will parse the XML file we download and turn it into a suitable data structure. This will make use of the SAX parsing model as we discussed in chapter four. We will take the XML file into the parser object, and return an ArrayList of NewsItem objects. We need a front-end to our component - the thing that our user will interact with. This needs to display the headline, the short description, and a button for the user to click to bring up the full news page. And of course, we need some way to provide said news page - there is no simple way to set one of these up in Java so we will forgo the 'roll your own' strategy and make use of a component someone has already written for us. And finally, we need to connect all of this up into a component that anyone can drop into their Java programs. Does that sound difficult? Pah, it'll be a piece of cake and you know it. Have I ever lied to you? You know, so far? In this chapter?
We'll start off nice and simple, and concern ourselves just with actually reading the XML file from the appropriate website. We'll write a class to do this for us - XmlLoader. Remember the principles of good OO design - we should separate out functionality as much as possible to ensure maximum reusability. Loading an XML file from an external source is a very common process, and one that benefits well from having a class dedicated to it. The process for setting up a URL connection to an internet file is detailed in chapter 20.3 of the Javanomicon - but I will summarise it here for the sake of a reminder.
However, as far as XML parsing goes, we don't need to perform the last two steps - the parse method of the SAXParser takes an InputStream as its first parameter. So, the code for our XmlLoader looks like this:
There's nothing in here that isn't Old Territory that we covered in the Javanomicon, so let's not spend any more time on this when we could be getting on with the interesting stuff!
Once we have a connection to our XML file, it becomes our job to parse it - we need to build a parser class for this, using the same techniques we discussed in the last chapter. First we create a skeleton class that imports the correct packages and extends the DefaultHandler class:
For this particular class, we're going to pass the InputStream we created within our XmlLoader class as a parameter to the constructor - we'll use this as the basis of our parse method call:
Within our constructor, we create a new instance of the SAXParserFactory object by calling the static method newInstance on the SAXParserFactory class:
And then we call the method newSAXParser on the object we just created - this needs to go in a try-catch block to deal with the two mandatory acknowledgement exceptions:
And then, we call the parse method on our SAXParser object - in the previous chapter, we passed a File object as the first parameter. In this case study, we'll pass the InputStream object that we sent to the constructor. Putting it all together gives us the following constructor method for our RssParser class:
Tada! With this constructor, we've set ourselves up with an appropriate framework for parsing our XML document. All we need to do now is actually write the parsing methods and set up a class that is suitable for holding the information we extract.
Much as we did with the example XML file in the previous chapter, we'll extract all the useful information from the file and create an instance of a class to hold all the details. In this case, it will be an instance of a NewsItem class that contains the headline, the description, and the URL where more information can be found:
Our XML parser will return an ArrayList of instances of this class - we'll then be able to pick whichever we want to display in the Bean... but more on that when we get to it.
Before we go any further, let's take a look at what an RSS file actually looks like - we'll pull one from the BBC website and take a look at a stripped-down version of its contents:
As you can see, it's a little bit more complicated than our simple example from the last chapter, but it's not so different that we can't see how to parse it. In this chapter, we'll only look at parsing the item elements into objects - we're not particularly interested in the rest of the information since that's all just variation on a theme. Note here an example of a problem we discussed in the last chapter - that of name collisions:
Since we don't define the XML file, we cannot resolve this problem through the use of namespaces. Also, since we're not interested in parsing out the image information, we don't need to maintain a stack that indicates the complete element path we're following... instead, when we encounter an open tag for item, we'll simply set a boolean variable to true. When we encounter the closing tag, we'll set it to false. We'll base our startElement extraction on this simple routine.
We've already set up a framework for our XML parser - we just need to over-ride the appropriate methods so that it actually does something useful. You will undoubtedly remember from the last chapter that these methods are startElement, endElement, startDocument, endDocument and characters. In fact, we only need to over-ride three of these methods - we don't really care when we reach the start or end of a document. We just care when we reach the start and end of tags. First of all, we're going to set up a StringBuffer to catch everything sent into the characters method. We're also going to set up the boolean variable that we alluded to above. To the framework RssParser class we created above, we add the following code:
Does that look familiar? It should! It's practically the same code that we used in the chapter on XML... once you have the technique, it's adaptable (with minor changes in structure) to any XML file you need to parse. All you need to know is what you are going to do with the tags when you encounter them. At the end of this parsing process, we get an ArrayList that contains all of our parsed news items... with this, we can do whatever we like. Our job of parsing out the XML is accomplished... now we just need to tie it all up into an appropriate JavaBean.
We've extracted the raw information that we need to build our bean - but we need to make some decisions on how the bean is actually going to be displayed and what properties we are going to expose. The most obvious property is what feed we are going to use - we'll call this property RssFeed. When it is set, we'll create an instance of our XmlLoader class and create the InputStream we need. We'll then create an instance of our RssParser class, using this InputStream as the constructor parameter:
Now we need to make some design decisions - particularly, how are we going to display the news stories? We're not creating a bean that anyone is going to pay money for, so let's stick to first principles. We'll want a JLabel for the headline, and a JTextArea for the description. We'll worry about the link later. We'll also place the description JTextArea into a JScrollPane, just in case it's too big to fit onto a single line. Rather than go for a complicated display (like for example, a scrolling ticker-tape), we'll just have a timer control that steps through each element of the news after a given interval:
And now, to tie it into an application:
Now we compile and execute, and what we get is a simple news ticker bean that can be slotted into any application. Neato!
We're not done yet, of course - we need to provide some hyperlink functionality before we can find an end to our labours.
Now that we've got our headline and our description, we need to provide some functionality for bringing up the more detailed internet page. There's no standard component in the base Java packages for rendering an HTML document, so we'll need to either write something ourselves (ouch! That sounds like a lot of work), or make use of a component that someone else has written (say, that sounds like what SMRT people like us should do!). In fact, the lovely people over at Sun have provided just such a component called the IceBrowserBean... it can be found at the link provided at the end of the chapter. We're going to be making use of this JavaBean to provide us with the web-browser functionality that our component is currently lacking. The Bean comes as a Jar file - see your notes from APE Antics for information on how to make this available in your own projects. Once it's been added into JCreator, we make it available within our own code by importing the appropriate package:
This is a complex component, but it's created in the same way as any other Java component - we create an instance of the component (which is called Browser), and then we decide how it is going to be displayed. We could add it to our current bean, but that's not very neat - sometimes we're not interested in the story... really, we only want the proper web-page to be displayed when we indicate our interest. Perhaps by pressing a button! We can make use of a multi-frame model here to pop up a window containing the new story... we just need to make a new class that extends JFrame and incorporates an instance of the Browser class:
The documentation that comes along with the browser component details some of the methods that go with the browser - really, there is only one that matters to us - it is called gotoLocation and takes a string parameter indicating the URL. We'll add a method to our new class that lets us set the appropriate location:
Now all we need to do is add a button to our bean display, and then display an instance of our new class whenever the button is pressed. Believe it or not, that will give us all the functionality we require to render HTML pages!
And now, whenever we press the button, it flashes up a web-page that contains the details of the story:
And that's it - a fully featured (well...) RSS news ticker, written entirely by our good-selves... with a little help from component based solutions. Not too shabby!
Hopefully this chapter has demonstrated the power of component based programming - perhaps not as far as the XML and JavaBean elements are concerned, but certainly as far as integrating other components into our own programs. We have created a genuinely useful JavaBean in this case study - something that can easily be incorporated into other applications to provide constant updates on the day's news. RSS is one of those standards that is taking the web by storm - most 'web communities' have at least one RSS feed that provides their users with a constant source of new information. Most news outlets have an RSS feed that they provide free of charge - all of this is made possible through the use of XML, which allows for a profoundly compatible data file to be easily parsed into genuine information.
Exercise OneOur bean is beautiful, but it could be more so - provide properties for configuring all pertinent aspects of the display such as background colour, fonts and so on. Exercise TwoProvide buttons for stepping forwards and backwards through the archive of news items. Exercise ThreeChoose a different newsfeed - for example, http://slashdot.org/index.rss. Consider the differences in layout and tags... does this offer a more difficult challenge for parsing than the example BBC feed? Further ReadingThe following table details further reading on the topic in this chapter, and also any external resources that you may find useful.
|
| Previous | Table of Contents | Next |
© 2004-2006 Michael James Heron