Enterprise Java

Developing a personal mini Photo Gallery application using Struts2, Hibernate and MySQL BLOB – Part 1

Overview:

In this workshop we’ll develop a web application which we can use to create a beautiful photo gallery. This you can host in a web server or you can use in your own PC to maintain and manage your collection of photos. Using this tutorial you will be able to learn the following important points related to Struts2 and Hibernate:

  • How to integrate Struts2 framework with Hibernate
  • How to upload photo or file in Struts2
  • How to dynamically upload/download photos to and from MySQL BLOB field
  • How to pass parameters dynamically from one action to another action in Struts2

In Part-1 of this tutorial, we’ll develop the admin panel. Admin Panel will be used to create photo album and upload photos to the album. In Part-2 we’ll create the front end main web application which will display photos by albums as added in the admin panel.

Tools Used:

  1. Eclipse Indigo Java EE IDE for Web Developers
  2. Struts 2
  3. Hibernate 3
  4. Hibernate Tools Eclipse Plugin Version 3.5.1
  5. mysql JDBC jar (mysql-connector-java-5.1.23)
  6. Tomcat 7

Step 1: Preparing the Database MySQL for the Photo gallery application

We’ll be using MySQL database. Belw is the script for you to create the database tables. The database name use used is ‘tctalk_apps_photoalbum’ . However you can create any database name. Just remember you need to change the database name in Hibernate configuration file. Below are SQLs for the two tables album and phototbl.

