Project 1

CPE 437

Points 1-9, due 7/14/09

Points 10-12, due 7/21/09

 

Overview

In Lab 3 you fixed up MusicStore.  Now you get enhance the app in several ways. 

 

0. Rename Lab3 to Project1

Keep your Lab3 code as a separate codebase, and rename a copy of it to Project1.

 

1. Change to a new database

We’ll be adjusting the database content in various ways, so we’ll need a new database – “Project1”.  This will leave the old “music” database unchanged, so the old musicStore app still works. 

 

Check that:

□ Converting to the new project name and database required changes only to web.xml and context.xml.

 

2. Generalize the product display page

Add a “Details” field to the product table, to hold the paragraph-descriptions that Murach instead embeds in the index.jsp for each product’s subdirectory under Catalog (pretty cheesy design).  Drop those subdirectories, and create instead a single show_product.jsp under Catalog.  Display all products using just this one JSP page.  And remember, do not add any hardwired reference to “Project1”, even for the links to the images (which may remain under the images directory).   Lose the sound clips feature when you do all this – it’s possible to upload and store images and clips in a database, but that’s too specialized a subject for this exercise.  I found it useful to retain the product_table include, btw.

 

Check that:

□ product display page produces results just like the MusicStore original, minus the option to listen to clips, but all from one show_product.jsp, with no special-cased code per-product, aside from the images directory.

□ nothing in your show_product code or its includes is hardwired to “Project1”

□ you used no raw JSP escapes in show_product or its includes (no <%, <%=, etc.) – only EL.

 

3. Make catalog/index.jsp work from the database

The main catalog page is hardwired – more Murach cheesiness, though this time he was probably just trying to keep it simple for instructional reasons.  (His claim that you’d design a main catalog page with fixed content to “give more control to the designer” is nonsense.)  Redesign it to draw from the database “product” table, and display all products from that table.

 

You’ll need to figure out how to get a session entry to support the modified index.jsp page.  This is *not* the same as the products entry from another page (you should know which).  Instead, the entry must be a List<List<Product>>, with each sublist giving all products with a given artists name.  Such a structure will allow you to group entries by artist, with headers for each group, as catalog/index.jsp currently does. 

 

Use Java generics fully, with no warnings for unsafe assignments or the like.

 

Use JSTL tags.  Your new index.jsp must have at most 5-6 lines of pure HTML, with the rest being JSTL or jsp tags, or JSP escapes (and around 10 non-comment lines of these).

 

Check that:

□ main catalog index properly shows contents of DB product table, and reflects changes made to that table, at least after a new session start.

□ listings are grouped by artist, in alphabetical order, even if DB product table rows are not in that order.

□ you complied with the above limits on the number of pure-HMTL lines, and total line limit.

□ you used a single session attribute of type List<List<Product>>, with no generics-related warnings.

  

4. Rewrite catalog/index.jsp without any use of JSP tags, or EL

And now that you wrote it with tags, write it again using absolutely nothing but JSP escapes.  Just once, you should see how this was done the old way, to understand it, and because you may work on legacy code that does this.  Keep your code from part 4 as a comment in the file, so you can return to civilization later. :)

 

Check that:

□ your rewrite uses only raw JSP escapes, and no EL, JSTL, or jsp tags.

□ you changed only the catalog/index.jsp file, with no changes to any supporting servlet.

 

5. Make Download immutable

Database objects like Download, which is created but not modified, are best designed with a constructor that initializes all values, and no set-methods at all.  This makes them “immutable objects”.   Revise Download to be such an object, and fix the uses of it accordingly.  You should end up with more elegant code.

 

Check that:

□ downloads are still properly recorded (once you restore them a little later on)

□ there are no get methods in Download.

 

6. Fix the dual-field description in product

Deriving two separate properties from a single one, based on String parsing, is poor design.  Fix Product, and its database table, so that artist name and album name are separate fields, and description is derived.

 

Check that:

□ all display function still works correctly

□ all affected ProductDB methods were updated with the new design.

 

7. Add admin pages to set up a product

Add an admin page that lets you set up the properties of a new product.  Use my posted solution as an example for the behavior (but leave track handling till point 9 below).  To support this admin page, add exactly one object to the session, in keeping with the form-object design pattern we’ll discuss in class.  Do this even when you add tracks in point 9.

 

Check that:

□ your new product page and confirmation page look exactly like mine, without the track information

□ you generate the same error messages as mine for missing fields, duplicated product code, and poorly formatted price

□ created new products show up in the catalog/index.jsp, at least after a session restart

□ products not successfully created due to errors do not end up in the database.

 

 

8. Add tracks

Add  a “Track” table, linked 1-many, from the Product table.  Tracks have a name, an optional filename (mp3 suffix assumed), and a sequence number; the latter is assigned automatically by the site, based on the order of tracks in the newProduct page.  Maintain the Track list as a List<Track> property of music.business.Product, with Track a nested class of Product.  Automatically fetch/write the tracks for a Product whenever you fetch/write the Product in the relevant ProductDB methods.  For queries, do this via a join, not via two separate SQL queries.

 

Check that:

□ all ProductDB methods are updated, using joins in the query methods.

□ ProductDB.insert properly links Tracks back to their Product via a foreign key field.

□ tracks with no sound clip have a null value, not “”, for the sound file.

 

