Customizing your application

In this tutorial, we will create objects that will search for stock prices and update the entities. Two classes will be generated:

  • core/src/main/java/tutorial/StockPriceRefresher.java
  • core/src/main/java/tutorial/StockPriceSearcher.java

StockPriceSearcher.java

This class searches for stock prices using the Yahoo Finance API.

public class StockPriceSearcher {
    private static final String NOT_FOUND = "Not found";
    //    private static Set<String> queries = new ConcurrentSkipListSet<String>();
    private static Set<String> queries = new CopyOnWriteArraySet<String>();
    private static Map<String, String> prices =
            new ConcurrentHashMap<String, String>();

    public StockPriceSearcher() {
        StockPriceRefresher refresher = new StockPriceRefresher(this);
        new Thread(refresher).start();
    }

    /**
     *
     * @param mnemonic
     * @return stock price, in numerical format
     */
    public BigDecimal getNumericalPrice(String mnemonic) {
        if (!prices.containsKey(mnemonic)) {
            return null;
        } else {
            String value = prices.get(mnemonic);
            if (value.equals(NOT_FOUND)) {
                return null;
            } else {
                return new BigDecimal(value);
            }
        }
    }

    /**
     *
     * @param mnemonic
     * @return the price of a stock, if available. If a search had
     * been not executed for a given mnemonic, return "Searching".
     */
    public String getPrice(String mnemonic) {
        if (prices.containsKey(mnemonic)) {
            return prices.get(mnemonic);
        } else {
            return null;
        }
    }

    /**
     * The stock identified by mnemonic will be put into a queue and later its 
     * price will be retrieved.
     *
     * @param mnemonic stock identifier
     */
    public void putQuery(String mnemonic) {
        queries.add(mnemonic);
    }

    /**
     * Search the stock price of all stocks that have been included using putQuery method
     */
    public void update() {
        StringBuilder query = new StringBuilder();

        Iterator<String> iterator = queries.iterator();

        if (queries.size() == 0) {
            return;
        } else {
            query.append(iterator.next());

            while (iterator.hasNext()) {
                query.append(",");
                query.append(iterator.next());
            }
        }

        String stockMnemonics = query.toString();

        searchStocks(stockMnemonics);
    }

    /**
     * Process a single stock, retrieving its price
     * @param stockMnemonics
     */
    private void searchStocks(String stockMnemonics) {
        try {
            URL url = new URL((new StringBuilder())
                    .append("http://query.yahooapis.com/v1/public/yql?q=")
                    .append("select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in%20(%22")
                    .append(stockMnemonics)
                    .append("%22)%0A%09%09&diagnostics=true&env=http%3A%2F%2Fdatatables.org%2Falltables.env")
                    .toString()
            );

            InputStream xmlStream = url.openStream();
            BufferedReader in = new BufferedReader(new InputStreamReader(xmlStream));

            SAXBuilder builder = new SAXBuilder();
            Document document = (Document) builder.build(in);
            Element rootNode = document.getRootElement();
            Element resultList = rootNode.getChild("results");
            List quoteList = resultList.getChildren("quote");

            prices.put("mnemonic", NOT_FOUND);

            for (int i = 0; i < quoteList.size(); i++) {
                Element node = (Element) quoteList.get(i);

                String key = node.getAttribute("symbol").getValue();
                String value = node.getChildText("Bid");
                if (!value.equals("")) {
                    prices.put(key, value);
                }
            }
        } catch (Exception e) {
            prices.put("mnemonic", NOT_FOUND);
        }
    }
}

StockPriceRefresher.java

This class calls StockPriceSearcher every 10 seconds.

public class StockPriceRefresher implements Runnable {

    private static final long SLEEP_MSEC = 10000;

    private StockPriceSearcher searcher;

    public StockPriceRefresher(StockPriceSearcher searcher) {
        this.searcher = searcher;
    }

    /**
     * Search for stock prices, every SLEEP_MSEC milisseconds.
     */
    public void run() {
        while (true) {
            try {
                searcher.update();

                Thread.sleep(SLEEP_MSEC);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}