1
2
3
4
5
6
7
CREATE TABLE IF NOT EXISTS `album` (
  `albumid` INT(4) NOT NULL AUTO_INCREMENT,
  `albumname` VARCHAR(55) NOT NULL,
  `albumdesc` text NOT NULL,
  `albumcreatedate` DATE NOT NULL,
  PRIMARY KEY (`albumid`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;
01
02
03
04
05
06
07
08
09
10
CREATE TABLE IF NOT EXISTS `phototbl` (
  `photoid` INT(4) NOT NULL AUTO_INCREMENT,
  `albumid` INT(4) NOT NULL,
  `phototitle` VARCHAR(255) NOT NULL,
  `photoname` VARCHAR(255) NOT NULL,
  `imgcontenttype` VARCHAR(255) NOT NULL,
  `photocreatedate` datetime NOT NULL,
  `photodata` longblob NOT NULL,
  PRIMARY KEY (`photoid`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1;

Step 2: Create the packages in the java source

Create the packages in java src side after creating the dynamic web project in Eclipse. Remember the packages com.tctalk.apps.album.db.xxx holds all java and other files for working in database/hibernate side whereas com.tctalk.apps.album.web.xxx will have all java files for the presentation layer using struts2 framework.

image001

Businessobjects will have all BO classes mapped with tables. Dao will have the DAO classes to call database using Hibernate. Hbm will have *.hbm.xml files which has the mapping of the table fields and table java. Utils will have all kind of Utility classes. Actions will have all Action classes of the Struts2 framework. Delegates will have the delegate classes as a bridge between UI layer and DB layer. Forms will have the POJO(Plain Old Java Objects) correspond to UI fields. Hibernate.cfg.xml has the hibernate configuration file to have database connection information to connect to the database. Struts.xml has the Struts configurations data.

Step 3: Copy the jar files in the lib folder

image003

You would require servlet-api.jar file which you’ll get from Tomcat installation directory. My Tomcat is in C:\Java\Tomcat\tomcat7 folder.

Step 4: Add Struts 2 support to our app

We already have the required jar files for Struts2 support in our app. Now it is time to include the Struts2.xml and put the reference in web.xml to let Tomcat know about it.

Web.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<?xml version="1.0" encoding="UTF-8"?>
<display-name>PersonalPhotoAlbumApp</display-name>
  <welcome-file-list>
    <welcome-file>index.jsp</welcome-file>
  </welcome-file-list>
 <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>*.action</url-pattern>
</filter-mapping>
</web-app>

Struts.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE struts PUBLIC
    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
 
<struts>
 
    <constant name="struts.enable.DynamicMethodInvocation" value="false" />
    <constant name="struts.devMode" value="false" />
 
    <package name="default" extends="struts-default" namespace="/">
 
    <result-types>
        <result-type name="imageResult" class="com.tctalk.apps.album.web.actions.CustomPhotoResult" />
    </result-types>
 
    <default-action-ref name="index" />
 
    <action name="index">
        <result>index.jsp</result>
    </action>
 
    <action name="admin">
        <result name="success" type="redirectAction">listAlbumAdmn</result>
    </action>
 
    <action name="listAlbumAdmn"
        class="com.tctalk.apps.album.web.actions.PhotoAlbumAdminAction" method="getAllAlbumList" >
        <result name="success">/WEB-INF/admin/jsp/showalbums.jsp</result>
    </action>
 
    <action name="addAlbumAdmn"
        class ="com.tctalk.apps.album.web.actions.PhotoAlbumAdminAction" method="addAlbumToCollection" >
        <result name="input">listAlbumAdmn</result>
        <result name="success" type="redirectAction">listAlbumAdmn</result>
    </action>
 
    <action name="delAlbumAdmn"
        class ="com.tctalk.apps.album.web.actions.PhotoAlbumAdminAction" method="delAlbumFromCollection" >
        <result name="success" type="redirectAction">listAlbumAdmn</result>
    </action>
 
    <action name="listPhotosByAlbumAdmn"
        class="com.tctalk.apps.album.web.actions.PhotoAlbumAdminAction" method="listAllPhotos" >
        <result name="success">/WEB-INF/admin/jsp/showphotos.jsp</result>
    </action>
 
    <action name="addPhotoAcion"
        class ="com.tctalk.apps.album.web.actions.PhotoAlbumAdminAction" method="uploadPhotoToAlbum" >
            <interceptor-ref name="exception"/>
            <interceptor-ref name="i18n"/>
            <interceptor-ref name="fileUpload">
                <param name="allowedTypes">image/x-png,image/png,image/gif,image/jpeg,image/pjpeg</param>
            </interceptor-ref>
            <interceptor-ref name="params">
                <param name="excludeParams">dojo\..*,^struts\..*</param>
            </interceptor-ref>
            <interceptor-ref name="validation">
                <param name="excludeMethods">input,back,cancel,browse</param>
            </interceptor-ref>
            <interceptor-ref name="workflow">
                <param name="excludeMethods">input,back,cancel,browse</param>
            </interceptor-ref>
 
        <result name="success" type="redirectAction">
            <param name="actionName">listPhotosByAlbumAdmn</param>
            <param name="albumid">${albumid}</param>
        </result>
 
        <result name="input">/WEB-INF/admin/jsp/showphotos.jsp</result>
    </action>
 
    <action name="delPhotoFrmAlbumAdmn"
        class ="com.tctalk.apps.album.web.actions.PhotoAlbumAdminAction" method="delPhoto" >
        <result name="success" type="redirectAction">
            <param name="actionName">listPhotosByAlbumAdmn</param>
            <param name="albumid">${albumid}</param>
        </result>
    </action>
 
    <action name="showPhotoAction" 
        class="com.tctalk.apps.album.web.actions.PhotoAlbumAdminAction" method="showPhoto">
        <result name="success" type="imageResult"/>
    </action>
 
 </package>
 
</struts>

Step 5: Add Hibernate support to our photo album app

To work with hibernate we already have a nice step by step tutorial which shows how you can use Hibernate plugin in Eclipse to auto-generate the hbm and java files coresponds to the tables in your database. Check the tutorial – http://www.techcubetalk.com/2013/04/step-by-step-auto-code-generation-for-pojo-domain-java-classes-and-hbm-files-using-elipse-hibernate-plugin/

  1. Create hibernate.cfg.xml with database connection information to connect to the database
  2. Create the POJO classes using the plugin and keep in the package corresponding to the tables. In our app we’ll be using two tables album and phototbl, so we have two POJO classes for that.
  3. Then add the hbm files correspond to the two POJO classes created in above steps
  4. Next we’ll add the HibernateUtils.java for handling the hibernate session easily in our application. Also in the same package we are keeping one constant file to keep any constants we have in our project.
  5. Now we’ll add the DAO classes which will have all the methods to interact with database.
    1. ListgetAllPhotoAlbums() – returns list of all albums from the database
    2. boolean addAlbum(AlbumBO album) – this adds an album to the database
    3. boolean delAlbum(int albumId) – delete the album and all the photos under this album
    4. ListgetAllPhotosFromAlbum(int albumid) – Returns all photos from the album based on the albumid
    5. boolean addPhotoToAlbum(PhototblBO photo) – add photo object to the album
    6. boolean delPhotoFromAlbum(int photoid) – delete photo from the album
    7. ListgetPhoto(int photoid) – returns the photo object to display in the page

hibernate.cfg.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/tctalk_apps_photoalbum</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password"></property>
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
        <property name="show_sql">true</property>
 
    <mapping resource="com/tctalk/apps/album/db/hbm/Album.hbm.xml" />
    <mapping resource="com/tctalk/apps/album/db/hbm/Phototbl.hbm.xml" />
 
    </session-factory>   
</hibernate-configuration>

AlbumBO.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
package com.tctalk.apps.album.db.businessobjects;
// Generated Apr 22, 2013 1:26:39 PM by Hibernate Tools 3.4.0.CR1
 
import java.util.Date;
 
/**
 * Album generated by hbm2java
 */
public class AlbumBO implements java.io.Serializable {
 
    private Integer albumid;
    private String albumname;
    private String albumdesc;
    private Date albumcreatedate;
 
    public AlbumBO() {
    }
 
    public AlbumBO(String albumname, String albumdesc, Date albumcreatedate) {
        this.albumname = albumname;
        this.albumdesc = albumdesc;
        this.albumcreatedate = albumcreatedate;
    }
 
    public Integer getAlbumid() {
        return this.albumid;
    }
 
    public void setAlbumid(Integer albumid) {
        this.albumid = albumid;
    }
 
    public String getAlbumname() {
        return this.albumname;
    }
 
    public void setAlbumname(String albumname) {
        this.albumname = albumname;
    }
 
    public String getAlbumdesc() {
        return this.albumdesc;
    }
 
    public void setAlbumdesc(String albumdesc) {
        this.albumdesc = albumdesc;
    }
 
    public Date getAlbumcreatedate() {
        return this.albumcreatedate;
    }
 
    public void setAlbumcreatedate(Date albumcreatedate) {
        this.albumcreatedate = albumcreatedate;
    }
 
}

PhototblBO.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package com.tctalk.apps.album.db.businessobjects;
// Generated Apr 22, 2013 1:26:39 PM by Hibernate Tools 3.4.0.CR1
 
import java.util.Date;
 
/**
 * Phototbl generated by hbm2java
 */
public class PhototblBO implements java.io.Serializable {
 
    private int photoid;
    private int albumid;
    private String phototitle;
    private String photoname;
    private String imgcontenttype;
    private Date photocreatedate;
    private byte[] photodata;
 
    public PhototblBO() {
    }
 
    public PhototblBO(int photoid, int albumid, String phototitle,
            String photoname, String imgcontenttype, Date photocreatedate,
            byte[] photodata) {
        this.photoid = photoid;
        this.albumid = albumid;
        this.phototitle = phototitle;
        this.photoname = photoname;
        this.imgcontenttype = imgcontenttype;
        this.photocreatedate = photocreatedate;
        this.photodata = photodata;
    }
 
    public int getPhotoid() {
        return this.photoid;
    }
 
    public void setPhotoid(int photoid) {
        this.photoid = photoid;
    }
 
    public int getAlbumid() {
        return this.albumid;
    }
 
    public void setAlbumid(int albumid) {
        this.albumid = albumid;
    }
 
    public String getPhototitle() {
        return this.phototitle;
    }
 
    public void setPhototitle(String phototitle) {
        this.phototitle = phototitle;
    }
 
    public String getPhotoname() {
        return this.photoname;
    }
 
    public void setPhotoname(String photoname) {
        this.photoname = photoname;
    }
 
    public String getImgcontenttype() {
        return this.imgcontenttype;
    }
 
    public void setImgcontenttype(String imgcontenttype) {
        this.imgcontenttype = imgcontenttype;
    }
 
    public Date getPhotocreatedate() {
        return this.photocreatedate;
    }
 
    public void setPhotocreatedate(Date photocreatedate) {
        this.photocreatedate = photocreatedate;
    }
 
    public byte[] getPhotodata() {
        return this.photodata;
    }
 
    public void setPhotodata(byte[] photodata) {
        this.photodata = photodata;
    }
 
}

Album.hbm.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
<!-- Generated Apr 22, 2013 1:26:40 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.tctalk.apps.album.db.businessobjects.AlbumBO" table="album" catalog="tctalk_apps_photoalbum">
        <id name="albumid" type="java.lang.Integer">
            <column name="albumid" />
            <generator class="identity" />
        </id>
        <property name="albumname" type="string">
            <column name="albumname" length="55" not-null="true" />
        </property>
        <property name="albumdesc" type="string">
            <column name="albumdesc" length="65535" not-null="true" />
        </property>
        <property name="albumcreatedate" type="date">
            <column name="albumcreatedate" length="10" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

Phototbl.hbm.xml

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
<!-- Generated Apr 22, 2013 1:26:40 PM by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
    <class name="com.tctalk.apps.album.db.businessobjects.PhototblBO" table="phototbl" catalog="tctalk_apps_photoalbum">
        <id name="photoid" type="int">
            <column name="photoid" />
            <generator class="assigned" />
        </id>
        <property name="albumid" type="int">
            <column name="albumid" not-null="true" />
        </property>
        <property name="phototitle" type="string">
            <column name="phototitle" not-null="true" />
        </property>
        <property name="photoname" type="string">
            <column name="photoname" not-null="true" />
        </property>
        <property name="imgcontenttype" type="string">
            <column name="imgcontenttype" not-null="true" />
        </property>
        <property name="photocreatedate" type="timestamp">
            <column name="photocreatedate" length="19" not-null="true" />
        </property>
        <property name="photodata" type="binary">
            <column name="photodata" not-null="true" />
        </property>
    </class>
</hibernate-mapping>

HibernateUtils.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package com.tctalk.apps.album.utils;
 
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
 
public class HibernateUtils {
    private static SessionFactory hbmSessionFactory;
 
    static {
        try {
            Configuration cfg = new Configuration()
                    .configure(PhotoAlbumConstant._HIBERNATE_CONFIG_LOCATION);
            hbmSessionFactory = cfg.buildSessionFactory();
        } catch (RuntimeException ex) {
            System.out.println("********* Error occurred while reading config file *********");
            ex.printStackTrace();
        }
    }
 
    /**
     * getSession creates hibernate Session & returns it
     */
    public static Session getSession() {
        return hbmSessionFactory.openSession();
    }
 
    /**
     * closeSession closes the session, if it exists
     */
    public static void closeSession(Session inSession) {
        if (inSession != null) {
            inSession.close();
        }
    }
}

PhotoAlbumConstant.java

1
2
3
4
5
6
7
package com.tctalk.apps.album.utils;
 
public interface PhotoAlbumConstant {
 
    String _HIBERNATE_CONFIG_LOCATION = "hibernate.cfg.xml";
    String _HQL_DEL_PHOTOS_ALBUM = "DELETE FROM PhototblBO WHERE albumid= :albumid";   
}

PhotoAlbumAdminDao.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
package com.tctalk.apps.album.db.dao;
 
import java.util.List;
 
import com.tctalk.apps.album.db.businessobjects.AlbumBO;
import com.tctalk.apps.album.db.businessobjects.PhototblBO;
 
public interface PhotoAlbumAdminDao {
    // Photo Album related operations
    public List<AlbumBO> getAllPhotoAlbums();
    public boolean addAlbum(AlbumBO album);
    public boolean delAlbum(int albumId);
 
    //Photo related operations
    public List<PhototblBO> getAllPhotosFromAlbum(int albumid);
    public boolean addPhotoToAlbum(PhototblBO photo);
    public boolean delPhotoFromAlbum(int photoid);
    public List<PhototblBO> getPhoto(int photoid);
}

PhotoAlbumAdminDaoImpl.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
package com.tctalk.apps.album.db.dao;
 
import java.util.Date;
import java.util.List;
 
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Restrictions;
 
import com.tctalk.apps.album.db.businessobjects.AlbumBO;
import com.tctalk.apps.album.db.businessobjects.PhototblBO;
import com.tctalk.apps.album.utils.HibernateUtils;
import com.tctalk.apps.album.utils.PhotoAlbumConstant;
 
public class PhotoAlbumAdminDaoImpl implements PhotoAlbumAdminDao, PhotoAlbumConstant {
 
    /**
     * The below methods will be used for handling the Photo album related
     * operations
     *
     */
 
    /**
     * This function retrieves all the photo albums and send the list to the
     * front end
     */
    public List<AlbumBO> getAllPhotoAlbums() {
        List<AlbumBO> albumList = null;
        Session hbmSession = null;
        try {
            hbmSession = HibernateUtils.getSession();
            Criteria criteria = hbmSession.createCriteria(AlbumBO.class);
            albumList = criteria.list();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            HibernateUtils.closeSession(hbmSession);
        }
 
        return albumList;
    }
 
    /**
     * This function adds one photo album to the database
     */
    public boolean addAlbum(AlbumBO album) {
        Session hbmSession = null;
        boolean STATUS_FLAG = true;
        try {
            hbmSession = HibernateUtils.getSession();
            hbmSession.beginTransaction();
 
            // change the creation date to today's date in the album object
            album.setAlbumcreatedate(new Date());
            // add the album to the hibernate session to save
            hbmSession.save(album);
            hbmSession.getTransaction().commit();
        } catch (Exception ex) {
            hbmSession.getTransaction().rollback();
            ex.printStackTrace();
            STATUS_FLAG = false;
        } finally {
            HibernateUtils.closeSession(hbmSession);
        }
        return STATUS_FLAG;
    }
 
    /**
     * This function deletes the photoalbum based on the album id. It first
     * check if the album has any photos or not. If the album is not emptry then
     * it deletes the photos first and then delete the album itself
     */
    public boolean delAlbum(int albumId) {
        Session hbmSession = null;
        boolean STATUS_FLAG = true;
        try {
            // get the hibernate session to perform delete operation
            hbmSession = HibernateUtils.getSession();
            hbmSession.beginTransaction();
 
            //delete all photos from the Photo table correspond to the album id
            Query query = hbmSession.createQuery(_HQL_DEL_PHOTOS_ALBUM);
            query.setInteger("albumid", new Integer(albumId));
            int rowCount = query.executeUpdate();
            System.out.println("Rows affected: " + rowCount);
 
            //now load the album object from Album table and delete it correspond to the album id
            AlbumBO albumObj = (AlbumBO) hbmSession.load(AlbumBO.class, albumId);
            hbmSession.delete(albumObj);
 
            hbmSession.getTransaction().commit();
        } catch (Exception ex) {
            hbmSession.getTransaction().rollback();
            ex.printStackTrace();
            STATUS_FLAG = false;
        } finally {
            HibernateUtils.closeSession(hbmSession);
        }
        return STATUS_FLAG;
    }
 
    /**
     * The below functions will be helpful to work on the Photos in the photo
     * album
     */
 
    /**
     * This function retrieves all the photos and send the list to the front end
     */
    public List<PhototblBO> getAllPhotosFromAlbum(int albumid) {
        List<PhototblBO> photoList = null;
        Session hbmSession = null;
        Criteria criteria = null;
 
        try {
            hbmSession = HibernateUtils.getSession();
            hbmSession.beginTransaction();
 
            // retrieve all photos from photo table correspond to the album Id
            criteria = hbmSession.createCriteria(PhototblBO.class).add(
                    Restrictions.eq("albumid", albumid));
            photoList = criteria.list();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            HibernateUtils.closeSession(hbmSession);
        }
        return photoList;
    }
 
    /**
     * This function adds photo to the album
     */
    public boolean addPhotoToAlbum(PhototblBO photoobj) {
        Session hbmSession = null;
        boolean STATUS_FLAG = true;
        try {
            hbmSession = HibernateUtils.getSession();
            hbmSession.beginTransaction();
            hbmSession.save(photoobj);
            hbmSession.getTransaction().commit();
        } catch (Exception ex) {
            hbmSession.getTransaction().rollback();
            ex.printStackTrace();
            STATUS_FLAG = false;
        } finally {
            HibernateUtils.closeSession(hbmSession);
        }
        return STATUS_FLAG;
    }
 
    /**
     * This function deletes the photo from the album itself
     */
    public boolean delPhotoFromAlbum(int photoid) {
        Session hbmSession = null;
        boolean STATUS_FLAG = true;
 
        try {
            // get the hibernate session to perform delete operation
            hbmSession = HibernateUtils.getSession();
            hbmSession.beginTransaction();
            PhototblBO photoobj = (PhototblBO) hbmSession.load(
                    PhototblBO.class, photoid);
            hbmSession.delete(photoobj);
            hbmSession.getTransaction().commit();
        } catch (Exception ex) {
            hbmSession.getTransaction().rollback();
            ex.printStackTrace();
            STATUS_FLAG = false;
        } finally {
            HibernateUtils.closeSession(hbmSession);
        }
        return STATUS_FLAG;
    }
 
    /**
     * This function returns the photo object itself
     */
    public List<PhototblBO> getPhoto(int photoid) {
        List<PhototblBO> photoList = null;
        Session hbmSession = null;
        Criteria criteria = null;
 
        try {
            hbmSession = HibernateUtils.getSession();
            hbmSession.beginTransaction();
 
            // retrieve all photos from photo table correspond to the album Id
            criteria = hbmSession.createCriteria(PhototblBO.class).add(
                    Restrictions.eq("photoid", photoid));
            photoList = criteria.list();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            HibernateUtils.closeSession(hbmSession);
        }
        return photoList;
    }
 
}

Step 6: Develop the UI part

Create the ‘admin’ folder to keep all admin related UI files. Though we’ll not have CSS or JavaScript file in our app still we’ll create folders as a placeholder. We’ll add two jsp files – showalbums.jsp – this will be used to show existing albums as well as fields to add one album to the database

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>TechcubeTalk.com - Let's build apps from scratch series - Personal Photo Album App</title>
</head>
<body>
<h2>:: TechcubeTalk.com - Personal Photo Album Admin Panel ::</h2>
<div style="margin-bottom: 25px;">
<s:form action="addAlbumAdmn" method="POST">
        <s:textfield label="Photo Album Name/Title" name="album.albumname"/>
        <s:textfield label="Optional Brief Description" name="album.albumdesc"/>
        <br/>
        <s:submit value="Create Photo Album" align="center"/>
</s:form>
<hr/>
</div>
<div>
    <table style="border: 1px dotted black;">
    <tr>
        <th style="background-color:#ABDCFF;" align="center"> Album Id </th>
        <th style="background-color:#ABDCFF;" align="center"> Photo Album Title </th>
        <th style="background-color:#ABDCFF;" align="center"> Brief Description </th>
        <th style="background-color:#ABDCFF;" align="center"> Created On </th>
        <th style="background-color:#ABDCFF;" align="center"> Delete? </th>
        <th style="background-color:#ABDCFF;" align="center"> View Photos in Album </th>
    </tr>
    <s:iterator value="albumList" var="album">
        <tr>
            <td align="center"><s:property value="albumid"/></td>
            <td align="center"><s:property value="albumname"/></td>
            <td align="center"><s:property value="albumdesc"/></td>
            <td align="center"><s:property value="albumcreatedate"/></td>
            <td align="center"> <a href="delAlbumAdmn.action?albumid=<s:property value="albumid"/>">Delete</a> </td>
            <td align="center"> <a href="listPhotosByAlbumAdmn.action?albumid=<s:property value="albumid"/>">Click to View</a> </td>
        </tr>
    </s:iterator>
    </table>
</div>
</body>
</html>

showphotos.jsp – this jsp will show all photos under the album user will click. Also it will show fields to upload photos under that directory.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="s" uri="/struts-tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>TechcubeTalk.com - Let's build apps from scratch series - Personal Music Manager Application</title>
</head>
<body>
<h2>:: TechcubeTalk.com - Personal Photo Album Admin Panel ::</h2>
<div style="margin-bottom: 25px;">
<s:form action="addPhotoAcion" namespace="/" method="POST" enctype="multipart/form-data">
<s:textfield label="Photo Title" name="photoTitle"/>
<s:file name="fileUpload" label="Select a File to upload" size="40" />
<s:hidden name="albumid" value="%{albumid}" />
 
<s:submit value="Upload Photo to Album" name="submit" />
</s:form>
 
</div>
<div> <a href="listAlbumAdmn.action"><< Back to Albums</a></div>
<div>
    <table style="border: 1px dotted black;">
    <tr>
        <th style="background-color:#ABDCFF;">Photo Id</th>
        <th style="background-color:#ABDCFF;">Photo Title</th>
        <th style="background-color:#ABDCFF;">Upload Date</th>
        <th style="background-color:#ABDCFF;">View Photo</th>
        <th style="background-color:#ABDCFF;">Delete Photo</th>
    </tr>
    <s:iterator value="photoList" var="photo">
        <tr>
            <td><s:property value="photoid"/></td>
            <td><s:property value="phototitle"/></td>
            <td><s:property value="photocreatedate"/></td>
            <td><a href="showPhotoAction.action?photoid=<s:property value="photoid"/>" target="_blank">View</a></td>
            <td><a href="delPhotoFrmAlbumAdmn.action?albumid=<s:property value="albumid"/>&photoid=<s:property value="photoid"/>">Delete</a></td>
        </tr>
    </s:iterator>
    </table>
</div>
</body>
</html>

Step 7: Add Action classes and the custom result class

PhotoAlbumAdminAction extends the POJO PhotoAlbumForm.java to hold submitted form fields and other values for the UI page. We uses one custom result displaying the photo by fetching it as binary file from the BLOB field database.

PhotoAlbumAdminAction.java

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package com.tctalk.apps.album.web.actions;
 
import java.io.IOException;
import java.util.Date;
import java.util.List;
 
import org.apache.commons.io.FileUtils;
 
import com.tctalk.apps.album.db.businessobjects.AlbumBO;
import com.tctalk.apps.album.db.businessobjects.PhototblBO;
import com.tctalk.apps.album.web.delegates.PhotoAlbumAdminDelegate;
import com.tctalk.apps.album.web.forms.PhotoAlbumForm;
 
public class PhotoAlbumAdminAction extends PhotoAlbumForm {
 
    private static final long serialVersionUID = 9168149105719285096L;
    private PhotoAlbumAdminDelegate delegate = new PhotoAlbumAdminDelegate();
 
    public String getAllAlbumList() {
        List<AlbumBO> albumList = delegate.getAllPhotoAlbums();
        String returnString = ERROR;
 
        if (albumList != null) {
            setAlbumList(albumList);
            returnString = SUCCESS;
        }
        return returnString;
    }
 
    public String addAlbumToCollection() {
        String returnString = ERROR;
        AlbumBO album = getAlbum();
 
        if (delegate.addAlbumToCollection(album)) {
            returnString = SUCCESS;
        }
 
        return returnString;
    }
 
    public String delAlbumFromCollection() {
        String returnString = ERROR;
 
        int albumId = getAlbumid();
        if (delegate.delAlbumFromCollection(albumId)) {
            returnString = SUCCESS;
        }
 
        return returnString;
    }
 
    public String listAllPhotos() {
        List<PhototblBO> photoList = delegate.getAllPhotos(this.getAlbumid());
        String returnString = ERROR;
 
        if (photoList != null) {
            this.setPhotoList(photoList);
            returnString = SUCCESS;
        }
        return returnString;
    }
 
    public String uploadPhotoToAlbum() {
        String returnString = ERROR;
        PhototblBO photoBO = new PhototblBO();
 
        // set the uploaded file meta data to the PhototblBO object before
        // saving to database
        photoBO.setAlbumid(getAlbumid());
        photoBO.setPhotocreatedate(new Date());
        photoBO.setImgcontenttype(getFileUploadContentType());
        photoBO.setPhotoname(getFileUploadFileName());
        photoBO.setPhototitle(getPhotoTitle());
        try {
            // the uploaded file is in File format so we need to convert to
            // byte[] array for storing in our database. For this apache
            //common file utility class is used below.
            photoBO.setPhotodata(FileUtils.readFileToByteArray(getFileUpload()));
        } catch (IOException e) {
            e.printStackTrace();
        }
 
        setPhotobo(photoBO);
        setAlbumid(photoBO.getAlbumid());
        if (delegate.addAPhoto(getPhotobo())) {
            returnString = SUCCESS;
        }
 
        return returnString;
    }
 
    public String delPhoto() {
        String returnString = ERROR;
 
        int photoId = getPhotoid();
        if (delegate.delPhoto(photoId)) {
            returnString = SUCCESS;
        }
 
        return returnString;
    }
 
    public String showPhoto() {
        String returnString = ERROR;
        List<PhototblBO> photoList = delegate.getPhoto(this.getPhotoid());
 
        if (photoList != null) {
            PhototblBO photoBO = (PhototblBO)photoList.get(0);
            if(photoBO != null){
                setPhotobo(photoBO);
                returnString = SUCCESS;
            }
        }
        return returnString;
    }
 
}

PhotoAlbumForm.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
package com.tctalk.apps.album.web.forms;
 
import java.io.File;
import java.util.List;
 
import com.opensymphony.xwork2.ActionSupport;
import com.tctalk.apps.album.db.businessobjects.AlbumBO;
import com.tctalk.apps.album.db.businessobjects.PhototblBO;
 
public class PhotoAlbumForm extends ActionSupport{
 
    private static final long   serialVersionUID         = 706337856877546963L;
 
    private List<AlbumBO>         albumList                = null;
    private List<PhototblBO>  photoList                = null;
 
    private AlbumBO             album                    = null;
    private PhototblBO          photobo                  = null;
 
    private File                fileUpload;
    private String              fileUploadContentType;
    private String              fileUploadFileName;
    private String              photoTitle;
    private int                 photoid;
    private int                 albumid;
 
    public String getFileUploadContentType() {
        return fileUploadContentType;
    }
 
    public void setFileUploadContentType(String fileUploadContentType) {
        this.fileUploadContentType = fileUploadContentType;
    }
 
    public String getFileUploadFileName() {
        return fileUploadFileName;
    }
 
    public void setFileUploadFileName(String fileUploadFileName) {
        this.fileUploadFileName = fileUploadFileName;
    }
 
    public File getFileUpload() {
        return fileUpload;
    }
 
    public void setFileUpload(File fileUpload) {
        this.fileUpload = fileUpload;
    }
 
    public String getPhotoTitle() {
        return photoTitle;
    }
 
    public void setPhotoTitle(String photoTitle) {
        this.photoTitle = photoTitle;
    }
 
    public List<AlbumBO> getAlbumList() {
        return albumList;
    }
    public void setAlbumList(List<AlbumBO> albumList) {
        this.albumList = albumList;
    }
    public List<PhototblBO> getPhotoList() {
        return photoList;
    }
    public void setPhotoList(List<PhototblBO> photoList) {
        this.photoList = photoList;
    }
    public AlbumBO getAlbum() {
        return album;
    }
    public void setAlbum(AlbumBO album) {
        this.album = album;
    }
    public PhototblBO getPhotobo() {
        return photobo;
    }
    public void setPhotobo(PhototblBO photobo) {
        this.photobo = photobo;
    }
    public int getPhotoid() {
        return photoid;
    }
    public void setPhotoid(int photoid) {
        this.photoid = photoid;
    }
    public int getAlbumid() {
        return albumid;
    }
    public void setAlbumid(int albumid) {
        this.albumid = albumid;
    }
}

CustomPhotoResult.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
package com.tctalk.apps.album.web.actions;
 
import javax.servlet.http.HttpServletResponse;
 
import org.apache.struts2.ServletActionContext;
 
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.Result;
 
public class CustomPhotoResult implements Result {
 
    private static final long serialVersionUID = 1L;
 
    public void execute(ActionInvocation invocation) throws Exception {
        PhotoAlbumAdminAction action = (PhotoAlbumAdminAction) invocation.getAction();
        HttpServletResponse response = ServletActionContext.getResponse();
 
        response.setContentType(action.getPhotobo().getImgcontenttype());
        response.setHeader("Content-Disposition", "inline; filename=\"" + action.getPhotobo().getPhotoname() + "\"");
        response.setHeader("cache-control", "no-cache");
        response.getOutputStream().write(action.getPhotobo().getPhotodata());
        response.getOutputStream().flush();
        response.getOutputStream().close();
    }
}

Step 8: Add the delegate class

Delegate class works as a bridge between Struts2 presentation layer and the business layer developed with Hibernate.

PhotoAlbumAdminDelegate.java

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.tctalk.apps.album.web.delegates;
 
import java.util.List;
 
import com.tctalk.apps.album.db.businessobjects.AlbumBO;
import com.tctalk.apps.album.db.businessobjects.PhototblBO;
import com.tctalk.apps.album.db.dao.PhotoAlbumAdminDao;
import com.tctalk.apps.album.db.dao.PhotoAlbumAdminDaoImpl;
 
public class PhotoAlbumAdminDelegate {
    PhotoAlbumAdminDao admindao = (PhotoAlbumAdminDao) new PhotoAlbumAdminDaoImpl();
 
    // Photo Album related functions
 
    public List<AlbumBO> getAllPhotoAlbums() {
        return admindao.getAllPhotoAlbums();
    }
 
    public boolean addAlbumToCollection(AlbumBO album) {
        return admindao.addAlbum(album);
    }
 
    public boolean delAlbumFromCollection(int albumId) {
        return admindao.delAlbum(albumId);
    }
 
    //Only Photo related functions
 
    public List<PhototblBO> getAllPhotos(int albumId) {
        return admindao.getAllPhotosFromAlbum(albumId);
    }
 
    public boolean addAPhoto(PhototblBO photo) {
        return admindao.addPhotoToAlbum(photo);
    }
 
    public boolean delPhoto(int photoid) {
        return admindao.delPhotoFromAlbum(photoid);
    }
 
    public List<PhototblBO> getPhoto(int photoid) {
        return admindao.getPhoto(photoid);
    }
}

Step 9: Final Integration

The entire project structure will be similar to the following:

image005

In the struts.xml file when we are redirecting from one action to another action we need to pass the album id . For example after a photo is uploaded to the database you need to redirect back to the all photo list under that album. So we need to send back the albumid also after photo is added. For doing this we used ${albumid} in struts.xml to pass the albumid from the POJO form.

Once the project is done generate the WAR file from eclipse. To do this do right click on project and select Export -> WAR file to create the WAR file and deploy in Tomcat.

If your deployment is successful and there is no error message in Tomcat console (ignore any warning like LOG4J etc.) then launch the browser and type the URL – http://localhost:8080/PersonalPhotoAlbumApp/admin.action

This will invoke the admin panel and the list of categories will be shown(first time no result will be shown so go ahead and add one album).

image007

Select ‘Click to View’ to go to Photos page and you can upload photos in that page or view the photos uploaded.

image009

That’s all for today. In the 2nd Part I’ll develop the front end panel which will show albums and the photos in that album using jQuery and Struts2 and Hibernate.

Download Source Files:

I’ve already given all the source codes in above steps. The eclipse project(with jars) and the WAR files are uploaded in GitHub repo.
 

Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy
Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

11 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
subbareddy
subbareddy
11 years ago

Hi Im subbareddy ,
your code is so good and Im wait for second part can u post that.
Thanks.

Suvoraj
11 years ago
Reply to  subbareddy

Hi Subbareddy, Thanks for your comment. I’ll try to publish the part tutorial using Spring MVC very soon.

skr
skr
11 years ago

hi ,
your code is not working properly,

firstly index.jsp is not available.

secondally it get error,

java.lang.reflect.InvocationTargetException
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)

java.lang.NoSuchFieldError: INSTANCE
org.hibernate.type.BasicTypeRegistry.(BasicTypeRegistry.java:94)
org.hibernate.type.TypeResolver.(TypeResolver.java:59)
org.hibernate.cfg.Configuration.(Configuration.java:250)
org.hibernate.cfg.Configuration.(Configuration.java:302)

Suvoraj
11 years ago
Reply to  skr

Have you downloaded the Jars from the repo https://github.com/smweb239/techcubetalk_com ?
Also you don’t need index.jsp as here I only showcased the admin part. In next tutorial part 2 we’ll develop the front end.

skr
skr
11 years ago
Reply to  Suvoraj

Hi Suvoraj
As u mentioned index.jsp in web.xml as welcome file but u didn’t gave index,jsp code on ur site

ashish
ashish
8 years ago
Reply to  Suvoraj

hey i have an error in class photoAlbumAdminDaoImpl

ashish
ashish
8 years ago
Reply to  Suvoraj

and i have also error in PhotoAlbumAdminAction class

Justin Mathew
Justin Mathew
10 years ago

Hai, your post is very nice. i am developing a photo gallaery using struts. how can i download the source files of your example. .?

Matteo
Matteo
10 years ago

Wow, this is fantastic, when the 2 part?

this is the index.jsp for test the app:

Insert title here

<<to Albums<<

neha
neha
10 years ago

Hi,
m getting error of this code HTTP Status 404 – No result defined for action act.PhotoAlbumAdminAction and result error
and please give me the link of your 2nd part

dks
dks
9 years ago

plz send second part …..

Back to top button