Ich liebe Spring – mein eigener RSS Feed mit Java

3 Kommentare

Der Blog handelt ĂŒber ein kleines privates Projekt, passt aber hervorragend zum Firmen-Blog. Die Kernaussage des Blogs: Ich liebe Spring! 😉
News lese ich am liebsten ĂŒber meinen Google Reader. Mein Ziel ist es, so viele Informationen wie möglich ĂŒber diesen Kanal zu beziehen. Ich mag diesen Kanal, weil er viele andere KanĂ€le bĂŒndelt und mir die Informationen asynchron anbietet. Das heißt, ich kann jederzeit, z.B. beim Warten auf den Bus auf die Informationen zugreifen („pull“) ohne jedoch stĂ€ndig von neuen Informationen gestört zu werden („push“). Leider sind nicht alle Informationen ĂŒber RSS verfĂŒgbar. In der Vergangenheit habe ich mich daher des Öfteren mit frei verfĂŒgbaren RSS-Convertern o.Ä. beschĂ€ftigt. Hier ein paar Beispiele: FreeMyFeed, mmmmail.com oder eine Lösung fĂŒr eine Twitter-zu-RSS-Konvertierung. Keine Lösung konnte mich so richtig ĂŒberzeugen und deckte alle Aspekte ab. Dann dachte ich: Ich bin Programmierer, warum mach ich es nicht einfach selbst?!

Ich hĂ€tte hunderte Ideen, welche Informationen ich gerne in meinem Reader lesen wĂŒrde. Hier zwei Beispiele, die ich zuerst umgesetzt habe:

  • Ich bin ein Geocacher und wĂŒrde gerne ĂŒber neue Kletter-Geocaches in der Umgebung informiert werden. Geocaching.com bietet Benachrichtigungen fĂŒr neue Caches in Form von E-Mails an. In diesen E-Mails findet man dann einen Link zum Geocache und dort kann man herausfinden, ob es sich um einen Kletter-Geocache handelt. Diese manuelle Arbeit stört und ich will natĂŒrlich keine E-Mails, sondern EintrĂ€ge in meinem Google Reader.
  • Ich wĂŒrde gerne neue Tweets in meinem Google Reader lesen. Twitter ermöglicht nur das abonieren der Tweets eines einzelnen Users per RSS. Dazu muss man sogar authentifiziert sein, da einige Benutzer ihre Tweets schĂŒtzen. Google Reader unterstĂŒtzt leider keine Authentifizierung fĂŒr RSS Feeds. ZusĂ€tzlich möchte ich gerne alle Tweets in einem Feed lesen und ich möchte nach ein paar eigenen Regeln bestimmte Tweets filtern (z.B. Re-Tweets oder “I just became the mayor of…”-Tweets 😉 ). Noch dazu wĂŒrde ich gerne verlinkte Bilder sofort im Google Reader sehen können. Ganz unterschiedliche Anforderungen…

