Toy Struts Application

I wrote this little Struts / JSP application as a learning exercise. It runs on my home computer using jsp, struts, tomcat and eclipse. Written Nov 21, 2004.

Idea is that there exists a database of audio and video files. Each file has a title and has been manually transcribed. A system is needed to search those files, looking for patterns in the titles or the transcriptions.


Sample data input screen

Sample results screen,
including some debug information

index.jsp - Starting point for the toy application

   1: <%@ taglib uri="/tags/struts-logic" prefix="logic" %>
   2: <logic:redirect forward="welcome"/>
   3: 
   4: <%--
   5: 
   6: Redirect default requests to Welcome global ActionForward.
   7: By using a redirect, the user-agent will change address to match the path of our Welcome ActionForward. 
   8: 
   9: --%>
  10: 

Welcome.jsp - First screen, to collect user input

   1: <%@ taglib uri="/tags/struts-bean" prefix="bean" %>
   2: <%@ taglib uri="/tags/struts-html" prefix="html" %>
   3: <%@ taglib uri="/tags/struts-logic" prefix="logic" %>
   4: 
   5: <%@ page import="com.momentum.mav.*" %>
   6: 
   7: <html:html locale="true">
   8: 
   9: <head>
  10: <title><bean:message key="welcome.title"/></title>
  11: <html:base/>
  12: </head>
  13: <body bgcolor="#F0F0F0">
  14: 
  15: <logic:notPresent name="org.apache.struts.action.MESSAGE" scope="application">
  16:   <font color="red">
  17:     ERROR:  Application resources not loaded -- check servlet container
  18:     logs for error messages.
  19:   </font>
  20: </logic:notPresent>
  21: 
  22: <h3><bean:message key="welcome.heading"/></h3>
  23: <p><bean:message key="welcome.message"/></p>
  24: 
  25: <p><bean:message key="welcome.choices"/></p>
  26: 
  27: <html:form action="/search" method="post"> <!-- focus="expr" -->
  28:   <table border="2" cellpadding="10"><tr><td>
  29:     <html:radio property="media" value="<%= Integer.toString(Query.JustAudio) %>"/>&nbsp;
  30:       <bean:message key="welcome.searchfor.audio"/><br>
  31:     <html:radio property="media" value="<%= Integer.toString(Query.JustVideo) %>"/>&nbsp;
  32:       <bean:message key="welcome.searchfor.video"/><br>
  33:     <html:radio property="media" value="<%= Integer.toString(Query.BothAV) %>"/>&nbsp;
  34:       <bean:message key="welcome.searchfor.bothav"/>
  35:   </td><td>
  36:     <html:radio property="by" value="<%= Integer.toString(Query.ByTitle) %>"/>&nbsp;
  37:       <bean:message key="welcome.searchby.title"/><br>
  38:     <html:radio property="by" value="<%= Integer.toString(Query.ByTranscription) %>"/>&nbsp;
  39:       <bean:message key="welcome.searchby.transcription"/><br>
  40:     <html:radio property="by" value="<%= Integer.toString(Query.BothTT) %>"/>&nbsp;
  41:       <bean:message key="welcome.searchby.bothtt"/><br>
  42:   </td></tr></table>
  43:   <p><bean:message key="welcome.expr.label"/>&nbsp;<html:text property="expr" size="40"/>&nbsp;
  44:     <html:submit property="button"><bean:message key="welcome.button.label"/></html:submit>
  45: </html:form>
  46: 
  47: </body>
  48: </html:html>
  49: 

Results.jsp - Second screen, to display results

   1: <%@ taglib uri="/tags/struts-bean" prefix="bean" %>
   2: <%@ taglib uri="/tags/struts-html" prefix="html" %>
   3: <%@ taglib uri="/tags/struts-logic" prefix="logic" %>
   4: 
   5: <%@ page import="com.momentum.mav.*" %>
   6: 
   7: <html:html locale="true">
   8: 
   9: <head>
  10: <title><bean:message key="results.title"/></title>
  11: <html:base/>
  12: </head>
  13: <body bgcolor="#F0F0F0">
  14: 
  15: <logic:notPresent name="org.apache.struts.action.MESSAGE" scope="application">
  16:   <font color="red">
  17:     ERROR:  Application resources not loaded -- check servlet container
  18:     logs for error messages.
  19:   </font>
  20: </logic:notPresent>
  21: 
  22: <h3><bean:message key="results.heading"/></h3>
  23: <p><bean:message key="results.message"/></p>
  24: 
  25: <jsp:useBean id="myForm" scope="request" class="com.momentum.mav.MyForm"/>
  26: <p>Media:&nbsp;<%= myForm.getMedia() %></p>
  27: <p>Search by:&nbsp;<%= myForm.getBy() %></p>
  28: <p>Search string:&nbsp;<%= myForm.getExpr() %></p>
  29: 
  30: <table border="1" cellpadding="10">
  31: <tr bgcolor="#d0d0d0">
  32:   <td><bean:message key="results.ttl"/></td>
  33:   <td><bean:message key="results.trans"/></td>
  34:   <td><bean:message key="results.cont"/></td>
  35: </tr>
  36: 
  37: <%
  38:     Query query = new Query(myForm.getMedia(), myForm.getBy(), myForm.getExpr());
  39: 
  40:     Medium[] m = query.getResults();
  41:     if (m.length == 0)
  42:     {	
  43:         out.print("<tr><td colspan=3><i>No results found<i></td></tr>");
  44:         //out.print("<tr><td colspan=3><i><bean:message key=\"results.none\"/><i></td></tr>");
  45:     }
  46:     else
  47:     {
  48:         for (int i = 0; i < m.length; i++)
  49:         {
  50:             out.print("<tr><td>" + m[i].getTitle() + "<td>" +
  51: 		m[i].getTranscription() + "<td>");
  52:             if (m[i] instanceof AudioMedium)
  53:             {
  54:                 out.print(((AudioMedium)m[i]).getAudio());
  55:             }
  56:             else if (m[i] instanceof VideoMedium)
  57:             {
  58:                 out.print(((VideoMedium)m[i]).getVideo());
  59:             }
  60:             else
  61:             {
  62:                 out.print("Error");
  63:             }
  64:             out.println("</tr>");
  65:         }
  66:     }
  67: %>
  68: 
  69: </table>
  70: 
  71: </body>
  72: </html:html>
  73: 

