Saturday, September 24, 2011

Storing and Retrieving Images In DB Using Struts 2, Spring 3 and Hibernate 3

This tutorial will show how you can store images in Database and retrieve them from DB and display in browser using Struts 2, Spring and Hibernate step by step. I have used Oracle Database to store the data.


It uses Struts 2 for presentation layer and Spring to manage the business and DAO objects and Hibernate at DAO layer to access dabase.


To get all the required jar files and classpath setup please look at 
http://tiwarij2eeblog.blogspot.com/2011/01/integration-of-struts-20-spring-30-and.html


Step 1: Setup project in eclipse as given below.





Step 2: Copy all required jar files to WEB-INF/lib folder.
Step 3: Create VO object and hibernate mapping file.



package org.paandav.blog.vo;
import java.io.Serializable;
import java.sql.Blob;


public class User implements Serializable {
private static final long serialVersionUID = 1L;
private Long id;
private Long version;
private String firstName;
private String lastName;
private Blob image;
private String conTentType;
private String fileName;
private byte[] imageInBytes; // For external use
private int contentLength;// For external use


public int getContentLength() {
return contentLength;
}


public void setContentLength(int contentLength) {
this.contentLength = contentLength;
}


public byte[] getImageInBytes() {
return imageInBytes;
}


public void setImageInBytes(byte[] imageInBytes) {
this.imageInBytes = imageInBytes;
}


public String getFileName() {
return fileName;
}


public void setFileName(String fileName) {
this.fileName = fileName;
}


public String getConTentType() {
return conTentType;
}


public void setConTentType(String conTentType) {
this.conTentType = conTentType;
}


public String getFirstName() {
return firstName;
}


public void setFirstName(String firstName) {
this.firstName = firstName;
}


public Blob getImage() {
return image;
}


public void setImage(Blob image) {
this.image = image;
}


public Long getId() {
return id;
}


public void setId(Long id) {
this.id = id;
}


public Long getVersion() {
return version;
}


public void setVersion(Long version) {
this.version = version;
}


public String getLastName() {
return lastName;
}


public void setLastName(String lastName) {
this.lastName = lastName;
}
}


Hibernate Mapping file - User.hbm.xml



<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
        "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">


<hibernate-mapping package="org.paandav.blog.vo">
<class name="User" table="BT_USER" optimistic-lock="version" lazy="false">
<id name="id" column="userId">
<generator class="native" />
</id>
<version name="version" type="long" />
<property name="firstName" length="50" type="string" />
<property name="lastName" length="50" type="string" />
<property name="image" type="blob" />
<property name="conTentType" length="300" type="string" />
<property name="fileName" length="300" type="string" />
</class>
</hibernate-mapping>


Step 4: Hibernate configuration file oracle_hibernate.cfg.xml.

<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<!-- Database connection settings -->
<property name="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<property name="connection.url">jdbc:oracle:thin:@localhost:1521:ORACLE</property>
<property name="connection.username">pradeep</property>
<property name="connection.password">pradeep</property>
<!-- JDBC connection pool (use the built-in) -->
<property name="connection.pool_size">2</property>
<!-- SQL dialect -->
<property name="dialect">org.hibernate.dialect.Oracle10gDialect</property>
<!-- Disable the second-level cache -->
<property name="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>
<!-- Echo all executed SQL to stdout -->
<property name="show_sql">true</property>
<!-- Drop and re-create the database schema on startup -->
<property name="hbm2ddl.auto">update</property>
<mapping resource="org/paandav/blog/vo/User.hbm.xml" />
</session-factory>
</hibernate-configuration>


Step 5: Create applicationContext.xml file.

<?xml version="1.0" encoding="UTF-8"?>
<!-- Application context definition for Online Exam -->
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xsi:schemaLocation="
            http://www.springframework.org/schema/beans
            http://www.springframework.org/schema/beans/spring-beans.xsd
            http://www.springframework.org/schema/aop
            http://www.springframework.org/schema/aop/spring-aop.xsd
            http://www.springframework.org/schema/tx
            http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
            http://www.springframework.org/schema/jdbc
            http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
            http://www.springframework.org/schema/context
            http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- END FOR LOGIC LAYER -->
