Micronaut RSS

It eases the creation of RSS feeds with Micronaut

Version: 1.0.0

1 Installation

This project eases RSS 2.0. feeds generation with Micronaut.

compile 'io.micronaut.configuration:micronaut-rss:1.0.0'
<dependency>
    <groupId>io.micronaut.configuration</groupId>
    <artifactId>micronaut-rss</artifactId>
    <version>1.0.0</version>
</dependency>

To use the BUILD-SNAPSHOT version of this library, check the documentation to use snapshots.

Code can be found at the micronaut-rss repository.

2 RSS 2.0

This modules exposes a controller FeedController which exposes feeds as described by RSS 2.0 Specification.

The following table displays several characteristics which can be configured:

🔗
Table 1. Configuration Properties for FeedControllerConfigurationProperties
Property Type Description

micronaut.rss.enabled

boolean

Whether FeedController should be enabled. Default value (true).

micronaut.rss.path

java.lang.String

Configures FeedController path. Default value "/feed"

FeedController requires two beans to be present RssFeedProvider and RssFeedRenderer. While DeafultRssFeedRenderer provides a default implementation for RssFeedRenderer, you will need to provide an implementation for RssFeedProvider.

For example, if you wanted to generate a feed as the one described in the RSS 2.0 specifiation’s sample you could create the next bean:

@Singleton
class MockRssFeedProvider implements RssFeedProvider {
    RssChannel rssChannel = RssChannel.builder("Liftoff News", "http://liftoff.msfc.nasa.gov/", "Liftoff to Space Exploration.")
            .language(RssLanguage.LANG_ENGLISH_UNITED_STATES)
            .pubDate(ZonedDateTime.of(LocalDateTime.of(2003, 6, 10, 4, 0, 0), ZoneId.of("GMT")))
            .lastBuildDate(ZonedDateTime.of(LocalDateTime.of(2003, 6, 10, 9, 41, 1), ZoneId.of("GMT")))
            .docs("http://blogs.law.harvard.edu/tech/rss")
            .generator("Weblog Editor 2.0")
            .managingEditor("editor@example.com")
            .webMaster("webmaster@example.com")
            .item(RssItem.builder()
                .title("Star City")
                .link("http://liftoff.msfc.nasa.gov/news/2003/news-starcity.asp")
                .description("How do Americans get ready to work with Russians aboard the International Space Station? They take a crash course in culture, language and protocol at Russia's &lt;a href=\"http://howe.iki.rssi.ru/GCTC/gctc_e.htm\"&gt;Star City&lt;/a&gt;.")
               .pubDate(ZonedDateTime.of(LocalDateTime.of(2003, 6, 3, 9, 39, 21), ZoneId.of("GMT")))
                .guid("http://liftoff.msfc.nasa.gov/2003/06/03.html#item573")
                .build())
            .item(RssItem.builder()
                .description("Sky watchers in Europe, Asia, and parts of Alaska and Canada will experience a &lt;a href=\"http://science.nasa.gov/headlines/y2003/30may_solareclipse.htm\"&gt;partial eclipse of the Sun&lt;/a&gt; on Saturday, May 31st.")
                .pubDate(ZonedDateTime.of(LocalDateTime.of(2003, 5, 30, 11, 6, 42), ZoneId.of("GMT")))
                .guid("http://liftoff.msfc.nasa.gov/2003/05/30.html#item572")
                .build())
            .item(RssItem.builder()
                .title("The Engine That Does More")
                .link("http://liftoff.msfc.nasa.gov/news/2003/news-VASIMR.asp")
                .description("Before man travels to Mars, NASA hopes to design new engines that will let us fly through the Solar System more quickly.  The proposed VASIMR engine would do that.")
                .pubDate(ZonedDateTime.of(LocalDateTime.of(2003, 5, 27, 8, 37, 32), ZoneId.of("GMT")))
                .guid("http://liftoff.msfc.nasa.gov/2003/05/27.html#item571")
            .build())
            .item(RssItem.builder()
                .title("Astronauts' Dirty Laundry")
                .link("http://liftoff.msfc.nasa.gov/news/2003/news-laundry.asp")
                .description("Compared to earlier spacecraft, the International Space Station has many luxuries, but laundry facilities are not one of them.  Instead, astronauts have other options.")
                .pubDate(ZonedDateTime.of(LocalDateTime.of(2003, 5, 20, 8, 56, 02), ZoneId.of("GMT")))
                .guid("http://liftoff.msfc.nasa.gov/2003/05/20.html#item570")
                .build())
            .build();