struts-config.xml - Struts configuration file

   1: <?xml version="1.0" encoding="ISO-8859-1" ?>
   2: 
   3: <!DOCTYPE struts-config PUBLIC
   4:           "-//Apache Software Foundation//DTD Struts Configuration 1.2//EN"
   5:           "http://jakarta.apache.org/struts/dtds/struts-config_1_2.dtd">
   6: 
   7: <struts-config>
   8:     <data-sources/>
   9: 
  10:     <form-beans>
  11:         <form-bean name="myForm" type="com.momentum.mav.MyForm"/>
  12:     </form-beans>
  13: 
  14:     <global-exceptions/>
  15: 
  16:     <global-forwards>
  17:         <forward name="welcome" path="/Welcome.do"/>
  18:     </global-forwards>
  19: 
  20:     <action-mappings>
  21:         <action path="/Welcome" forward="/pages/Welcome.jsp"/>
  22:         <action path="/search" name="myForm"
  23:             scope="request" forward="/pages/Results.jsp"/>
  24:     </action-mappings>
  25: 
  26:     <controller/>
  27: 
  28:     <message-resources parameter="MessageResources" />
  29: </struts-config>
  30: 

MessageResources.properties - Properties for display

   1: # -- welcome --
   2: welcome.title=Momentum Audio Visual Demonstration
   3: welcome.heading=Flopsie's Audio Visual Archive
   4: welcome.message=We have a collection of fascinating audios and videos available for your edification.
   5: welcome.choices=You can search for audio clips, video clips or both. And you can search by title, transcription or both.
   6: welcome.searchfor.audio=Audio Clips
   7: welcome.searchfor.video=Video Clips
   8: welcome.searchfor.bothav=Both Audio and Video
   9: welcome.searchby.title=Just Titles
  10: welcome.searchby.transcription=Just Transcriptions
  11: welcome.searchby.bothtt=Both Titles and Transcriptions
  12: welcome.expr.label=Search for:
  13: welcome.button.label=Search
  14: 
  15: # -- results --
  16: results.title=Momentum Audio Visual Search Results
  17: results.heading=Search Results
  18: results.message=Here are the results from your search:
  19: results.ttl=Title
  20: results.trans=Transcription
  21: results.cont=Content
  22: results.none=No results found

up.bat - Update files for Tomcat

   1: @setlocal
   2: @set TOM=C:\Program Files\jakarta-tomcat-4.1.24
   3: @set MAV=%TOM%\webapps\mav
   4: 
   5: call "%TOM%\bin\shutdown.bat"
   6: @echo on
   7: jar -cf mav.jar -C bin com
   8: jar -tvf mav.jar
   9: copy /y mav.jar "%MAV%\WEB-INF\lib"
  10: copy /y pages\*.jsp "%MAV%\pages"
  11: copy /y WEB-INF\classes\MessageResources.properties "%MAV%\WEB-INF\classes"
  12: copy /y WEB-INF\struts-config.xml "%MAV%\WEB-INF"
  13: call "%TOM%\bin\startup.bat"
  14: 

MyForm.java - Form bean for communicating between screens

   1: package com.momentum.mav;
   2: 
   3: import org.apache.struts.action.*;
   4: 
   5: public class MyForm extends ActionForm
   6: {
   7:     // --------------------------------------------------- Instance Variables
   8: 
   9:     private int media = Query.BothAV;           // audio, video, bothav
  10:     private int by = Query.ByTranscription;     // title, transcription, bothtt
  11:     private String expr = "5";                  // what to search for
  12: 
  13:     //  ----------------------------------------------------------- Properties
  14: 
  15:     public int getMedia()
  16:     {
  17:         return media;
  18:     }
  19: 
  20:     public void setMedia(int i)
  21:     {
  22:         media = i;
  23:     }
  24: 
  25:     public int getBy()
  26:     {
  27:         return by;
  28:     }
  29: 
  30:     public void setBy(int i)
  31:     {
  32:         by = i;
  33:     }
  34: 
  35:     public String getExpr()
  36:     {
  37:         return expr;
  38:     }
  39: 
  40:     public void setExpr(String s)
  41:     {
  42:         expr = s;
  43:     }
  44: }
  45: 

