Workshop on Creating a Personal MusicManager Web Application with Struts2, Hibernate and MySQL
Overview:
In this workshop tutorial we’ll develop a personal music manager application using Struts 2, Hibernate and MySQL database. The web application can be used to add your music collection to the database. We’ll display form to add the record and underneath we’ll show all the music collections. From each row the record can be deleted by clicking ‘Delete’ link. We have chosen Struts2 as this is one of the flexible J2EE framework. The database is MySQL and we have used Hibernate as ORM tool.
Tools Used:
- Eclipse Indigo Java EE IDE for Web Developers
- Struts 2
- Hibernate 3
- Hibernate Tools Eclipse Plugin Version 3.5.1
- mysql JDBC jar (mysql-connector-java-5.1.23)
- Tomcat 7
Step 1: Preparing the Database
We used phpMyAdmin to design the database and add table to it. You can use any tool to create the table in MySQL. Below is the screenshot of the table.
The database we created is music_manager and the table albumtbl will be used for storing the music data. Ignore genretbl for the time being as we’ll use this table as master table to store all music genres in the later part of the tutorial.
CREATE TABLE IF NOT EXISTS `albumtbl` ( `music_id` INT(4) NOT NULL AUTO_INCREMENT, `album_title` VARCHAR(255) NOT NULL, `album_genre` VARCHAR(255) NOT NULL, `album_artists` text NOT NULL, `no_of_tracks` INT(2) NOT NULL, PRIMARY KEY (`music_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ; INSERT INTO `albumtbl` (`music_id`, `album_title`, `album_genre`, `album_artists`, `no_of_tracks`) VALUES (1, 'Trouble-Akon', 'Hip Hop', 'Akon', 11), (3, 'Savage Island', 'Contemporary R&B', 'Savage, Ganxstardd, Soulja Boy, David Dallas, Sean P, Pitbull', 16), (4, 'Kiss (Carly Rae Jepsen album)', 'Pop', 'Carly Rae Jepsen, Justin Bieber, Owl City', 12), (5, 'Taylor Swift (album)', 'Pop', 'Taylor Swift', 15);
Step 2: Create the packages in the java source as shown in the screenshot
- ‘businessobjects’ package will contain the POJO java beans of the fields in database table.
- In ‘dao’ package will contain the Data Access Layer java classes. We have an interface dao and its implementation version. This dao will actually do the dirty work of talking and updating table.
- ‘hbm’ package contains the *.hbm file for hibernate xml to table fields mapping.
- ‘utils’ package contains all the Utility class to be used by other classes.
- ‘actions’ will have all the Struts 2 action classes.
- ‘delegates’ package has the delegate java classes which will act as a bridge between the front end layer and the hibernate dao layer.
- ‘forms’ package is optional in Struts 2 as it doesn’t have the ActionForm concept. However for simplicity and maintainability we’ll keep all the getter setters here and the class will extend from it.
Step 3: Copy the jar files in the lib folder
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
Include Struts2.xml and put the reference in web.xml for struts2 support.
web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app id="WebApp_ID" version="2.4" 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"> <display-name>PersonalMusicManagerApp</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
<?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.enable.DynamicMethodInvocation" value="false" /> <constant name="struts.devMode" value="false" /> <package name="default" extends="struts-default" namespace="/"> <default-action-ref name="index" /> <action name="index"> <result>index.jsp</result> </action> <action name="listAlbum" class="com.tctalk.apps.mmgr.web.actions.MusicManagerAction" method="getAllAlbumList" > <result name="success">/WEB-INF/web/jsps/musicmgr.jsp</result> </action> <action name="addAlbum" class ="com.tctalk.apps.mmgr.web.actions.MusicManagerAction" method="addAlbumToCollection" > <result name="input">listAlbum</result> <result name="success" type="redirectAction">listAlbum</result> </action> <action name="delAlbum" class ="com.tctalk.apps.mmgr.web.actions.MusicManagerAction" method="delAlbumFromCollection" > <result name="success" type="redirectAction">listAlbum</result> </action> </package> </struts>
Step 5: Add Hibernate support
To work with Hibernate we used the Jboss Elipse Hibernate plugin to generate hbm files for that. This plugin is optional as it will save some time manually generating “hibernate configuration” and hbm files easily. We already have a nice step by step tutorial on how you can use this plugin to auto-generate the hbm and java files. Click here to go to 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/
You can download the plugin from jboss.org depending upon the Eclipse version.
Step 5a: Create hibernate.cfg.xml – this will have all the database authentication information
<?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 name=""> <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property> <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/music_manager</property> <property name="hibernate.connection.username">root</property> <property name="hibernate.connection.password"></property> <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property> <mapping resource="com/tctalk/apps/mmgr/db/hbm/Albumtbl.hbm.xml" /> </session-factory> </hibernate-configuration>
Step 5b: AlbumBO.java – POJO correspond to the table albumtbl
package com.tctalk.apps.mmgr.db.businessobjects; // Generated by Hibernate Tools 3.4.0.CR1 /** * AlbumtblBO generated by hbm2java */ public class AlbumtblBO implements java.io.Serializable { private static final long serialVersionUID = -1445059679188116334L; private int musicId; private String albumTitle; private String albumGenre; private String albumArtists; private int noOfTracks; public AlbumtblBO() { } public AlbumtblBO(int musicId, String albumTitle, String albumGenre, String albumArtists, int noOfTracks) { this.musicId = musicId; this.albumTitle = albumTitle; this.albumGenre = albumGenre; this.albumArtists = albumArtists; this.noOfTracks = noOfTracks; } public int getMusicId() { return this.musicId; } public void setMusicId(int musicId) { this.musicId = musicId; } public String getAlbumTitle() { return this.albumTitle; } public void setAlbumTitle(String albumTitle) { this.albumTitle = albumTitle; } public String getAlbumGenre() { return this.albumGenre; } public void setAlbumGenre(String albumGenre) { this.albumGenre = albumGenre; } public String getAlbumArtists() { return this.albumArtists; } public void setAlbumArtists(String albumArtists) { this.albumArtists = albumArtists; } public int getNoOfTracks() { return this.noOfTracks; } public void setNoOfTracks(int noOfTracks) { this.noOfTracks = noOfTracks; } }
Step 5c: Albumtbl.hbm.xml – this contains the mapping between the fields of the table albumtbl table and the fields of the POJO class AlbumBO.
<?xml version="1.0"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <!-- Generated Mar 17, 2013 11:53:52 PM by Hibernate Tools 3.4.0.CR1 --> <hibernate-mapping> <class name="com.tctalk.apps.mmgr.db.businessobjects.AlbumtblBO" table="albumtbl" catalog="music_manager"> <id name="musicId" type="int"> <column name="music_id" /> <generator class="assigned" /> </id> <property name="albumTitle" type="string"> <column name="album_title" not-null="true" /> </property> <property name="albumGenre" type="string"> <column name="album_genre" not-null="true" /> </property> <property name="albumArtists" type="string"> <column name="album_artists" length="65535" not-null="true" /> </property> <property name="noOfTracks" type="int"> <column name="no_of_tracks" not-null="true" /> </property> </class> </hibernate-mapping>
Step 5d: HibernateUtils.java – this is the hibernate session handling utility class
Also MusicMgrConstant.java has the location/path of the hibernate.cfg.xml to be referenced from.
package com.tctalk.apps.mmgr.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(MusicMgrConstant._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(); } } }
package com.tctalk.apps.mmgr.utils; public interface MusicMgrConstant { String _HIBERNATE_CONFIG_LOCATION = "hibernate.cfg.xml"; }
Step 5e: MusicManagerDao.java and MusicManagerDaoImpl.java – these are the DAO classes to have methods to list, add and delete data in database.
package com.tctalk.apps.mmgr.db.dao; import java.util.List; import com.tctalk.apps.mmgr.db.businessobjects.AlbumtblBO; public interface MusicManagerDao { public List getAllMusicAlbumsFromCollection(); public boolean addAlbum(AlbumtblBO album); public boolean delAlbum(int albumId); }
package com.tctalk.apps.mmgr.db.dao; import java.util.List; import org.hibernate.Criteria; import org.hibernate.Session; import com.tctalk.apps.mmgr.db.businessobjects.AlbumtblBO; import com.tctalk.apps.mmgr.utils.HibernateUtils; public class MusicManagerDaoImpl implements MusicManagerDao { public List getAllMusicAlbumsFromCollection() { List albumList = null; Session hbmSession = null; try { hbmSession = HibernateUtils.getSession(); Criteria criteria = hbmSession.createCriteria(AlbumtblBO.class); albumList = criteria.list(); } catch (Exception ex) { ex.printStackTrace(); } finally { HibernateUtils.closeSession(hbmSession); } return albumList; } public boolean addAlbum(AlbumtblBO album) { Session hbmSession = null; boolean STATUS_FLAG = true; try { hbmSession = HibernateUtils.getSession(); hbmSession.beginTransaction(); //add the album to the hibernate session to save hbmSession.save(album); hbmSession.getTransaction().commit(); } catch (Exception ex) { ex.printStackTrace(); STATUS_FLAG = false; } finally { HibernateUtils.closeSession(hbmSession); } return STATUS_FLAG; } public boolean delAlbum(int albumId) { Session hbmSession = null; boolean STATUS_FLAG = true; try { hbmSession = HibernateUtils.getSession(); hbmSession.beginTransaction(); //first retrieve the album corresponds to that id AlbumtblBO albumObj = (AlbumtblBO)hbmSession.load(AlbumtblBO.class, albumId); hbmSession.delete(albumObj); hbmSession.getTransaction().commit(); } catch (Exception ex) { ex.printStackTrace(); STATUS_FLAG = false; } finally { HibernateUtils.closeSession(hbmSession); } return STATUS_FLAG; } }
Step 6: Create the UI layer in WebContent section
We created ‘web’ folder to keep all the UI related files there. Since this app has only one JSP we’ll create jsp folder and copy musicmngr.jsp.
In the we are posting the form data to the action addAlbum . Underneath this we are iterating through the albumList in a table to list the music album.
Musicmngr.jsp
<%@ 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 Music Manager ::</h2> <div style="margin-bottom: 25px;"> <s:form action="addAlbum" method="POST"> <s:textfield label="Album Title" name="album.albumTitle"/> <s:textfield label="Music Genre" name="album.albumGenre"/> <s:textarea label="Artist Names" name="album.albumArtists" cols="40" rows="10"/> <s:textfield label="Total No of Tracks" name="album.noOfTracks"/> <s:submit value="Add Music Album" align="center"/> </s:form> </div> <div> <table style="border: 1px dotted black;"> <tr> <th style="background-color:#ABDCFF;">Album Title</th> <th style="background-color:#ABDCFF;">Music Genre</th> <th style="background-color:#ABDCFF;">Artist Names</th> <th style="background-color:#ABDCFF;">Total No of Tracks</th> <th style="background-color:#ABDCFF;">Delete</th> </tr> <s:iterator value="albumList" var="album"> <tr> <td><s:property value="albumTitle"/></td> <td><s:property value="albumGenre"/></td> <td><s:property value="albumArtists"/></td> <td><s:property value="noOfTracks"/></td> <td><a href="delAlbum.action?musicId=<s:property value="musicId"/>">delete</a></td> </tr> </s:iterator> </table> </div> </body> </html>
Step 7: Add action class
Action class MusicManagerAction.java will handle all data handling for the jsp. This class extends MusicManagerForm which is nothing but a POJO to have all the getter/setters correspond to all form values and albumList for the jsp.
- getAllAlbumList() method retrieves the music album list from database through MusicManagerDelegate and sets in the albumList variable.
- addAlbumToCollection() method adds the music album to the database.
- delAlbumFromCollection() deletes the particular album based on the musicId from the database.
MusicManagerAction.java
package com.tctalk.apps.mmgr.web.actions; import java.util.List; import com.tctalk.apps.mmgr.db.businessobjects.AlbumtblBO; import com.tctalk.apps.mmgr.web.delegates.MusicManagerDelegate; import com.tctalk.apps.mmgr.web.forms.MusicManagerForm; public class MusicManagerAction extends MusicManagerForm { private static final long serialVersionUID = 9168149105719285096L; private MusicManagerDelegate musicMgrDelegate = new MusicManagerDelegate(); public String getAllAlbumList(){ List albumList = musicMgrDelegate.getAllMusicAlbums(); String returnString = ERROR; if(albumList != null) { setAlbumList(albumList); returnString = SUCCESS; } return returnString; } public String addAlbumToCollection(){ String returnString = ERROR; AlbumtblBO album = getAlbum(); if(musicMgrDelegate.addAlbumToCollection(album)){ returnString = SUCCESS; } return returnString; } public String delAlbumFromCollection(){ String returnString = ERROR; int albumId = getMusicId(); if(musicMgrDelegate.delAlbumFromCollection(albumId)) { returnString = SUCCESS; } return returnString; } }
MusicManagerForm.java
package com.tctalk.apps.mmgr.web.forms; import java.util.List; import com.opensymphony.xwork2.ActionSupport; import com.tctalk.apps.mmgr.db.businessobjects.AlbumtblBO; public class MusicManagerForm extends ActionSupport { private static final long serialVersionUID = 706337856877546963L; private List albumList = null; private AlbumtblBO album = null; private int musicId; public AlbumtblBO getAlbum() { return album; } public void setAlbum(AlbumtblBO album) { this.album = album; } public List getAlbumList() { return albumList; } public void setAlbumList(List albumList) { this.albumList = albumList; } public int getMusicId() { return musicId; } public void setMusicId(int musicId) { this.musicId = musicId; } }
Step 8: Add Delegate class
Delegate class acts as a bridge between the presentation layer and the database handling layer. It takes the input and pass to database layer (dao classes) to add/delete data in the database. Similarly it fetches the data from database and displays in the page.
MusicManagerDelegate.java
package com.tctalk.apps.mmgr.web.delegates; import java.util.List; import com.tctalk.apps.mmgr.db.businessobjects.AlbumtblBO; import com.tctalk.apps.mmgr.db.dao.MusicManagerDao; import com.tctalk.apps.mmgr.db.dao.MusicManagerDaoImpl; public class MusicManagerDelegate { MusicManagerDao mmgrDao = (MusicManagerDao) new MusicManagerDaoImpl(); public List getAllMusicAlbums() { return mmgrDao.getAllMusicAlbumsFromCollection(); } public boolean addAlbumToCollection(AlbumtblBO albumobj) { return mmgrDao.addAlbum(albumobj); } public boolean delAlbumFromCollection(int albumId) { return mmgrDao.delAlbum(albumId); } }
Step 9: Final Integration
Once all are integrated the final package structure will look like this below-
Build the project and right click on it and select Export as war file and save in a known folder. Open the Tomcat manager console app and browse the WAR file to install it.
Once installed, run the app as (http://localhost:8080/PersonalMusicManagerApp – the URL may vary based on your Tomcat installation folder/port etc.)
If everything is running successfully the screen will be shown –
Musicians and artists rely on emanate website’s audio distribution services to make their music available to listeners. This is the only way to stay relevant thanks to cool advertising opportunities and fierce competition. Live broadcasts have a bright future, and they will continue to be the number one source for online radio listeners, who are more likely to spend money on subscriptions than on downloads or broadcasts.
Hello there! It would probably be great to create such an app, but really, as much as I love music, I’m not a professional musician. I’m just a teacher who teaches music lessons. Often for lessons I need to show my students videos that I can usually download from Tubidy. By the way I really like this service because everything can be done for free and fast. And the variety for the lesson is just great.