9. Generalize WriteDownloadServlet

Generate the tracks list via a general jsp page show_tracks.jsp, which is fed by WriteDownloadServlet, as at present.  show_tracks.jsp takes care of the product and track display, with no specialized index file per title.  The per-title subdirectories of Catalog are now gone,. though you may keep the sounds directory,with per-title subdirectories with mp3 files, since we’re not doing database-storage of binary data in this exercise.  Be sure to use only jsp, EL, or jstl tags in show_tracks.jsp; no use of “<%” or “<%=”.

 

Check that:

□ no track-specific code remains – everything is driven from the database except for the sounds directory.

□ your display is just like mine, including handling tracks with no sound file.

 

10. Augment the new product page to allow set up of tracks

My example page for this is the “spec”, but some details:

 

a. The number of empty track slots shown is always 8 more than the maximum-numbered track successfully filled in so far.  If you run out, you can click the Add More Tracks button, and more empty slots appear without the product being saved yet. 

 

b. Make the “8” a constant in your .java servlet; do not hardwire it anywhere in the jsp.  Note in particular that this means you cannot simply hardwire 8 <input> tags in your new_product.jsp.

 

c. Note that track sequence numbers need not appear in sequence – this allows some editing flexibility.  But, they must be contiguous from 1 to N, the number of tracks, with no gaps or duplicates, or errors result.

 

d. Track name is required, but audio file is optional.  An empty or null audio file field must go into the database as NULL, not empty string.

 

Some lessons you may draw from this little step, which will motivate our Hibernate and JSF discussion:  JDBC is tedious and repetitive, and

handling null vs ‘’” vs “ “ values in strings from an HTML form is a PIA.

 

Check that:

□ you can change the number of additional blank track rows by changing just one constant in your servlet

□ track error handling works just like mine, for all cases including missing track name, duplicate sequence ids, missing sequence ids, ill-formatted or out-of-range sequence numbers.

□ database is properly updated, and tracks with no sound clip have a null value, not “”, for the sound file.

□ Newly added tracks show in show_tracks.jsp, perhaps after a session restart.

□ track sequence numbers may be in any order as long as they run contiguously from 1 to N, and they’re stored properly in the database, with the right sequence numbers.

 

11. Add an I18n filter

Place all strings for the new product page (but not the header/footer includes) you created from point 6 into a resource bundle, and have a Spanish and English version of said bundle, populated via property files.  I generated my Spanish translation from babelfish.yahoo.com, which I’m sure has produced some amusing results :) (I have no idea if the term “pista” is used in Spanish, for instance, to describe the “tracks” of a CD.)  You may do the same, however.  Be sure the right accents are included.  Here are some specifics:

 

a. Be sure you’ve done the assigned reading on internationalization from Horstmann.  Unless you already know all this stuff, there is *no* substitute for doing that reading.

 

b. Use the class overview, plus online documentation you must research (there is plenty of it) to understand how the JSTL fmt tab library works.

 

c. Create the necessary properties files for English, Spanish, and default.

 

d. Use fmt to replace the fixed strings for field titles button titles, and headers in the new product page with internationalized versions.  Internationalize also the format of the price field.   Turn off “grouping” when formatting this field and when parsing it – this simplifies the testing.

 

e. Modify the NewProduct servlet that supports the new product page, to use internationalized strings for its error messages.  You’ll need to use a ResourceBundle and a MessageFormat for this, to fill in the missing pieces.  Also, do *not* hardwire each “field is required” error message.  Generalize these with only one string for the error of a missing field, thus:

 

admin.newproduct.fieldRequired={0} is a required field.

 

Be sure you parse the price field correctly (in particular Double.parseDouble ain’t gonna work).  Test the Spanish version with es_ES, not es_MX or other new world Spanish cultures.  (Spain, like most of Europe, uses “,” for a “decimal point”.)

 

f. Once the rest is working, add a Filter to ensure the session is populated with a ResourceBundle “res”, which resource bundle you use in the New Product servlet, rather than creating a Resource object each time.  The Filter updates the session only if “res” does not exist, or if it does but the preferred language (save that in the session also) has changed since the last hit.

 

Check that:

□ you get English appearance when your browser is set for first-preference of English or for Chinese.  You get Spanish when it’s set for Spanish.

□ all error messages are just like mine, including the ones for required fields

□ you do not have per-field specialized error messages for required fields.

□ parsing and display of the price switches to European decimal notation when your browser has es_ES preference, and there is no grouping of nonfractional digits

□ you use the fmt taglib throughout new_product.jsp to do internationalizing

□ your NewProduct servlet does not include the words “getBundle” nor the pathname of the resource bundle, but instead obtains the resource bundle directly from the session, based on the attribute your filter set.

 

12. Add a session listener to log session starts

Add a session listener that logs, to a file “sessionStarts” in Tomcat’s log directory, a line for each session as it starts, indicating date and time of session start.

 

Check that:

□ session starts are correctly logged (working from localhost, they should appear in the localhost log)

 

Final Checks

 

Check that:

□ localhost, catalina, and stdout logs are devoid of any stack traces (aside from historical ones you’ve since fixed).

 

 

Affirm, by your signature below, that you carefully followed through on testing of each of the points checked above. 

 

_____________________________________________________              _______

Name                                                                                                  Date