PrimeFaces 1.0.0.RC is Released

I’m pleased to announce that PrimeFaces 1.0.0.RC is released.

PrimeFaces 1.0.0.RC introduces 12 new components, Ajax Push Alpha Integration, various improvements and fixes. In total 61 issues in tracker are closed.

  • Alpha Ajax Push/Comet integration built on top of Atmosphere Framework.
  • New component: AccordionPanel (Reimplementation)
  • New component: Password Strength
  • New component: Inplace
  • New component: Terminal
  • New component: Printer
  • New component: Tabslider
  • New component: Breadcrumb
  • New component: Messages
  • New component: Message
  • New component: RemoteCommand
  • New component: Resource
  • New component: Watermark
  • TouchFaces enhancements; exposed client side api, new view animations.
  • DataTable enhancements; Instant Ajax row selection and Ajax Sorting
  • Many improvements and fixes to issues reported by PrimeFaces community

See the full changelog for detailed information. Also don’t forget to update your Reference Documentation, it has reached 300 pages now.

Note: This version is not backward compatible, please see Migration Guide.

Next release is for PrimeFaces 2.0.0.RC that targets JSF 2.0, we’re aiming to release 2.0.RC by next week. After that we’ll add more components such as treeTable, contextMenu, fullCalendar, implement feature requests of PrimeFaces users and improve the current codebase.

Thanks to everyone supporting PrimeFaces!

By the way today is the 1st birthday of PrimeFaces, happy birthday!

Mobile GPS Navigation App with JSF

I’ve created various sample mobile apps before such as Translator, Weather, News, Notes, Twitter Client and Mobile Chat (powered by PrimeFaces/Atmosphere Push infastructre) etc. Since these are webapps tuned for mobile app look and feel, I was wondering the limits of a mobile webapp compared to a native app. Geolocation and GPS support might sound like one of these limitations but well, it is not :) As a proof of concept for a PrimeFaces/TouchFaces app I’ve created the PathFinder, A mobile GPS Navigation app for iphone.

To begin with here’s the final output; There’re two screens, one is for map with directions and other is for settings. Click images for higher resolution.

pf1 pf1 pf1

See it in action

I’ve recorded a short screencast as well running the PathFinder on iPhone Emulator.

All of this is basically a simple JSF page; pathfinder.jsf

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<f:view xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.prime.com.tr/ui"
	xmlns:i="http://primefaces.prime.com.tr/touch"
	contentType="text/html">

	<i:application icon="/images/touch/mapicon.png">
		<f:facet name="meta">
			<script src="http://maps.google.com/maps?file=api&amp;v=2&amp;sensor=true&amp;key=ABQIAAAAfC5eyG3CuuRKtsMbGj42fhThrJrTqAJnkzhJQxjbFhIXTdSD6xRglAovT0AWB71tfpSZxEd9pJoxwQ" type="text/javascript"></script>
			<script type="text/javascript">

				PathFinder = {

						init : function() {
							map = new GMap2(document.getElementById("map"));
							map.setUIToDefault();

				        	navigator.geolocation.getCurrentPosition(
						        function(position) {
							        lat = position.coords.latitude;
							        lng = position.coords.longitude;
							        var center = new GLatLng(position.coords.latitude, position.coords.longitude);
							        map.setCenter(center, 15);
							        map.addOverlay(new GMarker(center));
							        geocoder = new GClientGeocoder();
							        directions = new GDirections(map, document.getElementById('route'));
						        });
						},

						findAndGo : function() {
							var address = document.getElementById('address').value;
							geocoder.getLatLng(address,function(point) {
								 if (!point) {
						              alert(address + " not found");
						          } else {
						              directions.load("from " + lat + " " + lng + " to " + point.lat() + " " + point.lng());
						           }
							});
						}
					};

				if(!navigator.geolocation) {
					alert('Error: PathFinder requires a GPS capable device.');
				} else {
					window.onload = PathFinder.init;
				}

			</script>
			<meta content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;" name="cube"/>
		</f:facet>

		<i:view id="home" title="PathFinder">
			<f:facet name="rightNavBar">
				<i:navBarControl label="Settings" view="settings" type="button" effect="cube"/>
			</f:facet>

			<h:form prependId="false">
				<i:tableView>
					<i:rowGroup display="edgetoedge">
						<div id="map" style="width:100%;height:285px;"></div>
					</i:rowGroup>

					<i:rowGroup>
						<i:rowItem>
							<h:inputText id="address"/>
						</i:rowItem>
					</i:rowGroup>

					<p:commandLink style="margin:10px 10px;" styleClass="whiteButton" value="#" onclick="PathFinder.findAndGo();return false;">Find and Go!</p:commandLink>

					<i:rowGroup>
							<i:rowItem>
								<div id="route"></div>
							</i:rowItem>
					</i:rowGroup>
				</i:tableView>
			</h:form>

		</i:view>

		<i:view id="settings" title="Settings">
			<f:facet name="leftNavBar">
				<i:navBarControl label="Home" view="home" />
			</f:facet>

			<h:form prependId="false">
				<i:tableView>

					<i:rowGroup>
						<i:rowItem>
							<h:outputText value="Transport" />
							<h:selectOneMenu>
								<f:selectItem itemLabel="Driving" itemValue="d" />
								<f:selectItem itemLabel="Walking" itemValue="w" />
							</h:selectOneMenu>
						</i:rowItem>

						<i:rowItem>
							<h:outputText value="Traffic" />
							<i:switch id="traffic"/>
						</i:rowItem>
					</i:rowGroup>

				</i:tableView>

				<p:commandLink style="margin:0 10px;" styleClass="whiteButton" value="#" onclick="TouchFaces.goBack();">Save</p:commandLink>

			</h:form>

		</i:view>

	</i:application>