Also startete ich ein kleines Projekt. Hier ist das Protokoll einer Woche mit 7 schönen Spring-Abenden 🙂

  • Abend 1 – Veröffentlichen von einigen Beispieldaten ĂŒber RSS
    Projekt-Setup mit Maven, initiale Konfiguration von Spring MVC mit einem Controller und einer View basierend auf AbstractAtomFeedView – Ein kleines bißchen Request-Mapping, das erzeugen von Beispieldaten im Controller und – JA! – nach dem Tomcat-Start und dem Aufruf der URL fragt mein Chrome mich, ob ich den neuen Feed mit dem Google Reader abonieren möchte. NatĂŒrlich – Ohne Sinn, noch handelt es sich ja schließlich um localhost 🙂

    @Override
    protected void buildFeedMetadata(Map<String, Object> model, Feed feed, HttpServletRequest request) {
    

    @Override
    protected List<Entry> buildFeedEntries(Map<String, Object> model, HttpServletRequest request, HttpServletResponse response) throws Exception {
  • Abend 2 – Entfernen der Beispieldaten und Anzeige von Mails aus meinem Google-Mail Postfach
    Der Zugriff auf mein Google-Mail Postfach funktioniert sehr einfach mit dem ImapMailReceiver von Spring Integration. Ich lese dabei nur Mails zu meinem „toRSS“-Label aus, welches ich in meinem Google Konto konfiguriert habe. Zusammen mit ein paar einfachen Filter-Regeln ist dies alles was ich benötige.

    Message[] messages = mailReceiver.receive();
  • Abend 3 – Erzeugen von lesbarem Text aus javax.mail.Message und Auswertung von Nachrichten
    Lesbaren Text aus javax.mail.Message zu generieren war fĂŒr mich eher frustrierend (MultiPart, BodyPart, usw
). Gibt es dazu ein gutes Tool oder ein Framework? Denoch konnte ich nach der Konvertierung an der eigentlichen Auswertung meiner Nachrichten ganz nach meinen eigenen Vorgaben arbeiten. Zum Beispiel muss ich jeden Link zu einem Geocache öffnen, um die HTML-Beschreibung zu erhalten und zu ermitteln, ob es sich um einen Kletter-Geocache handelt. Diese Regeln habe ich sehr oft geĂ€ndert. Es ist toll mal sein eigener Product-Owner zu sein! 🙂

  • Abend 4 – Persistenz!
    Spring Integration’s ImapMailReseiver liest jede Mail nur einmal aus dem Google-Postfach. Das macht natĂŒrlich Sinn. Ich möchte Daten aus vielen Quellen sammeln und diesen Aspekt von der Bereitstellung der Daten ĂŒber die View trennen. Also mĂŒssen die gesammelten Daten in der Zwischenzeit persistiert werden. Zeit fĂŒr Mongo DB und Spring Data. Super! Wieder eine sehr, sehr einfache Sache. Ich benutze ein einfaches CrudRepository von Spring Data fĂŒr Mongo DB. Setup und Speichern der ersten Werte war in 30 Minuten erledigt. Wieder ein bißchen Refactoring, einige neue Interfaces, einige Modell-Klassen (RssContent, RssContentProvider) und meine Software konnte Mails lesen, den verarbeiteten Inhalt in einer MongoDB speichern und den Inhalt spĂ€ter ĂŒber einen RSS Feed ausliefern.

    public interface RssContentRepository extends CrudRepository<RssContent, String> {
    	List<RssContent> findByUserAndFeed(String user, String feed);
  • Abend 5 – Zeitgesteuerter Aufruf der Content-Provider, Twitter
    Wie schon in Schritt 4 beschrieben soll das Sammeln der Daten getrennt von deren Anzeige passieren und nicht mit einem neu eintreffenden HTTP-Request ausgelöst werden. Also muss der Aufruf der Daten-Sammler zeitgesteuert erfolgen. Und – natĂŒrlich – auch dies ist mit Spring sehr einfach. Alle ContenProvider in einem neuen SchedulerService „autowiren“, eine Methode deklarieren, dort alle ContentProvider aufrufen und diese Methode mit Spring’s @Scheduled anotieren.

    @Scheduled(fixedRate = 1000 * 60 * 60)
    public void executeAll() {
    	for (ContentProvider contentProvider : contentProviderList) {
    		List<RssContent> content = contentProvider.getContent();
    		contentRepository.save(content);
    		...

    Danach war noch Zeit fĂŒr meinen Twitter-ContentProvider. Dazu benutze ich Spring Social’s Twitter-Api um alle Tweets meiner Timeline zu lesen. Auch hier war es wieder schön, mein eigener Product Owner zu sein und die Tweets beliebig zu filtern und zu bearbeiten.

    List<Tweet> timeline = twitter.timelineOperations().getHomeTimeline(1, 200, lastTweetId, 0);
  • Abend 6 – Ersetzen von „localhost“
    Leider lĂ€uft der Google Reader nicht auf meinem localhost. Also muss meine Anwendung irgendwo in einen öffentlichen Bereich deployed werden. Na klar, Spring hilft – Cloud Foundry. Da ich von Anfang an die Springsource Toolsuite benutzte, war das Deplyoment in die Cloud genauso leicht, wie ein Deployment in meinen lokalen Tomcat. MongoDB wird als Service innerhalb von CloudFoundry bereitgestellt. Die einzige Änderung war die Erstellung eines Spring-Profils, welches eine andere mongo-db-factory benutzt. Anschließend habe ich dann noch meinen SchedulerService mit @Profile(„cloud“) annotiert, damit in meiner lokalen Entwicklungsumgebung keine automatische Datenverarbeitung stattfindet.

  • Abend 7 – Refactoring
    Zu diesem Zeitpunkt lieferte meine Anwendung nur einen einzelnen RSS-Feed. Der richtige Zeitpunkt um einen genaueren Blick auf das Spring MVC-path mapping zu werfen. Die folgenden drei Zeilen und einige zusÀtzliche Informationen aus der Mongo-DB ermöglichen mehrere User und mehrere Feeds. User und Feed werden dabei beim Ablegen in die Mongo-DB vom jeweiligem ContentProvider gesetzt.

    @RequestMapping(value = "/user/{user}/feed/{feed}", method = RequestMethod.GET)
    public ModelAndView getFeedContent(@PathVariable String user, @PathVariable String feed) {
    	Iterable<RssContent> content = contentRepository.findByUserAndFeed(user, feed);
    	...

Fazit: Spring ist genial! Spring hilft einem Entwickler in nahezu allen Bereichen. In meinem Beispiel habe ich Spring Core, Spring MVC, Spring Data, Spring Social, Spring Integration und natĂŒrlich CloudFoundry genutzt. Man findet zu allen Bereichen immer gute Dokumentationen und Beispiele oder man wendet sich an die riesige Community. Alle oben beschriebenen Schritte waren in wenigen Stunden umgesetzt. Man muss nicht jede Technologie bis in die Tiefe verstehen, um mit Spring schnell erste Ergebnisse erzielen zu können. Wenn es im Projekt dann aber zur Sache geht, sollte man als professioneller Entwickler auch die zugrunde liegenden Basistechnologien beherrschen. Das erspart böse Überraschungen im Projektverlauf.

Tags

Daniel Reuter

Daniel gehört seit April 2009 zum Team der codecentric. Seine Schwerpunkte liegen in der Entwicklung von Enterprise-Anwendungen im Versicherungsumfeld. Daniel ist Allroundcodehacker, Architekturgedankenpfleger, Sauberkeitsprogrammierenthusiast, Teamzusammenarbeitshelfer und VersicherungsfachdomÀnenfreund.

Share on FacebookGoogle+Share on LinkedInTweet about this on TwitterShare on RedditDigg thisShare on StumbleUpon

Kommentare

  • Mirko Novakovic

    14. Juni 2012 von Mirko Novakovic

    Cool. Hast Du die Sourcen in GitHub?

    • Daniel Reuter

      Nein, leider nicht. Die implementierten Regeln sind doch sehr individuell auf meine BedĂŒrfnisse zugeschnitten und meine Passwörter zu Google, Twitter und Co sind auch in den Konfigurationen zu meinen ContentProvidern zu finden 😉 Wenn Interesse besteht, kann ich aber mal den Infrastruktur-Teil dort ablegen.

  • Eric Bredtmann

    Hi Daniel,

    Echt cooler Beitrag!
    Muss mir auch mal bei Gelegenheit die ToolSuite und Spring Integration etwas nÀher anschauen.

    Gruss,
    Eric

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.