<context:annotation-config />
<!-- Instruct Spring to retrieve and apply @AspectJ aspects which are defined 
as beans in this context (such as the CallMonitoringAspect below). -->
<aop:aspectj-autoproxy />
<!-- Hibernate plugin code -->
<bean id="sessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="configurationClass" value="org.hibernate.cfg.AnnotationConfiguration" />
<property name="configLocation" value="classpath:oracle_hibernate.cfg.xml" />
</bean>
<bean id="userService" class=" org.paandav.bolg.service.UserServiceImpl">
<property name="userDao" ref="userDao"></property>
</bean>
<bean id="userDao" class="org.paandav.blog.dao.UserDAOImpl">
<property name="sessionFactory" ref="sessionFactory"></property>
</bean>
<!-- Transaction Manger -->
<bean id="txManager"
class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="*" propagation="SUPPORTS" isolation="READ_COMMITTED"
rollback-for="Exception" />
</tx:attributes>
</tx:advice>
<aop:config>
<aop:pointcut id="serviceLayerBeanMethods"
expression="execution(* org.paandav.bolg.service.*.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="serviceLayerBeanMethods" />
</aop:config>
</beans>

Step 6: Create struts.xml file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
    "http://struts.apache.org/dtds/struts-2.0.dtd">

<struts>
<constant name="struts.devMode" value="false" />
<constant name="struts.custom.i18n.resources" value="global" />
<constant name="struts.objectFactory" value="spring" />

<package name="commonPackage" namespace="/" extends="struts-default">

<result-types>
<result-type name="imageBytesResult"
class="org.paandav.blog.action.ImageBytesResult" />
</result-types>

<action name="addUserData" class="org.paandav.blog.action.UserAction">
<result name="input">
WEB-INF/jsp/imageUploader.jsp
</result>
</action>
<action name="displayFullImage" class="org.paandav.blog.action.FullImageAction">
<result name="input">
WEB-INF/jsp/dispalyFullImage.jsp
</result>
</action>

<action name="getImage" class="org.paandav.blog.action.GetImageAction">
<result name="imageBytesResult" type="imageBytesResult">
</result>
</action>
</package>

</struts>

Step 7: Create web.xml file
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/j2ee" xmlns:javaee="http://java.sun.com/xml/ns/javaee"
xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
id="WebApp_9" version="2.4">
<display-name>Open Online Exam</display-name>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>/WEB-INF/applicationContext.xml</param-value>
</context-param>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>
org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
<welcome-file-list>
<welcome-file>index.jsp</welcome-file>
</welcome-file-list>

<error-page>
<error-code>404</error-code>
<location>/index.jsp</location>
</error-page>

</web-app>

Step 8: Struts 2 action classes and validation files.
UserAction-validation.xml
<!DOCTYPE validators PUBLIC
        "-//OpenSymphony Group//XWork Validator 1.0.2//EN"
        "http://www.opensymphony.com/xwork/xwork-validator-1.0.2.dtd">

<validators>
<field name="firstName">
<field-validator type="requiredstring">
<message key="First name is blank" />
</field-validator>
</field>
<field name="lastName">
<field-validator type="requiredstring">
<message key="Last name is blank" />
</field-validator>
</field>
</validators>

UserAction.java

package org.paandav.blog.action;

import java.io.File;
import java.io.FileInputStream;
import java.sql.Blob;
import java.util.List;

import org.hibernate.Hibernate;
import org.paandav.blog.vo.User;
import org.paandav.bolg.service.UserService;

import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;
import com.opensymphony.xwork2.Preparable;

public class UserAction extends ActionSupport implements ModelDriven<User>,
Preparable {
private static final long serialVersionUID = 1L;
User user = new User();
private File file;
private String contentType;
private String filename;
private UserService userService;
private List<User> allUserList;
private String from;

public String getFrom() {
return from;
}

public void setFrom(String from) {
this.from = from;
}

public List<User> getAllUserList() {
return allUserList;
}

public void setAllUserList(List<User> allUserList) {
this.allUserList = allUserList;
}

public UserService getUserService() {
return userService;
}

public void setUserService(UserService userService) {
this.userService = userService;
}

public void setUpload(File file) {
this.file = file;
}

public void setUploadContentType(String contentType) {
this.contentType = contentType;
}

public void setUploadFileName(String filename) {
this.filename = filename;
}

@Override
public User getModel() {
return user;
}

@Override
public void validate() {
if ("INIT".equalsIgnoreCase(from)) {
clearErrors();
return;
}
if (file == null) {
addFieldError("upload", "Upload an image");
}
}

@Override
public String execute() throws Exception {

if ("INIT".equalsIgnoreCase(from)) {
return INPUT;
}
try {
if (file != null) {
Blob image = Hibernate.createBlob(new FileInputStream(file));
user.setImage(image);
user.setConTentType(contentType);
user.setFileName(filename);
}
userService.save(user);
allUserList = userService.getAllUsers();
addActionMessage("Data Saved successfully");
} catch (Exception ex) {
addActionError("Upload failed");
}
return INPUT;
}

@Override
public void prepare() throws Exception {
allUserList = userService.getAllUsers();

}

}

