Main Tutorials

Spring 3 MVC and RSS feed example

In Spring 3, comes with a abstract class “AbstractRssFeedView” to generate RSS feed view, using java.net’s ROME package. In this tutorial, we show you how to generate a RSS feed view from Spring MVC framework.

Technologies used :

  1. Spring 3.0.5.RELEASE
  2. ROME 1.0.0
  3. JDK 1.6
  4. Eclipse 3.6
  5. Maven 3

At the end of the tutorial, when you visit this URL – http://localhost:8080/SpringMVC/rest/rssfeed, browser will return following RSS feed content :


<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0">
  <channel>
    <title>Mkyong Dot Com</title>
    <link>https://mkyong.com</link>
    <description>Java Tutorials and Examples</description>
    <item>
      <title>Spring MVC Tutorial 1</title>
      <link>https://mkyong.com/spring-mvc/tutorial-1</link>
      <content:encoded>Tutorial 1 summary ...</content:encoded>
      <pubDate>Tue, 26 Jul 2011 02:26:08 GMT</pubDate>
    </item>
    <item>
      <title>Spring MVC Tutorial 2</title>
      <link>https://mkyong.com/spring-mvc/tutorial-2</link>
      <content:encoded>Tutorial 2 summary ...</content:encoded>
      <pubDate>Tue, 26 Jul 2011 02:26:08 GMT</pubDate>
    </item>
  </channel>
</rss>

1. Directory Structure

Review the final project structure.

directory structure

2. Project Dependencies

For Maven, declares following dependencies in your pom.xml.


	<properties>
		<spring.version>3.0.5.RELEASE</spring.version>
	</properties>

	<dependencies>

		<!-- Spring 3 dependencies -->
		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-core</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-web</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<dependency>
			<groupId>org.springframework</groupId>
			<artifactId>spring-webmvc</artifactId>
			<version>${spring.version}</version>
		</dependency>

		<!-- RSS -->
		<dependency>
			<groupId>net.java.dev.rome</groupId>
			<artifactId>rome</artifactId>
			<version>1.0.0</version>
		</dependency>

		<!-- for compile only, your container should have this -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>servlet-api</artifactId>
			<version>2.5</version>
			<scope>provided</scope>
		</dependency>

	</dependencies>

3. Model

A simple POJO, later use this object to generate the RSS feed content.


package com.mkyong.common.model;

import java.util.Date;

public class SampleContent {

	String title;
	String url;
	String summary;
	Date createdDate;

	//getter and seeter methods
}

4. AbstractRssFeedView

Create a class extends AbstractRssFeedView, and override the buildFeedMetadata and buildFeedItems methods, below code should be self-explanatory.


package com.mkyong.common.rss;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.web.servlet.view.feed.AbstractRssFeedView;
import com.mkyong.common.model.SampleContent;
import com.sun.syndication.feed.rss.Channel;
import com.sun.syndication.feed.rss.Content;
import com.sun.syndication.feed.rss.Item;

public class CustomRssViewer extends AbstractRssFeedView {

	@Override
	protected void buildFeedMetadata(Map<String, Object> model, Channel feed,
		HttpServletRequest request) {
		
		feed.setTitle("Mkyong Dot Com");
		feed.setDescription("Java Tutorials and Examples");
		feed.setLink("https://mkyong.com");
		
		super.buildFeedMetadata(model, feed, request);
	}
	
	
	@Override
	protected List<Item> buildFeedItems(Map<String, Object> model,
		HttpServletRequest request, HttpServletResponse response)
		throws Exception {
		
		@SuppressWarnings("unchecked")
		List<SampleContent> listContent = (List<SampleContent>) model.get("feedContent");
		List<Item> items = new ArrayList<Item>(listContent.size());
		
		for(SampleContent tempContent : listContent ){
		
			Item item = new Item();
			
			Content content = new Content();
			content.setValue(tempContent.getSummary());
			item.setContent(content);
			
			item.setTitle(tempContent.getTitle());
			item.setLink(tempContent.getUrl());
			item.setPubDate(tempContent.getCreatedDate());
			
			items.add(item);
		}
		
		return items;
	}

}

5. Controller

Spring MVC controller class, generate the rss feed content, and return a view name “rssViewer” (This view name is belong to above “CustomRssViewer“, will register in step 6 later).


package com.mkyong.common.controller;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.servlet.ModelAndView;
import com.mkyong.common.model.SampleContent;

@Controller
public class RssController {

	@RequestMapping(value="/rssfeed", method = RequestMethod.GET)
	public ModelAndView getFeedInRss() {

		List<SampleContent> items = new ArrayList<SampleContent>();
		
		SampleContent content  = new SampleContent();
		content.setTitle("Spring MVC Tutorial 1");
		content.setUrl("https://mkyong.com/spring-mvc/tutorial-1");
		content.setSummary("Tutorial 1 summary ...");
		content.setCreatedDate(new Date());
		items.add(content);
		
		SampleContent content2  = new SampleContent();
		content2.setTitle("Spring MVC Tutorial 2");
		content2.setUrl("https://mkyong.com/spring-mvc/tutorial-2");
		content2.setSummary("Tutorial 2 summary ...");
		content2.setCreatedDate(new Date());
		items.add(content2);
		
		ModelAndView mav = new ModelAndView();
		mav.setViewName("rssViewer");
		mav.addObject("feedContent", items);
		
		return mav;

	}
	
}

6. Spring Bean Registration

In a Spring bean definition file, enable the auto component scanning, and register your “CustomRssViewer” class and “BeanNameViewResolver” view resolver, so that when view name “rssViewer” is returned, Spring know it should map to bean id “rssViewer“.

File : mvc-dispatcher-servlet.xml


<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans     
        http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-3.0.xsd">

	<context:component-scan base-package="com.mkyong.common.controller" />

	<!-- Map returned view name "rssViewer" to bean id "rssViewer" -->
	<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />

	<bean id="rssViewer" class="com.mkyong.common.rss.CustomRssViewer" />

</beans>
Note
File content of web.xml is omitted, just a standard configuration, if you are interest, download this whole project at the end of the article.

7. Demo

URL : http://localhost:8080/SpringMVC/rest/rssfeed

spring mvc and rss feed demo
How about Atom?
For Atom, you just need to extends AbstractAtomFeedView, instead of AbstractRssFeedView.

Download Source Code

Download it – SpringMVC-RSS-Feed-Example.zip (9 KB)

References

  1. ROME – Java library for RSS Feed
  2. AbstractRssFeedView JavaDoc
  3. Example to create a RSS feed in Java

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
16 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
Batandwa
7 years ago

I couldn’t get the downloaded copy of this to work until I changed the url-pattern, in web.xml, from ‘/rest/*’ to ‘/rssfeed/*’.

Darshan Khot
9 years ago

Wow!!! Thats great to start on RSS Feed for beginner. Thank you alot for the wonderful demo. Hats off again.

Sebastián Arbona
10 years ago

You are my hero! Every question I ask about spring, mkong has the answer! When you travel to argentinam should contact me. I’m going to invite a couple of beers!

Manas
10 years ago

Very good Tutorial
I have tried it in PHP also
visit to get PHP code: http://www.discussdesk.com/create-rss-feed-with-php-mysql.htm

Marcio
10 years ago

Great tutorial. I was looking for anything like that.
Thanks!

vermoeid
10 years ago

I relish, cause I discovered just what I used to be taking a look for.
You’ve ended my 4 day long hunt! God Bless you man. Have a nice day. Bye

Alfredo Ramos
11 years ago

Do you know how can I format the publication date with rome from this line?

 Java source code here 

item.setPubDate(tempContent.getCreatedDate());

 XML here 
Sudhakar K
11 years ago

I dowloaded your zip file and i get this error.
30 Dec, 2012 10:29:03 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet featuriz threw exception
java.lang.ClassNotFoundException: org.jdom.JDOMException
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1680)
at org.apache.catalina.loader.WebappClassLoader.loadClass(WebappClassLoader.java:1526)
at org.springframework.web.servlet.view.feed.AbstractFeedView.renderMergedOutputModel(AbstractFeedView.java:62)
at org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:264)
at org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1208)
at org.springframework.web.servlet.DispatcherServlet.processDispatchResult(DispatcherServlet.java:992)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:939)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:856)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:915)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:811)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:796)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:77)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:322)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:116)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:103)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:113)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:146)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:45)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:182)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:87)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:334)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:184)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:155)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:293)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:602)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:662)

Sudhakar K
11 years ago

I’m going to add feed in my existing project.
I download and added rome-1.0.jar

My Controller is 100% same as your controller (Checked three to four times, and copy and paste)
My Model also 100% same checked many times.
AbstractRssFeedView : I just copied and pasted, and check all text by letters also.

My Problem is here:
In servlet.xml
Your code,

<context:component-scan base-package="com.mkyong.common.controller" />
 
	<!-- Map returned view name "rssViewer" to bean id "rssViewer" -->
	<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />
 
	<bean id="rssViewer" class="com.mkyong.common.rss.CustomRssViewer" />

I’m allready using component scan.
Added other two lines in my xml. The final xml is,

<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter" />
    <bean class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping" />
    <bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />

    <mvc:annotation-driven/>
    <context:component-scan base-package="com.sud.controller"/>
 
    <bean id="rssViewer" class="com.sud.controller.CustomRssViewer" />

<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"
          p:prefix="/WEB-INF/jsp/templates/"
          p:suffix=".jsp" />

I’m using spring 3.2, tomcat 6.0.33
To reduce my overall project size i’m not using tiles,hibernate and so other externals.

I also tried : @MikeNereson method. But no use.

Tomcat Errors:
java.lang.ClassNotFoundException: org.jdom.JDOMException

Sudhakar K
11 years ago
Reply to  Sudhakar K

I google and found to add jdom-2.0.4.jar and added this to my lib.
Even though same error.
java.lang.ClassNotFoundException: org.jdom.JDOMException

Raj
11 years ago

Hi,
can you give some example of generating mRSS feed with spring

billschen
12 years ago

I download your source code .but I didn’t find SampleContent Class

billschen
12 years ago
Reply to  billschen

sorry! I found it.
I download wrong source fist!

MikeNereson
12 years ago

Worked… eventually. I have a couple of notes to add.

If you’re using

<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">

Then adding

<bean class="org.springframework.web.servlet.view.BeanNameViewResolver" />

won’t do anything for you.

I did define the rssView as a bean, but then in RssController I used

return new ModelAndView(new RssViewer(), "feedContent", items);

Thanks, mkyong.

John Hunsley
11 years ago
Reply to  MikeNereson

you can use multipe View Resolvers and chain them by setting the order property.

   <bean class="org.springframework.web.servlet.view.BeanNameViewResolver">
        <property name="order" value="0"/>
    </bean>

and set it in your other view resolver with order value of 1

MikeNereson
12 years ago
Reply to  MikeNereson

I mean, I did not define anything RssViewer as a bean at all, or set the BeanNameViewResolver. I just created both classes as you described but
used return new ModelAndView(new RssViewer(), “feedContent”, items);