    @Override
    public RssChannel fetch() {
        return rssChannel;
    }

    @Override
    public RssChannel fetchById(Serializable id) {
        if(id != null && id.equals("1")) {
            return rssChannel;
        }
        return null;
    }
}

3 Itunes Podcast RSS Feed

compile 'io.micronaut.configuration:micronaut-itunespodcast'
<dependency>
    <groupId>io.micronaut.configuration</groupId>
    <artifactId>micronaut-itunespodcast</artifactId>
</dependency>

An Itunes podcast feed, is a valid RSS 2.0 feed with additional tags.

For example, the following bean will generate the Itunes Podcast RSS Feed’s sample

@Singleton
public class DefaultRssFeedProvider implements RssFeedProvider {

    @Override
    public RssChannel fetch() {
        return ItunesPodcast.builder()
                .title("Hiking Treks")
                .link("https://www.apple.com/itunes/podcasts/")
                .language(RssLanguage.LANG_ENGLISH_UNITED_STATES)
                .copyright("&#8471; &amp; &#xA9; 2017 John Appleseed")
                .description("Love to get outdoors and discover nature&apos;s treasures? Hiking Treks is the show for you. We review hikes and excursions, review outdoor gear and interview a variety of naturalists and adventurers. Look for new episodes each week.")
                .subtitle("Find your trail. Great hikes and outdoor adventures.")
                .author("The Sunset Explorers")
                .subtitle("Find your trail. Great hikes and outdoor adventures.")
                .type(ItunesPodcastType.SERIAL)
                .owner(ItunesPodcastOwner.builder()
                        .name("Sunset Explorers")
                        .email("mountainscape@icloud.com")
                        .build())
                .image(RssChannelImage
                        .builder("Hiking Treks", "http://podcasts.apple.com/resources/example/hiking_treks/images/cover_art.jpg", "https://www.apple.com/itunes/podcasts/")
                        .build())
                .summary("Love to get outdoors and discover nature&apos;s treasures? Hiking Treks is the show for you. We review hikes and excursions, review outdoor gear and interview a variety of naturalists and adventurers. Look for new episodes each week.")
                .category(Arrays.asList(ItunesPodcastCategory.SPORTS_AND_RECREATION_OUTDOOR.getCategories()))
                .explict(false)
                .item(ItunesPodcastEpisode.builder("Hiking Treks Trailer")
                        .episodeType(ItunesPodcastEpisodeType.TRAILER)
                        .author("The Sunset Adventurers")
                        .subtitle("The Sunset Explorers share tips, techniques and recommendations for great hikes and adventures around the United States.")
                        .summary("The Sunset Explorers share tips, techniques and recommendations for great hikes and adventures around the United States.")
                        .description("The Sunset Explorers share tips, techniques and recommendations for great hikes and adventures around the United States.")
                        .contentEncoded("<![CDATA[The Sunset Explorers share tips, techniques and recommendations for great hikes and adventures around the United States. Listen on <a href=\"https://www.apple.com/itunes/podcasts/\">Apple Podcasts</a>]]>")
                        .enclosure(RssItemEnclosure.builder()
                                .length(498537)
                                .type("audio/mpeg")
                                .url("http://example.com/podcasts/everything/AllAboutEverythingEpisode4.mp3")
                                .build())
                        .guid("http://example.com/podcasts/archive/aae20160418.mp3")
                        .pubDate(ZonedDateTime.of(LocalDateTime.of(2016, 4, 12, 1, 15, 0), ZoneId.of("GMT")))
                        .duration("17:59")
                        .explicit(false)
                        .build())
                .item(ItunesPodcastEpisode.builder("Mt. Hood, Oregon")
                        .episodeType(ItunesPodcastEpisodeType.FULL)
                        .episode(4)
                        .season(2)
                        .title("S02 EP04 Mt. Hood, Oregon")
                        .author("The Sunset Explorers")
                        .subtitle("Tips for trekking around the tallest mountain in Oregon")
                        .summary("Tips for trekking around the tallest mountain in Oregon")
                        .description("Tips for trekking around the tallest mountain in Oregon")
                        .contentEncoded("Tips for trekking around the tallest mountain in Oregon")
                        .enclosure(RssItemEnclosure.builder()
                                .length(8727310)
                                .type("audio/x-m4a")
                                .url("http://example.com/podcasts/everything/mthood.m4a")
                                .build())
                        .guid("http://example.com/podcasts/archive/aae20170606.m4a")
                        .pubDate(ZonedDateTime.of(LocalDateTime.of(2016, 6, 06, 12, 0, 0), ZoneId.of("GMT")))
                        .duration("17:04")
                        .explicit(false)
                        .build())
                .item(ItunesPodcastEpisode.builder("Bouldering Around Boulder")
                        .episodeType(ItunesPodcastEpisodeType.FULL)
                        .episode(3)
                        .season(2)
                        .title("S02 EP03 Bouldering Around Boulder")
                        .author("The Sunset Adventurers")
                        .subtitle("We explore fun walks to climbing areas about the beautiful Colorado city of Boulder.")
                        .summary("We explore fun walks to climbing areas about the beautiful Colorado city of Boulder.")
                        .description("We explore fun walks to climbing areas about the beautiful Colorado city of Boulder.")
                        .image("http://example.com/podcasts/everything/AllAboutEverything/Episode2.jpg")
                        .contentEncoded("href=\"http://example.com/podcasts/everything/\"")
                        .enclosure(RssItemEnclosure.builder()
                                .length(5650889)
                                .type("video/mp4")
                                .url("http://example.com/podcasts/boulder.mp4")
                                .build())
                        .guid("http://example.com/podcasts/archive/aae20170530.mp4")
                        .pubDate(ZonedDateTime.of(LocalDateTime.of(2017, 5, 30, 13, 0, 0), ZoneId.of("GMT")))
                        .duration("06:27")
                        .explicit(false)
                        .build())
                .item(ItunesPodcastEpisode.builder("Caribou Mountain, Maine")
                        .episodeType(ItunesPodcastEpisodeType.FULL)
                        .episode(2)
                        .season(2)
                        .title("S02 EP02 Caribou Mountain, Maine")
                        .author("The Sunset Adventurers")
                        .subtitle("Put your fitness to the test with this invigorating hill climb.")
                        .summary("Put your fitness to the test with this invigorating hill climb.")
                        .description("Put your fitness to the test with this invigorating hill climb.")
                        .image("http://example.com/podcasts/everything/AllAboutEverything/Episode3.jpg")
                        .contentEncoded("href=\"http://example.com/podcasts/everything/\"")
                        .enclosure(RssItemEnclosure.builder()
                                .length(5650889)
                                .type("audio/x-m4v")
                                .url("http://example.com/podcasts/everything/caribou.m4v")
                                .build())
                        .guid("http://example.com/podcasts/archive/aae20170523.m4v")
                        .pubDate(ZonedDateTime.of(LocalDateTime.of(2017, 5, 23, 02, 0, 0), ZoneId.of("GMT")))
                        .duration("04:34")
                        .explicit(false)
                        .build())
                .item(ItunesPodcastEpisode.builder("Stawamus Chief")
                        .episodeType(ItunesPodcastEpisodeType.FULL)
                        .episode(1)
                        .season(2)
                        .title("S02 EP01 Stawamus Chief")
                        .author("The Sunset Adventurers")
                        .subtitle("We tackle Stawamus Chief outside of Vancouver, BC and you should too!")
                        .summary("We tackle Stawamus Chief outside of Vancouver, BC and you should too!")
                        .description("We tackle Stawamus Chief outside of Vancouver, BC and you should too!")
                        .contentEncoded("We tackle Stawamus Chief outside of Vancouver, BC and you should too!")
                        .enclosure(RssItemEnclosure.builder()
                                .length(498537)
                                .type("audio/mpeg")
                                .url("http://example.com/podcasts/everything/AllAboutEverythingEpisode4.mp3")
                                .build())
                        .guid("http://example.com/podcasts/archive/aae20170516.mp3")
                        .pubDate(ZonedDateTime.of(LocalDateTime.of(2017, 5, 16, 02, 0, 0), ZoneId.of("GMT")))
                        .duration("13:24")
                        .explicit(false)
                        .build())
                .item(ItunesPodcastEpisode.builder("Kuliouou Ridge Trail")
                        .episodeType(ItunesPodcastEpisodeType.FULL)
                        .episode(4)
                        .season(1)
                        .title("S01 EP04 Kuliouou Ridge Trail")
                        .author("The Sunset Adventurers")
                        .subtitle("Oahu, Hawaii, has some picturesque hikes and this is one of the best!")
                        .summary("Oahu, Hawaii, has some picturesque hikes and this is one of the best!")
                        .description("Oahu, Hawaii, has some picturesque hikes and this is one of the best!")
                        .contentEncoded("Oahu, Hawaii, has some picturesque hikes and this is one of the best!")
                        .enclosure(RssItemEnclosure.builder()
                                .length(498537)
                                .type("audio/mpeg")
                                .url("http://example.com/podcasts/everything/AllAboutEverythingEpisode4.mp3")
                                .build())
                        .guid("http://example.com/podcasts/archive/aae20160509.mp3")
                        .pubDate(ZonedDateTime.of(LocalDateTime.of(2017, 5, 10, 01, 15, 0), ZoneId.of("GMT")))
                        .duration("15:29")
                        .explicit(false)
                        .build())
                .item(ItunesPodcastEpisode.builder("Blood Mountain Loop")
                        .episodeType(ItunesPodcastEpisodeType.FULL)
                        .episode(3)
                        .season(1)
                        .title("S01 EP03 Blood Mountain Loop")
                        .author("The Sunset Adventurers")
                        .subtitle("Hiking the Appalachian Trail and Freeman Trail in Georgia")
                        .summary("Hiking the Appalachian Trail and Freeman Trail in Georgia")
                        .description("Hiking the Appalachian Trail and Freeman Trail in Georgia")
                        .contentEncoded("Hiking the Appalachian Trail and Freeman Trail in Georgia")
                        .enclosure(RssItemEnclosure.builder()
                                .length(498537)
                                .type("audio/mpeg")
                                .url("http://example.com/podcasts/everything/AllAboutEverythingEpisode4.mp3")
                                .build())
                        .guid("http://example.com/podcasts/archive/aae20160502.mp3")
                        .pubDate(ZonedDateTime.of(LocalDateTime.of(2017, 5, 3, 01, 15, 0), ZoneId.of("GMT")))
                        .duration("24:59")
                        .explicit(false)
                        .build())
                .item(ItunesPodcastEpisode.builder("Garden of the Gods Wilderness")
                        .episodeType(ItunesPodcastEpisodeType.FULL)
                        .episode(2)
                        .season(1)
                        .title("S01 EP02 Garden of the Gods Wilderness")
                        .author("The Sunset Adventurers")
                        .subtitle("Wilderness Area Garden of the Gods in Illinois is a delightful spot for an extended hike.")
                        .summary("Wilderness Area Garden of the Gods in Illinois is a delightful spot for an extended hike.")
                        .description("Wilderness Area Garden of the Gods in Illinois is a delightful spot for an extended hike.")
                        .contentEncoded("Wilderness Area Garden of the Gods in Illinois is a delightful spot for an extended hike.")
                        .enclosure(RssItemEnclosure.builder()
                                .length(498537)
                                .type("audio/mpeg")
                                .url("http://example.com/podcasts/everything/AllAboutEverythingEpisode4.mp3")
                                .build())
                        .guid("http://example.com/podcasts/archive/aae20160425.mp3")
                        .pubDate(ZonedDateTime.of(LocalDateTime.of(2017, 4, 26, 01, 15, 0), ZoneId.of("GMT")))
                        .duration("13:59")
                        .explicit(false)
                        .build())
                .item(ItunesPodcastEpisode.builder("Upper Priest Lake Trail to Continental Creek Trail")
                        .episodeType(ItunesPodcastEpisodeType.FULL)
                        .episode(1)
                        .season(1)
                        .title("S01 EP01 Upper Priest Lake Trail to Continental Creek Trail")
                        .author("The Sunset Adventurers")
                        .subtitle("We check out this powerfully scenic hike following the river in the Idaho Panhandle National Forests.")
                        .summary("We check out this powerfully scenic hike following the river in the Idaho Panhandle National Forests.")
                        .description("We check out this powerfully scenic hike following the river in the Idaho Panhandle National Forests.")
                        .contentEncoded("We check out this powerfully scenic hike following the river in the Idaho Panhandle National Forests.")
                        .enclosure(RssItemEnclosure.builder()
                                .length(498537)
                                .type("audio/mpeg")
                                .url("http://example.com/podcasts/everything/AllAboutEverythingEpisode4.mp3")
                                .build())
                        .guid("http://example.com/podcasts/archive/aae20160418a.mp3")
                        .pubDate(ZonedDateTime.of(LocalDateTime.of(2017, 4, 19, 01, 15, 0), ZoneId.of("GMT")))
                        .duration("23:59")
                        .explicit(false)
                        .contentEncoded("The Sunset Explorers share tips, techniques and recommendations for great hikes and adventures around the United States. Listen on <a href=\"https://www.apple.com/itunes/podcasts/\">Apple Podcasts</a>")
                        .build()).build();
    }

    @Override
    public RssChannel fetchById(Serializable id) {
        return null;
    }
}