Using dynamic images in a JSP

Over the course of the summer, I had to go through a severe learning curve to write a Web catalogue application for a publishing company in Toronto. The focus of this column is the one area on which I got stuck for a long time: dynamic images.

My own search for information on the subject turned up scarce and ambiguous answers, and demonstrated that there are a lot of other people out there who wanted to do the very same thing as I.

These days, a Web page is nothing if it isn’t dynamic. The demand for Internet applications that communicate with a database has grown exponentially since the e-commerce boom, and technologies such as Active Server Pages, Sun’s Java Server Pages and Allaire’s ColdFusion have become standard fare. JSP is a popular choice for the same reason the Java language itself is so successful: code portability. Your Java server pages and servlets will theoretically run on any platform, provided you have installed a Java application server. There are many excellent tutorials available for dealing with JSP, but they are generally lacking in their description of image handling. This is unfortunate, as most on-line catalogues require the ability to display a graphical representation of the product.

When an image is stored in a database in binary form, it does not have a URL associated with it. Therefore, it cannot be accessed using standard HTML tags and we must write Java code that will query the database, return and display the image. The trap many developers fall into is trying to write this code inside the JSP itself. This leads to many hours of frustration, because the content type is set to text/html and even if the image is successfully fetched it will only display as a long stream of character data. The solution is to write a separate servlet for image retrieval.

In order to compile servlets you may need to install the JavaServer Web Development Kit (JSWDK). It is available for download from Sun at http://java.sun.com/products/servlet/.

Writing the Servlet

The following code example assumes prior knowledge of Java and basic SQL. It will create a servlet that receives a product number as a parameter and outputs the corresponding image. Depending on your needs, database connection information and SQL statements can also be passed as parameters, but for simplicity’s sake they are hard-coded here for connecting to an Oracle database.

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import java.sql.*;

public class ImageGetter extends HttpServlet {

//Method to get the parameter (product number) into a String and //pass it as an argument to the getImage method

public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {

String productNumber = null;

productNumber = request.getParameter(“productNumParam”);

getImage(response, productNumber);

}

//The method to query the database and output the image

public void getImage(HttpServletResponse response, String productNumber) throws ServletException, IOException {

try{

//create an instance of the Oracle JDBC driver (which //must found in your classpath)

Driver oracleDriver = (Driver)Class.forName(“oracle.jdbc.driver.OracleDriver”).newInstance();

//setup the database connection

Connection imageConn = DriverManager.getConnection(“jdbc:oracle:thin:@ DatabaseURL: port: SID“,” username“,” password“);

//SQL statement to query the database

PreparedStatement imagePS = imageConn.prepareCall(“SELECT PRODUCT_IMAGE FROM PRODUCT_IMAGE_TABLE WHERE PRODUCT_NUMBER = ‘” + productNumber + “‘”);

imagePS.setQueryTimeout(0);

//the ResultSet object to hold the query results

ResultSet RSImage = imagePS.executeQuery();

//create a boolean datatype that is initialized to //true if the ResultSet is empty (no image found)

boolean noRecords = !RSImage.next();

//if the ResultSet is empty, close it

if (noRecords){

RSImage.close();

}

//if it contains data, go ahead with the image //fetching

else{

//set the content type for an image (image/gif //will still display jpgs and possibly bmps

//in Internet Explorer)

response.setContentType(“image/gif”);

ServletOutputStream out = response.getOutputStream();

//getBytes is a method of class ResultSet used //to read the ResultSet data into an array of //bytes. This is where the image gets pulled //from the database into an array we can work //with in our code.

byte imageByteArray[] =RSImage.getBytes(“PRODUCT_IMAGE”);

//the content length is set to the length of //the byte array

response.setContentLength(imageByteArray.length);

//the byte array is written to the //ServletOutputStream starting with the first //byte and ending with the last

out.write(imageByteArray, 0, imageByteArray.length);

//The ServletOutputStream is flushed, the //recordset is closed, and the connection is //closed.

out.flush();

RSImage.close();

}

imageConn.close();

}

catch (Exception ex){

}

}

}

Embedding the Servlet

Now that the servlet is coded to return the image to the browser with the correct content type, displaying the image within the Web page is as easy as calling the servlet between HTML image tags. The following example gives the servlet product number 1234 as a parameter, and displays the associated image:

<img src=" path to servlet directory/ImageGetter?productNumParam=1234″>

Ultimately, you will want the product number to be dynamic and so your image tag may contain a JSP variable something like this:

<img src=" path to servlet directory/ImageGetter?productNumParam=”>

In order to avoid displaying a non-existent image (the ugly broken image placeholder in your browser) you may wish to query the database from within the JSP itself. Write an “if” statement to avoid printing the img src tag if there is no graphic available for that particular product number. This is especially useful when an image is only available for some of the products in the database.

I have found this servlet to function quite well as a portable piece of code. With only minor modifications (such as database connection information and SQL statements) I have successfully used it as an image fetcher in several Web-based applications. It is my hope that sharing this source code may save some other programmer from the dreaded research that occupied far too many of my summer days.

Cooney is a Toronto-based programmer and a freelance Internet developer. He is currently enrolled as a student of Humber College’s Computer Programmer/Analyst program. He can be reached at robert_cooney@hotmail.com.