My PrimeFaces RSS support draft implementation
Below is an overview of implementation of RSS support for PrimeFaces. I have used YARFRAW. The usage is as below.
<p:rss title="RSS feed title" link="http://www.karthikeyanc.com/feed.seam"
tagLine="CKs Developer Notes.."
xmlns:p="http://primefaces.prime.com.tr/ui"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<f:view contentType="application/atom+xml">
<ui:repeat var="tut" value="#{rssfeed.feedTutorials}">
<p:rssEntry title="#{tut.topic}"
link="http://localhost:8080/tutorial/#{tut.id}_#{tut.slug}"
id="http://localhost:8080/tutorial/#{tut.id}_#{tut.slug}"
author="karthikeyanC"
published="#{tut.lastupdate}"
updated="#{tut.lastupdate}"
summary="#{tut.summary}"/>
</ui:repeat>
</f:view>
</p:rss>
The following changes were made for the same.
To begin with add the following dependency in pom.xml
<!--RSS Yarfraw--> <dependency> <groupId>net.sourceforge.yarfraw</groupId> <artifactId>yarfraw</artifactId> <version>0.92</version> <scope>provided</scope> </dependency>
I created two template files namely rss.xml and rssEntry.xml under primefaces/src/main/resources-maven-jsf/ui.
rss.xml content is as below.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE component SYSTEM "../misc/component.dtd" [ <!ENTITY standard_uicomponent_attributes SYSTEM "../entities/standard_uicomponent_attributes.xml"> <!ENTITY widget_var_attribute SYSTEM "../entities/widget_var_attribute.xml"> <!ENTITY output_component_attributes SYSTEM "../entities/output_component_attributes.xml"> ]> <component> <tag>rss</tag> <tagClass>org.primefaces.component.rss.RssTag</tagClass> <componentClass>org.primefaces.component.rss.Rss</componentClass> <componentType>org.primefaces.component.Rss</componentType> <componentFamily>org.primefaces.component</componentFamily> <rendererType>org.primefaces.component.RssRenderer</rendererType> <rendererClass>org.primefaces.component.rss.RssRenderer</rendererClass> <parent>javax.faces.component.UIComponentBase</parent> <attributes> &standard_uicomponent_attributes; <attribute> <name>title</name> <required>true</required> <type>java.lang.String</type> <description>The title for RSS feed</description> </attribute> <attribute> <name>link</name> <required>true</required> <type>java.lang.String</type> <description>The Link for RSS feed</description> </attribute> <attribute> <name>tagLine</name> <required>false</required> <type>java.lang.String</type> <description>The tag line for RSS feed</description> </attribute> </attributes> <resources/> </component>
rssEntry.xml content is as below.
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE component SYSTEM "../misc/component.dtd" [ <!ENTITY standard_uicomponent_attributes SYSTEM "../entities/standard_uicomponent_attributes.xml"> <!ENTITY widget_var_attribute SYSTEM "../entities/widget_var_attribute.xml"> <!ENTITY output_component_attributes SYSTEM "../entities/output_component_attributes.xml"> ]> <component> <tag>rssEntry</tag> <tagClass>org.primefaces.component.rss.RssEntryTag</tagClass> <componentClass>org.primefaces.component.rss.RssEntry</componentClass> <componentType>org.primefaces.component.RssEntry</componentType> <componentFamily>org.primefaces.component</componentFamily> <rendererType>org.primefaces.component.RssEntryRenderer</rendererType> <rendererClass>org.primefaces.component.rss.RssEntryRenderer</rendererClass> <parent>javax.faces.component.UIComponentBase</parent> <attributes> &standard_uicomponent_attributes; <attribute> <name>title</name> <required>true</required> <type>java.lang.String</type> <description>The title for RSS entry</description> </attribute> <attribute> <name>link</name> <required>true</required> <type>java.lang.String</type> <description>The Link for RSS entry</description> </attribute> <attribute> <name>id</name> <required>true</required> <type>java.lang.String</type> <description>The id for RSS entry</description> </attribute> <attribute> <name>summary</name> <required>true</required> <type>java.lang.String</type> <description>The summary text for RSS entry</description> </attribute> <attribute> <name>author</name> <required>true</required> <type>java.lang.String</type> <description>The author for RSS entry</description> </attribute> </attributes> <resources/> </component>
The related renderer classes are as below.
package org.primefaces.component.rss;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.primefaces.renderkit.CoreRenderer;
import yarfraw.core.datamodel.ChannelFeed;
import yarfraw.core.datamodel.FeedFormat;
import yarfraw.io.FeedWriter;
public class RssRenderer extends CoreRenderer {
static final String CHANNELFEED_KEY = "CHANNELFEED_KEY";
private static final String MIME_TYPE = "text/xml";
public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
Rss rss = (Rss) component;
ChannelFeed feed = new ChannelFeed();
feed.setUid(String.valueOf(System.nanoTime()));
feed.setTitle(rss.getTitle());
feed.setDescriptionOrSubtitle(rss.getTagLine());
feed.addLink(rss.getLink());
HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
request.setAttribute(RssRenderer.CHANNELFEED_KEY, feed);
}
public void encodeEnd(FacesContext facesContext, UIComponent component) throws IOException {
HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
ChannelFeed feed = (ChannelFeed) request.getAttribute(RssRenderer.CHANNELFEED_KEY);
request.removeAttribute(RssRenderer.CHANNELFEED_KEY);
ResponseWriter writer = facesContext.getResponseWriter();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
FeedWriter.writeChannel(FeedFormat.ATOM10, feed, baos);
} catch (Exception e) {
throw new RuntimeException("Cannot create RSS feed", e);
}
HttpServletResponse response = (HttpServletResponse) facesContext.getExternalContext().getResponse();
response.setContentType(MIME_TYPE);
response.setContentLength(baos.size());
writer.write(baos.toString());
writer.flush();
facesContext.responseComplete();
}
}
and RssEntryRenderer.java is as below.
package org.primefaces.component.rss;
import java.io.IOException;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.servlet.http.HttpServletRequest;
import org.primefaces.renderkit.CoreRenderer;
import yarfraw.core.datamodel.ChannelFeed;
import yarfraw.core.datamodel.ItemEntry;
import yarfraw.core.datamodel.Person;
public class RssEntryRenderer extends CoreRenderer {
public void encodeBegin(FacesContext facesContext, UIComponent component) throws IOException {
HttpServletRequest request = (HttpServletRequest) facesContext.getExternalContext().getRequest();
RssEntry rssEntry = (RssEntry) component;
ChannelFeed feed = (ChannelFeed) request.getAttribute(RssRenderer.CHANNELFEED_KEY);
ItemEntry entry = new ItemEntry();
entry.setUid(rssEntry.getId());
entry.setTitle(rssEntry.getTitle());
entry.addLink(rssEntry.getLink());
//author is a mandatory attribute
Person person = new Person();
person.setName(rssEntry.getAuthor());
entry.addAuthorOrCreator(person);
entry.setDescriptionOrSummary(rssEntry.getSummary());
feed.addItem(entry);
}
}
To use this component in their application one has to add the YARFRAW jar as a dependency in their application pom.xml or in the classpath (if they dont use Maven for build)