Query.java - Business Logic 1

   1: package com.momentum.mav;
   2: 
   3: import java.util.Vector;
   4: 
   5: public class Query
   6: {
   7:     public static final int JustAudio = 1;
   8:     public static final int JustVideo = 2;
   9:     public static final int BothAV = 3;
  10:     
  11:     public static final int ByTitle = 1;
  12:     public static final int ByTranscription = 2;
  13:     public static final int BothTT = 3;
  14: 
  15:     private int media;
  16:     private int by;
  17:     private String expr; // search string
  18:     private Medium m[];
  19: 
  20:     public Query(int m, int b, String e)
  21:     {
  22:         media = m;
  23:         by = b;
  24:         expr = e;
  25:         init();
  26:     }    
  27:    
  28:     // Dummy initialize routine
  29:     private void init()
  30:     {
  31:         m = new Medium[10];
  32:         for (int i=0; i<m.length; i++)
  33:         {
  34:             if (i % 2 == 0) // Half audio, half video
  35:             {
  36:                 m[i] = new AudioMedium("title"+i, "trans"+i, "audio"+i+".mp3");
  37:             }
  38:             else
  39:             {
  40:                 m[i] = new VideoMedium("title"+i, "trans"+i, "video"+i+".mpeg");
  41:             }
  42:         }
  43:     }
  44: 
  45:     // Filter by type and name
  46:     public Medium[] getResults()
  47:     {
  48:         Vector result = new Vector();
  49:         for (int i=0; i<m.length; i++)
  50:         {
  51:             // Filter by type
  52:             if (m[i] instanceof AudioMedium && media == JustVideo)
  53:             {
  54:                 continue;   // Skip audios
  55:             }
  56:             if (m[i] instanceof VideoMedium && media == JustAudio)
  57:             {
  58:                 continue;   // Skip videos
  59:             }
  60:             
  61:             // Now compare names
  62:             if (expr == null || expr.length() == 0)
  63:             {
  64:                 // No search, accept 'em all!
  65:                 result.add(m[i]);
  66:             }
  67:             else if (by != ByTranscription)
  68:             {
  69:                 if (m[i].getTitle().indexOf(expr) >= 0)
  70:                 {
  71:                     // Found it in the title
  72:                     result.add(m[i]);
  73:                 }
  74:             }
  75:             else if (by != ByTitle)
  76:             {
  77:                 if (m[i].getTranscription().indexOf(expr) >= 0)
  78:                 {
  79:                     // Found it in the transcription
  80:                     result.add(m[i]);
  81:                 }
  82:             }
  83:         }
  84:         // Goofy way to convert a vector to an array
  85:         return (Medium[]) result.toArray(new Medium[result.size()]);
  86:     }
  87: }
  88: 

Medium.java - Business Logic 2

   1: package com.momentum.mav;
   2: 
   3: public abstract class Medium
   4: {
   5:     private String title;
   6:     private String transcription;
   7:     
   8:     public Medium(String ttl, String trx)
   9:     {
  10:         title = ttl;
  11:         transcription = trx;
  12:     }
  13: 
  14:     public String getTitle()
  15:     {
  16:         return title;
  17:     }
  18:     
  19:     public void setTitle(String s)
  20:     {
  21:         title = s;
  22:     }
  23: 
  24:     public String getTranscription()
  25:     {
  26:         return transcription;
  27:     }
  28:     
  29:     public void setTranscription(String s)
  30:     {
  31:         transcription = s;
  32:     }
  33: }
  34: 

AudioMedium.java - Business Logic 3

   1: package com.momentum.mav;
   2: 
   3: public class AudioMedium extends Medium
   4: {
   5:     public AudioMedium(String ttl, String trx, String aud)
   6:     {
   7:         super(ttl, trx);
   8:         audio = aud;
   9:     }
  10:     
  11:     private String audio;
  12:     
  13:     public String getAudio()
  14:     {
  15:         return audio;
  16:     }
  17:     
  18:     public void setAudio(String s)
  19:     {
  20:         audio = s;
  21:     }
  22: }
  23: 

VideoMedium.java - Business Logic 4

   1: package com.momentum.mav;
   2: 
   3: public class VideoMedium extends Medium
   4: {
   5:     public VideoMedium(String ttl, String trx, String vid)
   6:     {
   7:         super(ttl, trx);
   8:         video = vid;
   9:     }
  10: 
  11:     private String video;
  12:     
  13:     public String getVideo()
  14:     {
  15:         return video;
  16:     }
  17:     
  18:     public void setVideo(String s)
  19:     {
  20:         video = s;
  21:     }
  22: }
  23: 
Email: steve@oharasteve.com