grack.com

I’ve updated my prototype to use the excellent Rome feed parser library. Instead of dumping 20kB of ‘useful’ raw feed on you, it now formats the entries nicely.

I’ve hooked it up to deliver me real-time headlines from my Google Reader feed and from TechCrunch, both of which work flawlessly.

With all the building blocks I’ve strung together, this really wasn’t any work at all. All of the complexity lies in the cloud: Google’s AppEngine and XMPP implementation and the PubSubHubbub hub. The rest is done with a feed-parsing library.

Here’s the new code:

package com.grack.pubsubhubbub.xmpp;

import java.io.IOException;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.xmpp.JID;
import com.google.appengine.api.xmpp.MessageBuilder;
import com.google.appengine.api.xmpp.XMPPService;
import com.google.appengine.api.xmpp.XMPPServiceFactory;
import com.sun.syndication.feed.synd.SyndEntry;
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;

@SuppressWarnings("serial")
public class Subscribe extends HttpServlet {
    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp)
            throws ServletException, IOException {
        resp.setStatus(204);
        XMPPService xmpp = XMPPServiceFactory.getXMPPService();
        JID jid = new JID(req.getPathInfo().substring(1));

        SyndFeedInput input = new SyndFeedInput();
        SyndFeed feed;
        try {
            feed = input.build(new XmlReader(req.getInputStream()));
        } catch (IllegalArgumentException e) {
            throw new ServletException(e);
        } catch (FeedException e) {
            xmpp.sendMessage(new MessageBuilder().withBody(
                    "Feed exception: " + e.toString()).withRecipientJids(jid)
                    .build());
            throw new ServletException(e);
        }

        @SuppressWarnings("unchecked")
        List entries = feed.getEntries();

        StringBuilder message = new StringBuilder("Got update: \n");
        for (SyndEntry entry : entries) {
            message.append(entry.getTitle()).append(": ").append(
                    entry.getLink()).append('\n');
        }
        xmpp.sendMessage(new MessageBuilder().withBody(message.toString())
                .withRecipientJids(jid).build());
    }

    public void doGet(HttpServletRequest req, HttpServletResponse resp)
            throws IOException {
        resp.setStatus(200);
        resp.setContentType("text/plain");

        XMPPService xmpp = XMPPServiceFactory.getXMPPService();
        JID jid = new JID(req.getPathInfo().substring(1));

        if (req.getParameter("hub.mode").equals("subscribe"))
            xmpp.sendMessage(new MessageBuilder().withBody(
                    "Subscribing to " + req.getParameter("hub.topic"))
                    .withRecipientJids(jid).build());
        else
            xmpp.sendMessage(new MessageBuilder().withBody(
                    "Unsubscribing from " + req.getParameter("hub.topic"))
                    .withRecipientJids(jid).build());

        resp.getOutputStream().print(req.getParameter("hub.challenge"));
        resp.getOutputStream().flush();
    }
}
Read full post