</f:view>

That’s just it, now you have a GPS enabled navigation app with a couple of lines. Let’s breakdown the important points to see how it works;

* GEOLocation info is provided by mobile safari, navigation geolocation api is an HTML5 feature supported by major browsers like Safari and Firefox (no IE of course). When you run the application, safari asks for a confirmation since the app tries to access hardware information and on page load places a markers on map with the geo location info.

* Once we have the location, it’s trivial to place a map and do some gmap api coding. ‘Find and Go’ button simply does a geocoding and retrieves the latitude and longitude, with that it asks gmap api for directions and updates the map. Update happens in 5 seconds with the updated geo location info.

* A settings view is also added, I left out the implementation of settings UI but it helps to demonstrate how easy it can be to create another UI for customizations.

Summary

PathFinder is a simple reference app, things can be done with PrimeFaces is limitless. For example, since PrimeFaces also supports Ajax Push, it would be so easy to create location based mobile Comet applications as well.

Finally one thing I’d like to emphasize again, what PrimeFaces has so far (70+ Ajax Components, Ajax Push/Comet, Lightweight design, TouchFaces, GPS enabled apps, …) is just the beginning.

I’m speaking at JSFSummit 09

I’ll be speaking at JSFSummit 09 in Orlando between December 1-4 with my “Rapid RIA with PrimeFaces” session. I really enjoyed last year in Washington D.C. when the conference was called JSFOne back then.

I’m really looking forward to get together again with folks like Ed Burns, my man Matthias Wessendorf, Martin Marinschek, Max Katz, Kito Mann and Andy Schwartz. It’ll be a great conference!

Mobile Twitter Client with JSF

I’ve added another sample to TouchFaces showcase applications, this one is called TwitFaces allowing to view someone’s tweets in your iphone. The app integrates with twitter rest api and created with TouchFaces mobile JSF kit of PrimeFaces.

Let’s begin with TwitterService

package org.primefaces.examples.service;

import java.util.List;

public interface TwitterService {

	public List<String> getTweets(String username);
}

And TwitterRSSService, the RSS based implementation using Rome.

package org.primefaces.examples.service;

import java.net.URL;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Logger;

import com.sun.syndication.feed.synd.SyndEntry;
import com.sun.syndication.feed.synd.SyndFeed;
import com.sun.syndication.io.SyndFeedInput;
import com.sun.syndication.io.XmlReader;

public class TwitterRSSService implements TwitterService {

	private static final Logger logger = Logger.getLogger(TwitterRSSService.class.getName());

	public List<String> getTweets(String username) {
		List<String> tweets = new ArrayList<String>();

		try {
			URL feedSource = new URL("http://twitter.com/statuses/user_timeline.rss?screen_name=" + username);

			SyndFeedInput input = new SyndFeedInput();
			SyndFeed feed = input.build(new XmlReader(feedSource));
			for(Object f : feed.getEntries()) {
				SyndEntry entry = (SyndEntry) f;
				tweets.add(entry.getTitle().substring(username.length() + 2));
			}
		}catch(Exception e) {
			logger.severe(e.getMessage());
		}

		return tweets;
	}
}

And the JSF backing bean called TwitterController powered by PrimeFaces Optimus.

package org.primefaces.examples.touch;

import java.util.List;

import javax.faces.event.ActionEvent;

import org.primefaces.examples.service.TwitterService;
import org.primefaces.optimus.config.Scope;
import org.primefaces.optimus.config.annotations.Controller;

import com.google.inject.Inject;

@Controller(name="twitterController", scope=Scope.REQUEST)
public class TwitterController {

	@Inject private TwitterService twitterService;

	private String username;

	private List<String> tweets;

	public void loadTweets(ActionEvent actionEvent) {
		tweets = twitterService.getTweets(username);
	}

	public String getUsername() {
		return username;
	}
	public void setUsername(String username) {
		this.username = username;
	}

	public List<String> getTweets() {
		return tweets;
	}
	public void setTweets(List<String> tweets) {
		this.tweets = tweets;
	}
}

