Oracle ADF Medior: Rendering images based on BLOB columns
For my current project we are building an application with Oracle ADF 10.1.3.3 (ADF BC + JSF). One of the functionalities they want is to show images that were stored in a Blob field in the database at a JSF page. After a short search it appeared that this can be rather easily done if the column in the database is of the type ORD_SYS.ORDIMAGE (see Steve's Muench post here).
For a Blob column, however, there isn't a standard way in ADF to do that, so he suggests to make a servlet that renders the image and use that servlet as the 'src' for a image tag. I followed this approach and I made the servlet configurable, so it can generate any kind of file, based on the content of the Blob.
Here is the code for the servlet:
-
package net.pascalalma.view.servlet;
-
-
import java.io.IOException;
-
import java.io.InputStream;
-
import java.io.OutputStream;
-
-
import java.util.Iterator;
-
import java.util.Map;
-
-
import javax.servlet.ServletConfig;
-
import javax.servlet.ServletException;
-
import javax.servlet.http.HttpServlet;
-
import javax.servlet.http.HttpServletRequest;
-
import javax.servlet.http.HttpServletResponse;
-
-
import oracle.jbo.ApplicationModule;
-
import oracle.jbo.Row;
-
import oracle.jbo.ViewObject;
-
import oracle.jbo.client.Configuration;
-
import oracle.jbo.domain.BlobDomain;
-
-
import org.apache.commons.logging.Log;
-
import org.apache.commons.logging.LogFactory;
-
-
/**
-
* Use like:
-
* <af:image source="/urlToServlet?someParam=#{bindings.someValue}"/>
-
* @author Pascal Alma
-
*/
-
public class ImageServlet extends HttpServlet
-
{
-
private static final Log LOG = LogFactory.getLog(ImageServlet.class);
-
-
public void init(ServletConfig config)
-
throws ServletException
-
{
-
super.init(config);
-
}
-
-
public void doGet(HttpServletRequest request,
-
HttpServletResponse response)
-
throws ServletException, IOException
-
{
-
-
//TODO: throw exception if mandatory parameter not set
-
-
ApplicationModule am =
-
Configuration.createRootApplicationModule(appModuleName, appModuleConfig);
-
ViewObject vo = am.createViewObjectFromQueryStmt("TempView", voQuery);
-
-
int i=0;
-
-
while (paramValues.hasNext())
-
{
-
// Only one value for a parameter is expected.
-
// TODO: If more then 1 parameter is supplied make sure the value is bound to the right bind
-
// variable in the query! Maybe use named variables instead.
-
vo.setWhereClauseParam(i, paramValue[0]);
-
i++;
-
}
-
// Run the query
-
vo.executeQuery();
-
// Get the result (only the first row is taken into account
-
Row product = vo.first();
-
-
BlobDomain image = null;
-
// Check if a row has been found
-
if (product != null)
-
{
-
// We assume the Blob to be the first a field
-
image = (BlobDomain) product.getAttribute(0);
-
-
// Check if there are more fields returned. If so, the second one
-
// is considered to hold the mime type
-
if ( product.getAttributeCount()> 1 )
-
{
-
}
-
}
-
else
-
{
-
LOG.warn("No row found to get image from !!!");
-
return;
-
}
-
-
// Set the content-type. Only images are taken into account
-
response.setContentType("image/"+ mimeType+ "; charset=windows-1252");
-
-
// copy blob to output
-
byte[] buffer = new byte[4096];
-
int nread;
-
while ((nread = is.read(buffer)) != -1)
-
{
-
os.write(buffer, 0, nread);
-
}
-
os.close();
-
-
// Remove the temporary viewobject
-
vo.remove();
-
// Release the appModule
-
Configuration.releaseRootApplicationModule(am, false);
-
}
-
}
As you can see there might be some loose ends in the servlet code, but if you keep it rather simple (only 1 parameter for the query) the servlet will do its job.
Here is how you can configure the servlet in your application's web.xml:
-
<servlet-name>images</servlet-name>
-
<servlet-class>net.pascalalma.view.servlet.ImageServlet</servlet-class>
-
<init-param>
-
<param-name>ApplicationModuleName</param-name>
-
<param-value>net.pascalalma.model.services.MyService</param-value>
-
</init-param>
-
<init-param>
-
<description>The query that will select the image field. Second field might be selected
-
as mime type. Only the first row of the result will be taken into account</description>
-
<param-name>ImageViewObjectQuery</param-name>
-
<param-value>select image_file from my_images where image_id = ?</param-value>
-
</init-param>
-
<init-param>
-
<description>Configuration to be used</description>
-
<param-name>ApplicationModuleConfig</param-name>
-
<param-value>MyServiceLocal</param-value>
-
</init-param>
-
<init-param>
-
<description>Optional. If not set here, the second column in the query will be considered to
-
contain the mime type!</description>
-
<param-name>MimeType</param-name>
-
<param-value>gif</param-value>
-
</init-param>
-
</servlet>
-
<servlet-mapping>
-
<servlet-name>images</servlet-name>
-
<url-pattern>/render_image</url-pattern>
-
</servlet-mapping>
And this is how you would make the images appear on your page:
-
<af:objectImage source="/render_image?img_id=#{row.ImageId}"/>
where #{row.ImageId} refers to an id of a record in the my_images table.
Although it might not be exactly what you need, I hope it gives you enough ideas to create a servlet that meets your wishes.
Tags: JSF, Oracle ADF










perfect !!!!!