ImageBytesResult.java
package org.paandav.blog.action;

import javax.servlet.http.HttpServletResponse;

import org.apache.struts2.ServletActionContext;

import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;

public class ImageBytesResult implements Result {

private static final long serialVersionUID = 1L;

@Override
public void execute(ActionInvocation invocation) throws Exception {
GetImageAction action = (GetImageAction) invocation.getAction();
HttpServletResponse response = ServletActionContext.getResponse();

response.setContentType(action.getContentType());
response.setContentLength(action.getContentLength());
response.getOutputStream().write(action.getImageInBytes());
response.getOutputStream().flush();
}

}

GetImageAction.java
package org.paandav.blog.action;

import org.paandav.blog.vo.User;
import org.paandav.bolg.service.UserService;

import com.opensymphony.xwork2.ActionSupport;

public class GetImageAction extends ActionSupport {

private static final long serialVersionUID = 1L;
private UserService userService;
private Long id;
private User user;

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public UserService getUserService() {
return userService;
}

public void setUserService(UserService userService) {
this.userService = userService;
}

@Override
public String execute() throws Exception {

user = userService.getUserById(id);
return "imageBytesResult";
}

public byte[] getImageInBytes() {
return user.getImageInBytes();
}

public String getContentType() {
return user.getConTentType();
}

public String getContentDisposition() {
return "";
}

public int getContentLength() {
return user.getContentLength();
}

public int getBufferSize() {
return 1024;
}
}

FullImageAction.java
package org.paandav.blog.action;

import com.opensymphony.xwork2.ActionSupport;

public class FullImageAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private Long imageId;

public Long getImageId() {
return imageId;
}

public void setImageId(Long imageId) {
this.imageId = imageId;
}

@Override
public String execute() throws Exception {
return INPUT;
}
}

Step 9: Service layer java classes.
UserService.java
package org.paandav.bolg.service;

import java.util.List;

import org.paandav.blog.vo.User;

public interface UserService {
User save(User user) throws Exception;

List<User> getAllUsers() throws Exception;

User getUserById(long id) throws Exception;

}

UserServiceImpl.java
package org.paandav.bolg.service;

import java.util.List;

import org.paandav.blog.dao.UserDAO;
import org.paandav.blog.vo.User;

public class UserServiceImpl implements UserService {
private UserDAO userDao;

public UserDAO getUserDao() {
return userDao;
}

public void setUserDao(UserDAO userDao) {
this.userDao = userDao;
}

@Override
public User save(User user) throws Exception {

return userDao.save(user);
}

@Override
public List<User> getAllUsers() throws Exception {

return userDao.getAllUsers();
}

@Override
public User getUserById(long id) throws Exception {
return userDao.getUserById(id);
}
}

Step 10: DAO layer java classes

BaseDAO.java
package org.paandav.blog.dao;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class BaseDAO {
private SessionFactory sessionFactory;

public SessionFactory getSessionFactory() {
return sessionFactory;
}

public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}

protected Session getSession() {
return sessionFactory.getCurrentSession();
}

}

UserDAO.java
package org.paandav.blog.dao;

import java.util.List;

import org.paandav.blog.vo.User;

public interface UserDAO {

User save(User user) throws Exception;

List<User> getAllUsers() throws Exception;

User getUserById(long id) throws Exception;

}

UserDAOImpl.java
package org.paandav.blog.dao;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.List;

import org.paandav.blog.vo.User;