Finally create your app as a JSF page, twitfaces.xhtml;

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<f:view xmlns="http://www.w3.org/1999/xhtml"
	xmlns:ui="http://java.sun.com/jsf/facelets"
	xmlns:f="http://java.sun.com/jsf/core"
	xmlns:h="http://java.sun.com/jsf/html"
	xmlns:p="http://primefaces.prime.com.tr/ui"
	xmlns:i="http://primefaces.prime.com.tr/touch"
	contentType="text/html">

	<i:application icon="/images/touch/twiticon.png">
		<i:view id="home" title="TwitFaces">
			<h:form prependId="false">
				<i:tableView>
					<i:rowGroup>
						<i:rowItem>
							<h:inputText value="#{twitterController.username}" />
						</i:rowItem>
					</i:rowGroup>

					<p:commandLink actionListener="#{twitterController.loadTweets}" style="margin:10px 10px;"
					styleClass="whiteButton" value="#" update="display">Get Tweets</p:commandLink>

					<i:rowGroup id="display">
						<ui:repeat value="#{twitterController.tweets}" var="tweet">
							<i:rowItem>
								#{tweet}
							</i:rowItem>
						</ui:repeat>
					</i:rowGroup>
				</i:tableView>
			</h:form>
		</i:view>
	</i:application>

</f:view>

That’s it running twitfaces.jsf displays;

twitfaces

TwitFaces is a very simple app, a full blown twitter client can be written on top of it easily using TouchFaces/PrimeFaces.

Online Demo

Check out TwitFaces app live on PrimeFaces Online Demos.

PrimeFaces Reorg

Two PrimeFaces modules, Optimus and FacesTrace are moved to the PrimeFaces Extensions as spin-off projects and PrimeFaces UI module is renamed as PrimeFaces

Main goal of PrimeFaces has always been to be the ultimate JSF component suite, by this change PrimeFaces became all about UI again.

Dynamic Images with JSF

Legacy way to display binary images is to create a servlet and send the byte content as a stream. This requires a dedicated servlet and probably different servlets dealing with handling cases.

PrimeFaces features a simple but powerful StreamedContent API and p:graphicImage component to display any binary image easily. This binary image could be images stored in a database or images created programmatically on-the-fly. Following are a couple examples for demonstrating how easy it is to display binary images with PrimeFaces.

Images Stored in Database
This example retrieves a blob from a jdbc resultset and provides it’s inputstream as a StreamedContent.

public class BackingBean {

	private StreamedContent dbImage;

	public BackingBean() {
		InputStream dbStream = //Get inputstream of a blob eg javax.sql.Blob.getInputStream() API
		dbImage = new DefaultStreamedContent(dbStream, "image/jpeg");
	}

	//getters and setters
}
 <p:graphicImage value="#{backingBean.dbImage}" />

dynamicImage.jsf

Generated Chart Images
JFreeChart is a popular open source charting library, PrimeFaces also have flash based cool charts but if you want
to use JFreeChart instead you don’t need a wrapper JSF component for this. Just create your chart and define it as
as a streamed content.

public class BackingBean {

	private StreamedContent chartImage;

	public BackingBean() {
		try {
			JFreeChart jfreechart = ChartFactory.createPieChart("Turkish Cities", createDataset(), true, true, false);
			File chartFile = new File("dynamichart");
			ChartUtilities.saveChartAsPNG(chartFile, jfreechart, 375, 300);
			chartImage = new DefaultStreamedContent(new FileInputStream(chartFile), "image/png");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private PieDataset createDataset() {
		DefaultPieDataset dataset = new DefaultPieDataset();
		dataset.setValue("Istanbul", new Double(45.0));
		dataset.setValue("Ankara", new Double(15.0));
		dataset.setValue("Izmir", new Double(25.2));
		dataset.setValue("Antalya", new Double(14.8));

		return dataset;
	}

	//getters and setters
}
 <p:graphicImage value="#{backingBean.chartImage}" />

This chart example truly demonstrates the power of PrimeFaces StreamedContent, I’ve created a JSFChartCreator component long time ago which became quite popular in JSF community. The problem was when you wrap a huge API like JFreeChart, flexibility gets lost since it’s just too hard to support every different setting in JFreechart API with a wrapper component. StreamedContent and p:graphicImage simply makes any other JSF component wrapping JFreeChart obselete. Instead with this way you still have the full power of chart api and a very easy way to display it.

dynamicImage.jsf

Runtime Barcode Creator
Similar to the chart example, an on-the-fly generated barcode can easily be presented. This example uses barbecue project to create barcodes.

public class BackingBean {

	private StreamedContent barcode;

	public BackingBean() {
		try {
			File barcodeFile = new File("dynamicbarcode");
			BarcodeImageHandler.saveJPEG(BarcodeFactory.createCode128("PRIMEFACES"), barcodeFile);
			barcode = new DefaultStreamedContent(new FileInputStream(barcodeFile), "image/jpeg");
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	//getters and setters
}
 <p:graphicImage value="#{backingBean.barcode}" />

dynamicImage-1.jsf

Online Demo
Examples I’ve given here are also available live at PrimeFaces Showcase.

Summary
One of the design principles behind PrimeFaces is to hide complexity and keep the flexibility, this is just one example of it in PrimeFaces.