Hi, with Spring MVC 3 and JSP, I want to display image from database.
Currently on the jsp page, firebug revealed that the "broken image" caused by the following link:
<img src="/category_image/image?id=4957" />

I have implemented an ImageServlet class and have added servlet mapping in the web.xml file.

Here is the web.xml file:
<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
version="2.4">

<!-- The master configuration file for this Spring web application -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/WEB-INF/config/web-application-config.xml
</param-value>
</context-param>

<!-- Loads the Spring web application context -->
<listener>
<listener-class>org.springframework.web.context.ContextLoade rListener</listener-class>
</listener>

<!-- Enables use of HTTP methods PUT and DELETE -->
<filter>
<filter-name>httpMethodFilter</filter-name>
<filter-class>org.springframework.web.filter.HiddenHttpMet hodFilter</filter-class>
</filter>

<filter-mapping>
<filter-name>httpMethodFilter</filter-name>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
</filter-mapping>

<!-- Enables Spring Security -->
<filter>
<filter-name>springSecurityFilterChain</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFil terProxy</filter-class>
</filter>

<filter-mapping>
<filter-name>springSecurityFilterChain</filter-name>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
</filter-mapping>

<!-- The front controller of this Spring Web application, responsible for handling all application requests -->
<servlet>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherSe rvlet</servlet-class>
<init-param>
<param-name>contextConfigLocation</param-name>
<param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

<!-- Map all *.spring requests to the DispatcherServlet for handling -->
<servlet-mapping>
<servlet-name>Spring MVC Dispatcher Servlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

<!-- category image servlet -->
<servlet>
<servlet-name>categoryImageServlet</servlet-name>
<servlet-class>ix.houseware.category.servlet.CategoryImageS ervlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>categoryImageServlet</servlet-name>
<url-pattern>/category_image/*</url-pattern>
</servlet-mapping>


</web-app>
CategoryImageServlet class:

public class CategoryImageServlet extends HttpServlet {

private static final long serialVersionUID = 1L;
private static final Logger logger = Logger.getLogger(CategoryImageServlet.class);

CategoryImagesService imageService;

protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String categoryId = request.getParameter("id");

if (categoryId == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUN D); // 404.
return;
}

List<CategoryImages> ciList = imageService.findImagesByCategoryId(Integer.parseI nt(categoryId), 0, imageService.count()) ;

if (ciList.isEmpty()) {
response.sendError(HttpServletResponse.SC_NOT_FOUN D); // 404.
return;
}

// change it to list later.
CategoryImages ci = ciList.get(0);
int imageLength = ci.getImageData().length;
// Init servlet response.
response.reset();
response.setBufferSize(imageLength);
response.setContentType(ci.getImageType());

response.setHeader("Content-Length", String.valueOf(imageLength));
response.setHeader("Content-Disposition", "inline; filename=\"" + ci.getImageTitle() + "\"");

// Prepare streams.
BufferedInputStream input = null;
BufferedOutputStream output = null;

try {
InputStream is = new ByteArrayInputStream(ci.getImageData());
// Open streams.
input = new BufferedInputStream(is, imageLength);
output = new BufferedOutputStream(response.getOutputStream(), imageLength);

// Write file contents to response.
byte[] buffer = new byte[imageLength];
int length;
while ((length = input.read(buffer)) > 0) {
output.write(buffer, 0, length);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
finally {
// Gently close streams.
close(output);
close(input);
}
}

private static void close(Closeable resource) {
if (resource != null) {
try {
resource.close();
} catch (IOException e) {
throw new RuntimeException(e.getMessage());
}
}
}

}
JSP file:
<h3>Categories Search Results</h3>

<div id="categoryResults">
<form id="categoryListForm" name="categoryListForm" action="" method="get">
<input type="hidden" name="categoryName" />
<input type="hidden" name="categoryRelation" />
<input type="hidden" name="categoryId" value="${category.categoryId}"/>

<c:if test="${not empty categoryList}">
<table class="summary">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>Photo</th>
<th>Category Id</th>
<th>&nbsp;</th>
</tr>
</thead>
<tbody>
<c:forEach var="category" items="${categoryList}">
<tr>
<td>${category.categoryName}</td>
<td>${category.categoryDesc}</td>
<td><img src="/category_image/image?id=${category.categoryId}" /></td>
<td>${category.categoryId}</td>
<td>
<fieldset id="categoryListFormActionMenu-${category.categoryId}" name="${category.categoryName}">
</fieldset>
<script type="text/javascript">
createYUIMenuButton(${category.categoryId}, '${category.categoryName}');
</script>
</td>
</tr>
</c:forEach>
<c:if test="${empty categoryList}">
<tr>
<td colspan="5">No category found</td>
</tr>
</c:if>
</tbody>
</table>
...

</c:if>
</form>
</div>
Any suggestion would be very appreciated.
Thanks
Sam