Can you describe your MVC design (if any), as I feel this is where I lost a few points?
I was really concerned that my client GUI design was going to be too complicated, but apparently the grader didn't think so. I subclassed JTable, AbstractTableModel, DefaultTableColumnModel and TableColumn; I also created a wrapper class for DataInfo (the data model was an array of these wrapper objects) and wrapper classes for all of the non-String fields such as Price, Duration, Day, etc. The reason for all these extra classes was so that I could implement table sorting and be able to properly render each field (e.g. right justify the Price field). Each field wrapper contained a public static inner class named CellRenderer which extended DefaultTableCellRenderer. Of course to implement sorting, each had to implement the Comparable interface. That basically covers model and view. Now for control I used a java.beans package approach by creating pseudo-properties such as "searchDatabase", "bookFlight", "bookingComplete", etc. along with a variation of the Mediator pattern. I had a PropertyDispatcher that ran in a background thread that all pertinent objects had a reference to. The PropertyDispatcher stayed in a wait state most of the time, but when one of the dispatch methods was called it started a javax.swing.Timer, emptied the dispatch queue on the Timer's actionPerformed, and went back into a wait state. The reason for the Timer was so that property changes would be dispatched on the swing event thread since swing components are not thread-safe. The dispatch queue was kept in an ArrayList, so that properties could be dispatched in the order they arrived. All objects that had a reference to the PropertyDispatcher subscribed (registered) to all the property changes they were interested in. So for example, if the user pressed the Search button, the SearchPanel object would call dispathcer.dispatch("searchDatabase", (Object) searchData); the object that stood between the two subsystems (GUI and database) which was subscribed to "searchDatabase" then created a SearchCriteria object from the searchData that was dispatched, called dataFacade.setCriteria(searchCriteria), dataFacade.searchDatabase(), then dispathced either dispatcher.dispatch("dataChanged", (Object)dataFacade.getDataInfo()) or dispathcer.dispatch("emptySearch"). In the case of "dataChanged", the TableModel was subscribed to this which then grabbed the DataInfo from the dispatched property, created an array of FBNDataInfo from it and called fireTableDataChanged(). Booking was a little more complicated since each booking operation ran in a separate thread in case a flight was locked for a long time, but the same general principles apply. The BookingPanel (which contained labels indicating the currently selected flight) was kept in synch by a "rowChanged" property which was dispatched by an inner class of FBNTable. BJ:
Can you outline your approach torwards exception handling?
I created one Exception class called InvalidDataFileException which extended IOException. To complement this exception, I created a DBFileCheck class which had a single public static method: checkDBFile(String dbname) which did a partial integrity check on the file. The reason for doing this is that if the file is corrupted (or is not really the right file type) then there is a good chance that the Data class will generate an OutOfMemory Error when it creates the schema (FieldInfo). If either the Data constructor or the aforementioned method encountered a problem, then an InvalidDataFileException was thrown. My server GUI would then log the exception in its status log (text area) and pop up a dialog informing the user of the problem and suggesting the he select a valid db file from the File->Open menu. All other exceptions were handled essentially the same way: Either server or client GUI would pop up a dialog informing the user of the problem and when possible suggesting a remedy. Exceptions that occurred during boot (either client or server, before the GUI was shown) was simply written to stdout (I really screwed up on that, it should have been written to stderr instead) and a System.exit(exitCode) was called. The server had six different exitCodes and the client had 26.
I hope this is helpful, Michael Morris
Any intelligent fool can make things bigger, more complex, and more violent. It takes a touch of genius - and a lot of courage - to move in the opposite direction. - Ernst F. Schumacher
Now for control I used a java.beans package approach by creating pseudo-properties such as "searchDatabase", "bookFlight", "bookingComplete", etc. along with a variation of the Mediator pattern.
So essentially you didn't have a controller at all, is that right? Eugene.
Joined: Jan 30, 2002
I suppose that that's one way of looking at it, but another way would be that the controller was a composition of the objects that participated in the property changes with the PropertyDispatcher at the hub. Anyway, this was a novel approach for me and I would highly reccomend it for component mediation (synchronization) to any developer. It is amazing how simple it is to add GUI functionality with property changes. Michael Morris