public class UserDAOImpl extends BaseDAO implements UserDAO {

@Override
public User save(User user) throws Exception {
getSession().save(user);
return user;
}

@SuppressWarnings("unchecked")
@Override
public List<User> getAllUsers() throws Exception {
List<User> allUsers = getSession().createQuery("from User").list();
return allUsers;
}

@Override
public User getUserById(long id) throws Exception {
User user = (User) getSession().get(User.class, new Long(id));
// Convert BLOB to byte array
user.setImageInBytes(getImageInBytes(user));
user.setContentLength((int) user.getImage().length());
return user;
}

public byte[] getImageInBytes(User user) {

if (user.getImage() == null) {
return new byte[0];
}
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
InputStream is = user.getImage().getBinaryStream();
byte[] buf = new byte[1024];
int i = 0;
while ((i = is.read(buf)) >= 0) {
baos.write(buf, 0, i);
}
is.close();
} catch (Exception ex) {
ex.printStackTrace();
}
return baos.toByteArray();
}
}



Step 11: jsp files in WEB-INF/jsp folder
imageUploader.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Insert title here</title>
</head>
<body style="font-family: verdana; margin-top: 3%;">
<div>
<table border=1 align="center">
<tr>
<td>First Name</td>
<td>Last Name</td>
<td>Photo</td>
<td>View full Image</td>
</tr>
<s:iterator value="allUserList">
<tr>
<td><s:property value="firstName" /></td>
<td><s:property value="lastName" /></td>
<td align="center"><img alt="" width="150" height="100"
src="getImage.action?id=<s:property value="id" />"></td>
<td><a href="displayFullImage.action?imageId=<s:property value="id" />" target="_new">View full Image</a></td>
</tr>
</s:iterator>
<s:form action="addUserData" theme="simple"
enctype="multipart/form-data">
<tr>
<td><font color="red"><s:fielderror fieldName="firstName" /></font>
<s:textfield name="firstName"></s:textfield></td>
<td><font color="red"><s:fielderror fieldName="lastName" /></font><s:textfield
name="lastName"></s:textfield></td>
<td colspan="3"><font color="red"><s:fielderror
fieldName="upload" /></font><s:file name="upload" label="file" /> <s:submit></s:submit></td>
</tr>
</s:form>
</table>
</div>
</body>
</html>


dispalyFullImage.jsp

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>


<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">


</head>
<body>
<table align="center">
<tr>
<td><img alt="" width="100%" height="100%"
src="getImage.action?id=<s:property value="imageId" />" /></td>
</tr>
</table>
</body>
</html>


Step 12: Now either deploy the application on Tomcat or Other Server or start server from eclipse and access the URL


http://localhost:8080/blogs_tutorials/addUserData.action?from=INIT


It will display a screen with upload options. Fill the data and upload the photos. All uploaded photos will be displayed on the same screen and you will see small uploaded images like below 


If you want to see the original size image click on View full Image link and it will display full image in new browser window like below.







12 comments:

  1. this doesn't execute... where is index.jsp and where does it map?.. let me know please..

    ReplyDelete
  2. yes sir...
    you should jsp file placed here. Without this we can not understand perfectly.

    ReplyDelete
  3. hi sir,
    Its a wonderful project , but , when i try to run this project am getting 404 error on submitting the imageUploader.jsp page, am so eager to see the output of this project,so please send the project zip to my mail id.

    ReplyDelete
  4. Well It Was Very Goog Information ForJava Learners I Was Reaaly happy See This Areticle.We Are Also Providing All Java Online Training Courses.
    Our Java Online Training Institute Is one Of The Best Training Institute In The World

    ReplyDelete
  5. Its a good post and keep posting good article.its very interesting to read.

    Selenium Training Institute in chennai | Selenium Testing Training in Chennai

    ReplyDelete
  6. Very valuable article i have ever come across.Thanks to provide me a solution very clearly through screenshots.
    samsung mobile service center in chennai
    samsung mobile service center
    samsung mobile service chennai
    samsung mobile repair

    ReplyDelete
  7. I am happy for sharing on this blog its awesome blog I really impressed. thanks for sharing. Great efforts.

    Looking for Best Training Institute in Bangalore , India. Softgen Infotech is the best one to offers 85+ computer training courses including IT Software Course in Bangalore , India. Also, it provides placement assistance service in Bangalore for IT.

    ReplyDelete
  8. This post is very simple to read and appreciate without leaving any details out. Great work! Call center software solutions in Nigeria

    ReplyDelete
  9. This is an excellent post I seen thanks to share it. It is really what I wanted to see hope in future you will continue for sharing such a excellent post. call center software in Nigeria

    ReplyDelete