[ Team LiB ] Previous Section Next Section

Recipe 26.3 Creating a JavaBean as a Web Page Parser

Problem

You want to create a JavaBean that web components can use to parse an HTML page.

Solution

Use the Java API classes for parsing HTML from the javax.swing.text subpackages. Store the JavaBean in WEB-INF/classes or in a JAR placed inside WEB-INF/lib.

Discussion

Example 26-4 is a JavaBean whose sole purpose is to parse a web page for live stock quotes. A servlet or JSP can use this JavaBean for its special purpose, and thus avoid the clutter of taking on the parsing responsibility itself. All of the code, including the inner class representing a ParserCallback, is reproduced from this chapter's earlier recipes. What's new is the setter or mutator method for the bean's stock symbol: setSymbol(String symbol).

Example 26-4. A JavaBean for use with servlets and JSPs
package com.jspservletcookbook;  

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.MalformedURLException;

import javax.swing.text.html.HTMLEditorKit.ParserCallback;
import javax.swing.text.MutableAttributeSet;
import javax.swing.text.html.parser.ParserDelegator;

public class StockPriceBean {

     private static final String urlBase =  "http://finance.yahoo.com/"+
     "q?d=t&s=";
    
     private BufferedReader webPageStream = null;
     
     private URL stockSite = null;
    
     private ParserDelegator htmlParser = null;
    
     private MyParserCallback callback = null;

     private String htmlText = "";
     private String symbol = "";
     private float stockVal = 0f;

  public StockPriceBean( ) {}
        
  //Setter or mutator method for the stock symbol
  public void setSymbol(String symbol){
      this.symbol = symbol;
  }
   
  class MyParserCallback extends ParserCallback {

      //bread crumbs that lead us to the stock price
      private boolean lastTradeFlag = false; 
      private boolean boldFlag = false;
  
    public MyParserCallback( ){
      //Reset the enclosing class' instance variable
          if (stockVal != 0)
          stockVal = 0f;
         }
        
    public void handleStartTag(javax.swing.text.html.HTML.Tag t,
      MutableAttributeSet a,int pos) {
        if (lastTradeFlag && (t == javax.swing.text.html.HTML.Tag.B )){
            boldFlag = true;
       }
        
    }//handleStartTag

    public void handleText(char[] data,int pos){
        htmlText  = new String(data);
        if (htmlText.indexOf("No such ticker symbol.") != -1){
                throw new IllegalStateException(
                  "Invalid ticker symbol in handleText( ) method.");
        }  else if (htmlText.equals("Last Trade:")){
            lastTradeFlag = true;
        } else if (boldFlag){
            try{
                
                stockVal = new Float(htmlText).floatValue( );
            } catch (NumberFormatException ne) {
                try{
                    // tease out any commas in the number using 
                    //NumberFormat
                    java.text.NumberFormat nf = java.text.NumberFormat.
                      getInstance( );
                    Double f = (Double) nf.parse(htmlText);
                    stockVal =  (float) f.doubleValue( );
                } catch (java.text.ParseException pe){
                     throw new IllegalStateException(
                            "The extracted text " + htmlText +
                         " cannot be parsed as a number!");
                 }//try
            }//try
            
            lastTradeFlag = false;
            boldFlag = false;
                        
               }//if
      } //handleText

  }//MyParserCallback

  public float getLatestPrice( ) throws IOException,MalformedURLException {
      stockSite = new URL(urlBase + symbol);
      webPageStream = new BufferedReader(new InputStreamReader(stockSite.
       openStream( )));
      htmlParser = new ParserDelegator( );
      callback = new MyParserCallback( );//ParserCallback
      synchronized(htmlParser){        
          htmlParser.parse(webPageStream,callback,true);
          }//synchronized
          //reset symbol
          symbol = "";
     return stockVal;
  }//getLatestPrice

}//StockPriceBean

This bean resets the symbol instance variable to the empty String when it's finished fetching the stock quote. The MyParserCallback class resets the stockVal instance variable to 0, so that the previously attained stock price does not linger between different thread's calls to getLatestPrice( ).

Now let's see how a servlet and JSP use the bean.

See Also

Recipe 26.4 on using this JavaBean in a servlet; Recipe 26.5 on using the bean in a JSP.

    [ Team LiB ] Previous Section Next Section