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.

7 Responses to Dynamic Images with JSF

  1. Hi.
    I guess you store the graphicImage in memory before serving it to the user right? Is there an easy way not to do that?
    Another question; how easily will PrimeFaces be integrated with JSF 2.0 ?

  2. Image is streamed to the browser and cleared afterwards. PrimeFaces 2.0 alpha is coming out by the end of november.

  3. aravind says:

    is there a prime-faces version compatible with jsf 1.1

  4. chad says:

    In the examples shown on the PrimeFaces showcase, the backing beans always have request scope. I tried using backing beans with view scope but had no luck. Should view scoped backing beans work with this approach??

  5. @aravind, at least JSF 1.2 is required.
    @chad, that should work, please visit PrimeFaces forum if you have problems.

  6. Thats awsome! Richfaces for instances keeps the files in memory which really blows. My feeling is that PrimeFaces is a really lightweight and thoroughly thought-through approach compared to the other frameworks!

    Keep up the good work!

  7. Gift Sam says:

    Great stuff. Thanks for the article!!.

%d bloggers like this: