Groovy/Grails Talk
Home     Login     Register
Saturday, 19 June 2010
Adding Feeds With Grails Plugins
I added some feeds to the CompareXY.com site (see some other blogs on the experiment). Technically, I already had one feed already, but I'll go over it anyway. Eventually, I think I'll support Atom, and add some feeds based upon tags, or searches, but for now I just created feeds for the blog (about building the site), the latest-n articles, and a site map.

Basically, the idea for creating feeds is:
  • Install RSS feed plugin
  • Make a shared service for getting articles
  • Make a feeds controller with a few actions for delivering the feeds including:

    • latest - For feeding the n latest articles
    • sitemap - For feeding the site map of the site
    • blogs - For feeding the world my incredible blog updates

  • Put some links on the site, and tell browsers how to handle them

  1. First, I installed the "feeds" plugin from Grails.org, http://grails.org/Feeds+Plugin. There is reasonable documentation on how to use the feeds plugin on the site, but basically:

     >grails install-plugin feeds

  2. Second, I created a SiteMap service, and added a method called "list":

    >grails create-service com.comparexy.services.SiteMap

    I will be able to re-use the "list" method for both the full site map feed, and for the latest-n feed. The list method accepts three arguments:

    • size - The maximum number of elements to list in feed. For instance, Google will only read 50,000 items in an RSS site map. If my site ever (which I am not holding my breath) gets within a magnitude of that, I'll adjust the controller to split the feeds up.
    • minState & maxState - Just a filter range that is specific to the articles. Basically, it ranges from Official, and Valid to Suggested, Flagged, and Garbage. I don't really need to feed Google a site map of the Garbage articles, so I'll filter them out. Also, the latest feeds will filter everything out that isn't marked as Official, so (assuming anyone ever subscribes) it isn't feeding merely Suggested articles, but just Official articles).


    Maybe fortunate, or unfortunately, I modeled the comparison articles to maintain their history by having multiple versions in the same database table. The latest article in the table that is marked Official by an editor (me) will be the version of the article that will be displayed when an article is requested. So, to get a list of unique articles, I need to group them by the article identifiers, and order them by their createdDate (as you can see in the HQL below).

    I am going to pass the HQL statement that I wrote to the GORM method, executeQuery(), that was injected into the Comparison domain object. I'll add additional filters, and the maximum number of records to return.

    (Sorry for putting the code in images, but blogger.com seems to be a bit a pain to keep code formatted)
    (Snippet from SiteMapService.groovy) SiteMap Service

    * Parenthetically, the first time I used executeQuery(), I mistakenly assumed it for something that executed a native SQL statement, rather than a GORM or HQL statement, as it looks like java.sql.Statement#executeQuery(). That was quickly rectified. If you want to execute native SQL in GORM, you'll have to create an instance of groovy.sql.Sql.


  3. Thirdly, I created a controller, and added a few actions for it including "latest", "sitemap", and "blogs":

    >grails create-controller com.comparexy.controllers.Feeds

    For the latest-n feed, I needed to pass in a number from the URL, or use a default value if a good number wasn't passed in. Since the path to the feeds was already organized by Grails default (i.e."/$controller/$action/$id"), I could have just gone with that, but I figured it would be a bit clearer for me if I passed in a "num" parameter specifically instead of the "id" parameter. To do this, I updated the /conf/UrlMappings.groovy file with an entry that points to this controller, and action, but names the third parameter $num:

    (Snippet from UrlMapping.groovy)

    In the "latest" action (see code below):

    • I take the param.num that I set up in the UrlMapping.groovy above, and make it a reasonable integer that I can use.
    • I call the siteMapService.list() method, and load up some results with Official comparison articles.
      • The service's list method takes a range of states, and in this case, the upper and lower bounds ofthe range are both Official identified with the constant STATE_OFFICIAL.

    • I broke up the URL that I will eventually pass to the "feeds" service, into parts (mainly so it would fit into a screen shot) with the base, and path variables.

    Now the meat of the feeds: I pass the values for feedType, and feedVersion into the controller's render method. I hard-code the those values for RSS, but I could have (and I will be doing a little refactoring here shortly) passed in a "feedType" argument to the action, and dynamically set this to be an Atom, ROME, or ITunes feed rather than RSS. The "feeds" plugin defines a Builder DSL, which I used to define the content of the feed such as title, link (of the feed), and description. Then, for each record that I received from the SiteMap service, I add an entry element in the Builder DSL. The entry method takes a title inside it's parenthesis, and inside of the closure, you set the author, publishedDate, and link. For my title, I used the terms from the comparison like "This vs That".

    (Snippet from FeedsController.groovy)


    To the above controller, I also added an action for both sitemap, and blogs. The "sitemap" action uses the same SiteMap service method that "latest" action uses. The "blogs" action just used the Gorm DomainObject.list() method with a couple of properties for sorting: Blog.list(sort: 'dateCreated', order: 'desc' )

  4. So, that was fairly easy so far. The hardest thing was deciding what I wanted to put into the feed. Now I need to share the feed with the world by putting some links on my site.

    Before I put the links back to the appropriate actions, I used the feeds plugin's <feed:meta...> tags for assisting me in telling the browser the content type to expect at the other end of the RSS links. Again, I could have done this dynamically, and placed Atom, ROME, or ITunes in, but here I hard-coded RSS. I placed these in the <head...> tag of my main.gsp layout file.

    Snippet from main.gsp layout


    The output from the above feeds tags on the source code of the rendered web pages is as follows below:

    Snippet output from the what the above <feed:meta...> tags created


    Now, when I put the following orange feed squares links in my page as below, the browser will recognize the same URL that is referenced in the tag, and know that the intention is render the content at the other end of the link as a feed, and not as the plain XML that is delivered to the browser.RSS feeds to the site blog (left), and to the latest 20 articles (right)



    RSS feed to the sitemap for Google (and maybe other search engines if they accept RSS)


    Ok, it took me longer to write this blog than it did to add the feeds.

Posted by Doug DesCombaz at 02:03 PM
in Plug-ins
Send This Post To Your Friends
   
Your Email *
Your Name *
Send To *

Separate multiple addresses with commas.
Personal Message
  A copy of the message will be sent to your address.
 
Captcha
  If you were logged in, you would not have to enter the captcha.
 
All starred fields are required.
sun mon tue wed thu fri sat
    1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30   

Latest Posts
Archives
Categories
Bookmarks
Authors
Search
Syndicate This Site
Add to Technorati Favorites