NX: Notes on a design that passed 389/400

As I recently posted in the Certification Results area, I just passed with 389 of 400 and wanted to share some of my thoughts on the design. All of my deducts were under "General Considerations". My assignment was the B & S Contractors. I decided to implement a 3-tier design with a very simple application lifecycle and to use RMI for the network functionality. I used the Java 1.4 Logging API extensively, particularly in the critical locking code. I think this may have helped me get a quick turnaround on the grading (only 2 days !!!) as it made it easy for the tester. Application ======== When launched, the app displays a dialog to get the location using either hard-coded defaults or params from the properties file if it was previously created. My interpretation of location is: Standalone - db file pathname Network Server - db file pathname and port no. Network Client - hostname and port no. If something goes wrong at launch or any other time, the app simply warns the user, logs the error to a file, and if it's serious, exits. NO exceptions or stacktraces are allowed to percolate up to the end user, only informative error messages. If the user wants to use a different file or connect to a different server, he/she simply exits and restarts. GUI === This approach to the application makes the GUI very simple for the user and also results in very simple user documentation. I used NO menus or toolbars, merely providing comboxes and buttons to perform the relevant operations and exit the app. I did put a lot of effort into the appearance of the JTable, including having it automatically resize the column widths and making sure that they display nicely at any screen resolution. I also provided checkboxes to allow the user to select whether the search is "exact" or "case-sensitive". I primarily used BorderLayout with a smattering of FlowLayout and a few very simple GridBagLayouts. Persistence ========= The Data class implements the DBMain interface specified by Sun. It uses RandomAccessFile directly to get to the file data and provides an in-memory cache (List) of contractor record data. All of the synchronized code is in Data which is implemented as a singleton. It also has a Map of locked contractor records. I worked around the exception handling deficiency of the DBMain API by having the Data class wrap any IOExceptions in an unchecked DataAccessException. The DataAccessExceptions are then unwrapped within the Data class itself before being passed on to the data access client (see ServicesImpl below). This feels more natural to me than disguising them as RecordNotfoundExceptions. I implemented DuplicateRecordException but it is not thrown by any code because the spec is not clear. General ====== I used a Contractor class to put an O-O framework around the String arrays that represent the record data. I used a Services interface as my primary client/server access API. The UI clients only use the Services interface which has only 2 methods, book and search, both of which can throw IOException or RecordNotFoundException. The UI client is ultimately responsible for handling these exceptions. The most important implementation of Services is the ServicesImpl class which is a singleton. The ServicesImpl singleton is the only object that interacts with the Data singleton and hence the only direct user of the locking/unlocking API. The Standalone application functionality gets its Services instance directly from ServicesImpl's static getServices method. Locking ====== The implementation of the Services book method in ServicesImpl is the only user of the locking API. I specified a contract in the Javadoc that calls for any potential users of the locking API to invoke lock/process/unlock as a sequence within the context of a single method call which guarantees it will happen within a single thread of execution. When lock is invoked, a check is made to see if the Contractor already has been locked by another thread. If it has, the current thread will wait until notified that it has been unlocked. If not, a Lock object is created that has a reference to the current thread and it is put in the locking Map with the Contractor as the key. The protected processing operation is performed and then the Lock is removed from the Map and destoyed by the unlock method call. It is vital that any exception that occurs during processing is caught and rethrown after the Contractor has been unlocked. Deadlock is prevented by specifying a locking order to be used by programmers. Networking ======== Choosing RMI seemed to be a total no-brainer as it is so simple compared to using sockets. My entire networking code compiles to only 5,408 bytes of code. It consists of 2 classes, RemoteServices and RemoteServicesImpl. RemoteServices is an interface that extends Services and Remote. It has no body. This is possible because all the Services methods throw IOException and can therefore also throw a RemoteException. It's a nice trick that keeps things simple. RemoteServicesImpl extends UnicastRemoteObject and implements RemoteServices. It has 2 parts, the implementation of RemoteServices (i.e. the 2 Services methods) and static getServices methods that allow the clients to get a Services instance that is either an RMI server for the Network Server application functionality or its stub for the Network Client application functionality. The Services method implementations simply delegate all work to the ServicesImpl singleton. Since all of the locking occurs in a single method call in the Network Server's JVM, there is no need to worry about the RMI connection dieing in the middle of a locking operation. Miscellaneous ========== 1. My Network Server doesn't provide a JTable display for its user but it would be trivial to add that capability in a safe way. 2. I didn't fully subscribe to Sun's Java coding conventions and said so in my choices.txt. I told them I thought it was a practical choice to use the conventions provided as default by my IDE (Eclipse). Perhaps I got a deduct for this.

3. The 3-tier design makes it easy to add a different type client such as a Web Application. It just needs to get the ServicesImpl singleton and provide the same functionality as the GUI rich client. 4. Since no authentication (or authorization) is specified or required, I decided that it is OK for users to change or erase a booking at will.

I hope that some of you find this info helpful. Again, thanks to all of you and Max for his excellent book which really helped me come to grips with how to successfully implement the Locking.

Originally posted by Ken Krebs: As I recently posted in the Certification Results area, I just passed with 389 of 400 and wanted to share some of my thoughts on the design. All of my deducts were under "General Considerations". My assignment was the B & S Contractors....

Hi Ken-- Great score! Congratulations. May I ask the following questions: - How did you go about testing your design (ie, locking mechanism) to gain enough confidence that it was working right? - Where exactly did you place your logging calls? Did you send all your logs to one file, or did you split by function/package/class? I hadn't used the logging API because I thought it wouldn't help that much, but i'd very much like to hear more of your thoughts about its usefulness. - How verbose was your design document? User document? Thanks in advance, Paul

Hello Ken, Congratulations for such a high score! And thank you for your review of your design. I would like to clarify on your 3-tired design. Is this how you described it:

Client Tier --> Client UI Business Tier --> Network Server Data Tier --> db.db file only Could you please describe it with a little more detail? Thank you so much! Seid

Seid Myadiyev<br />SCJP, SCWCD, SCBCD, SCEA-Part 1

Seid Myadiyev
Ranch Hand

Joined: Jul 02, 2002
Posts: 196

posted Nov 12, 2003 04:17:00

0

Also did you opt to refresh the contents of your criteria ComboBox(es) after each trip to the Server? How did go about populating the combos? Thanks again! Seid

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 12, 2003 06:56:00

0

A couple more random thoughts on my project: 1. I used Ant to automate building, packaging, and testing. This is a great tool that is simply a must to learn for Java developers these days. Automation of the process helps build confidence when refactoring. 2. I used JUnit for most of my testing. This is another indispensable tool. I did however write a non-JUnit test that fired up a bunch of threads to exersize the server. All the threads were trying to book a specific Contractor. I manually checked the results of the server's log file to make sure that the threads were being forced to queue up and to make sure that they each got their turn. I'm sorry to say I did not use "Test-driven Development" to implement the project. My mind has not yet fully wrapped around how to do that. 3. My work on this project was greatly influenced by some work I did on the Spring Framework open source project. Spring is a lightweight set of application frameworks that is primarily targeted to J2EE but is very useful for any sort of Java application. In addition to a few other minor contributions, I developed the original version of the Petclinic sample web application. Working with the superb developers of this project prepared me well for the SCJD exam. The things I learned from this resulted in my choice, without reservtations, of a 3-tier design. WARNING: shameless plug coming --> I highly recommend you to check out Spring. 4. One of the reasons given by the 2-tier darksiders for their choice was the exact wording of some of the language surrounding the server providing the database fucntionality and their interpretaion that the client must use the locking API. In the "Should lock methods be callable by the client" thread, Peter Ye posted

Hi, My understanding of "provide" is just the same "implement". It doesn't necessary mean to "provide to who", it can be "provide to itself". I wonder if Sun provide any spec in some other languages? ex. Chinese. I remember there are language choice when doing the SCJP.

. This rang a bell with me that made me realize that the 3-tier approach was OK. Since Sun realizes that people of many different cultures and native languages will be taking the exam, it would be counter-productive to nail people on the subtle nuances of the English language. I therefore reasoned that you really need to be careful when they say "MUST" but have some freedom to interpret when they don't. kktec SCJP, SCWCD, SCJD

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 12, 2003 07:29:00

0

Paul, Regarding testing: See my last post. Regarding Logging (for testing purposes): In ServicesImpl, I log in the book method: at the beginning, "Book invoked" and at the end, "Book performed" along with some data details. In between these logging events, I call on Data to lock, update, and then unlock. I log in each of these methods, identifying the thread. I also log if the thread is forced to wait. I used a single logger instance for the entire application and log to a single file. Each client or server gets it's own file even if run on the same PC. BTW, although I could not use this for this project, apache.org provides a Commons Logging API that can be used as a wrapper around Java logging, it's own logging, or Log4J. The Spring Framework uses this wrapper for its own logging. Log4J appears to be the most capable but with a little steeper learning curve. IMHO, logging is a vital component in any non-trivial application.

Regarding documentation: Because my application lifecycle and UI is so simple, so was my userguide.txt file, weighing in at only 5477 bytes. It describes: 1. how to run the program in the 3 different modes 2. how to search 3. how to book a contractor 4. a description of the Contractor detail information 5. what happens if there are errors My choices.txt was somewhat larger at 10584 bytes. It had bullet points on the following subjects: General Issues (4) general Data Access Issues (3) Locking API Issues (3) Database File Format Specification Issues (9) User Interface issues (4) Sockets vs. RMI choice Other Networking Issues (2)

kktec SCJP, SCWCD, SCJD

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 12, 2003 07:33:00

0

One other note: I had my wife, who is not a programmer, run the network client program using my userguide.txt. This helped me to clarify the docs and make the UI a bit friendlier. kktec SCJP, SCWCD, SCJD

Hi Ken, Congrats!!! Thats an awesome score. I have a couple questions. Did you end up implementing any type of crash recorvery for your database since you read it into memory? I've been tossing this idea around for a few days and don't know whether its necessary or if i'm just being anal Also how did you go about locking the database when you had to iterate through its contents, ie for a search, or to check if a record already exists with a certain primary key. I believe it is necessary to lock on the collection that contains your records when you iterate through that collection, does your design do this? Right on with using ant and eclipse, i agree they are very useful tools and help out development a great deal. I'll have to check out that spring framework when i get a chance. Congrats again, Dave

Seid, Regarding the 3-tier design (design patterns in quotes) : My Contractor class provides an object-oriented "Active Record" for the String array data along with some business logic. Since it's used by the Data class, the boundary with the persistence tier is slightly fuzzy. I could have made this boundary less fuzzy by providing a separate class, "Value Object", for the String array data but it seemed to be not worth the effort here. In the real world, I would probably do something like this if I needed to reimplement the persistence functionality to for example, use a relational database but then I would probably throw away the yucky DBMain interface and make a new persistence API. My Services business API interface is a "Service Layer" which defines the boundary between the client tier and the server functionality. My Data class provides an "Identity Map" (cache) of Contractors and helper methods for the Contractor class to read and write the data. The locking API and the contracts I specified consitiute an example of the "Unit of Work" pattern. The getServices methods in ServicesImpl and RemoteServicesImpl are examples of the "Service Locator" pattern. I'm not quite sure if this what you were looking for but I hope it helps. Regarding the comboboxes: I took the "lazy" approach to populating the comboboxes. They are initially populated only with an "---ANY---" entry. As new names and locations are found during searches, they are added to the entries. Since the database is fairly small and not very likely to grow in a huge way this is a practical choice here. In the real world, I would not use this approach if I knew the database were going to potentially be large. In that case, I would probably try to populate the comboboxes boxes "eagerly" because it might not be practical to pull the whole set of Contractors over the network. Footnotes: The design patterns referenced here can be found in either "Patterns of Enterprise Architecture" by Martin Fowler or "Core J2EE Patterns" by Alur, Crupi, and Malks. Both books are highly recommended by me. For a more practical counterpoint to the design orientied books, I very highly recommend "Expert One-to-One: J2EE Design and Development" by Rod Johnson. This book provides a free J2EE framework that was the basis for what is now the Spring Application Framework. Making good practical design/implementation choices is also part of the exam and this book helped me a lot.

kktec SCJP, SCWCD, SCJD

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 12, 2003 09:00:00

0

Dave, I did not implement any crash recovery here but I certainly would in the real world. In my implementation, the file is only opened when accessed, i.e. during the initial read and subsequent writes. It is immediately closed afterward. In the real world, I would first make a copy of the file, update it, and only commit the changes if there were no errors. I would probably also try to protect the file from other processes though this is hard to do in a platform independent way. Or I would use a relational database instead . An important part of my locking design is that I specify a synchronization order contract that anybody working on the program must follow. They must first synchronize on the locking Map, then the contractor List, and then on the Contractor. This contract, if followed, prevents deadlock from occuring. I used the sychronization wrappers provided by the Collections class to implement my collections. kktec SCJP, SCWCD, SCJD

Seid Myadiyev
Ranch Hand

Joined: Jul 02, 2002
Posts: 196

posted Nov 12, 2003 09:43:00

0

Hello Ken, Thank you very much for your detailed descriptions -- they are very helpful! I would like to say that I very much admire your design and approach! Thank you again! (I also sent you a private message) Seid [ November 12, 2003: Message edited by: Seid Myadiyev ]

Ken, First off incredible score - truly. 1. How did you handle the methods that sun wanted us to implement but not use on the GUI (delete, add, update,) I implemented this methods and went as far as placing them on the GUI for full blown testing. This required me to place their calls inside my GUI controller and DBClient interface. Yes I did JUnit testing on the Data side but to test from a user perspective I became anal and placed them on the GUI. I plan to take them out of the GUI but I am not sure if I sould get rid of their calls in my controller and DBClient interface. 2. Did you implement something like the MVC pattern. If so where did you catch the exceptions - in the controller. 3. Did you use any form of chaining. Other than what you mention below.

I worked around the exception handling deficiency of the DBMain API by having the Data class wrap any IOExceptions in an unchecked DataAccessException. The DataAccessExceptions are then unwrapped within the Data class itself.

Could you elaborate a little more on what you mean by this. "Wrapped IOExceptions in an unchecked DataAccessException ..then unwrapped within the data class itself." ??? confused! OK, just one more (for now ) 4. Throughout you assignment did you directly refer to the column names of the contractor (i.e. contractor.name, contractor.location..) or better yet contractor.getName(), contractor.getLocation()..) Or did you use some type of data schema and refer to them as columns 1, 2, 3, 4, 5, and 6. thanks, bill

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 14, 2003 07:42:00

0

Bill,

1. How did you handle the methods that sun wanted us to implement but not use on the GUI (delete, add, update,) I implemented this methods and went as far as placing them on the GUI for full blown testing. This required me to place their calls inside my GUI controller and DBClient interface. Yes I did JUnit testing on the Data side but to test from a user perspective I became anal and placed them on the GUI. I plan to take them out of the GUI but I am not sure if I sould get rid of their calls in my controller and DBClient interface.

I briefly considered, definitely an anal thing , but decided not to use these methods on the GUI, i.e. add them to my Services business API. There simply was no need to because I had confidence that they worked correctly because of my JUnit tests. If you also put them in the GUI, what is it that you actually gain from this extra, time consuming step ? The extra work of removing it without breaking anything would probably have added to rather than reduced my anal pucker factor.

2. Did you implement something like the MVC pattern. If so where did you catch the exceptions - in the controller.

I kept it very simple and just used the Search and Book button ActionListeners I implemented as controllers. These mini-controllers invoked the methods on the Services business API and dealt with any exceptions that resulted in an appropriate, user friendly way.

3. Did you use any form of chaining. Other than what you mention below. quote: I worked around the exception handling deficiency of the DBMain API by having the Data class wrap any IOExceptions in an unchecked DataAccessException. The DataAccessExceptions are then unwrapped within the Data class itself. Could you elaborate a little more on what you mean by this. "Wrapped IOExceptions in an unchecked DataAccessException ..then unwrapped within the data class itself." ??? confused!

I understand your confusion as my original statement was inaccurate ;(. I actually unwrapped them in the ServicesImpl class. The misstatement came about because I had originally implemented ServicesImpl as an inner class of Data to give it access to Data's private parts. As my design improved, this access became unnecessary so I refactored ServicesImpl to be outside of Data as this is much simpler for a junior programmer to understand. This was the only exception chaining I did.

4. Throughout you assignment did you directly refer to the column names of the contractor (i.e. contractor.name, contractor.location..) or better yet contractor.getName(), contractor.getLocation()..) Or did you use some type of data schema and refer to them as columns 1, 2, 3, 4, 5, and 6.

I stuck to the KISS principle, "Keep It Simple Stupid" or as they say in XP, "Do the simplest thing that could possibly work". I simply inplemented a String[] of the column names in my ContractorTableModel constructor and return the appropriate one in its getColumnname method. I didn't see any need to get fancy and implement something more generic. kktec SCJP, SCWCD, SCJD

Bill Robertson
Ranch Hand

Joined: Mar 21, 2003
Posts: 234

posted Nov 14, 2003 07:58:00

0

thanks Ken, much appreciated!!!

Bill Robertson
Ranch Hand

Joined: Mar 21, 2003
Posts: 234

posted Nov 14, 2003 20:51:00

0

Ken, Another question. How did you handle you log files. Did do copy over them after each run and create fresh ones? Or did you implement sometype of rotation method. I am having trouble coming up with a rotation method. Thanks, Bill

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 14, 2003 21:10:00

0

Bill, Take a look at the Javadoc for java.util.logging.FileHandler. In the logging.properties file, you define a handler of this type and set its count property and limit property to say how many rolling files you want and the size limit for each file. You can also designate how the files are named using the pattern property. In my implementation, I also defined a formatter property that designated my own simple subclass of java.util.logging.Formatter to make the log entries look the way I wanted them to. kktec SCJP, SCWCD, SCJD

Bill Robertson
Ranch Hand

Joined: Mar 21, 2003
Posts: 234

posted Nov 14, 2003 21:25:00

0

Thanks for the advice. I saw that. I am trying to figure out how to rotate not based on file size but rather file existence. For example, if you have log1, then you create log2, then log3, then back to log1, then log2....etc. All based on the amount of times the user logs on.

Bill Robertson
Ranch Hand

Joined: Mar 21, 2003
Posts: 234

posted Nov 15, 2003 18:48:00

0

Here is a really nitty gritty question but I was wondering if you provided documentation for everything. Meaning even private variables.

I worked around the exception handling deficiency of the DBMain API by having the Data class wrap any IOExceptions in an unchecked DataAccessException.

A very good idea. With your permission, I will use a similar approach. Yet now I wrap an IOException into a RecordNotFoundException, but I feel that is not appropiate.

4. Since no authentication (or authorization) is specified or required, I decided that it is OK for users to change or erase a booking at will.

I do not really understand. Do you allow or do you not allow to change or erase bookings? What did you to prevent the following case. A client sees a contractor as free and wants to book it. But another client has booked it in the meantime. Which client gets the contractor? [In my solution, it is not allowed to modify performed bookings and therefor an AlreadyBookedException will be thrown and the table will be refreshed.] Greetings Werner [ November 16, 2003: Message edited by: Werner Joerling ]

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 16, 2003 11:36:00

0

Bill, I Javadoc'ed almost everything right down to private instance variables. I generally think it's best practice. The Javadoc I supplied in the upload only showed the public & protected items. kktec SCJP, SCWCD, SCJD

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 16, 2003 11:53:00

0

Werner, Thanks. In my submission, I allow bookings to be changed or erased at will. It must be reasonable to at some time be able to change or erase a booking. The circumstances under which this may occur are a Business Rule. This rule has not been specified in the requirements. I therefore decided to allow it as there is no reason not to and it is the simplest thing to do that meets the requirements. I made sure to make this decision known in the "choices" doc. Since the booking acts are serialized by the locking mechanism, the one that gets there last gets the booking. kktec' SCJP, SCWCD, SCJD

Bill Robertson
Ranch Hand

Joined: Mar 21, 2003
Posts: 234

posted Nov 17, 2003 17:34:00

0

Ken, Could you explain a little more on how you handle your columns when reading them from the database and using them throughout your program. I refer to them directly by name and really leave no place for column re-ordering or new columns. To get an idea of what I am talking about, one of my methods looks like this:

Let me try to explain some more. Lets take for example this piece of code

NOTE: cntr = Contractor = the type class that contains the following variables and getter and setters for each variable:

Notice I am not using any form of Metadata look up or some dynamic way to determine my columns. I refer to them directly (i.e. getSize(), getRate()). Instead of cntr.getColumn(1), getColumn(2),.... Some would say this does not allow for easy code changes if by chance they added a new column or changed the order of the columns in the file. I do not agree and I think its overboard for this assignment. I was wondering what you did and thought. Am I making any sense?

Dave Knipp
Ranch Hand

Joined: Oct 14, 2003
Posts: 146

posted Nov 18, 2003 11:38:00

0

Ken, One quick questions, I was reading through the instructions doc and came across this sentence and was curious how you handled this.

In either case, the program must allow the user to specify the location of the database, and it must also accept an indication that a local database is to be used, in which case, the networking must be bypassed entirely.

Note the bold portion of that sentence. Did you use some sort of indication that the local database is to be used? Or is this 'indication' equivalent to the mode (ie. alone) you start the application in? This is what i would think, but im not sure. Any ideas? Thanks, Dave

Dave Knipp
Ranch Hand

Joined: Oct 14, 2003
Posts: 146

posted Nov 18, 2003 12:02:00

0

Ken, Don't want to be a pest, but i thought of one more question. In your assignment did you handle the situation where the server could go down while the client is connected? And if so, did you provide some way for the server to tell the client that the server is down? I was just curious if sun thinks this is a mandatory requirement, but i guess if its not an automatic failure you could do it either way. Thanks, Dave

Or is this 'indication' equivalent to the mode (ie. alone) you start the application in? The mode of "alone" is all you need as an indication that a local DB is to be used. You may need to let the user confugure other stuff at this point (like what's the path to the DB file), but the decision to use a local DB was made the moment the command "java -jar runme.jar alone" was entered.

"I'm not back." - Bill Harding, Twister

Bill Robertson
Ranch Hand

Joined: Mar 21, 2003
Posts: 234

posted Nov 18, 2003 12:31:00

0

Ken, ever since you posted your score you have become the go to guy. Maybe next time you'll think twice Did you ever get a chance to take a look at my response to your question where you responded with "I don't understand your question." By the way if I am asking to many questions just tell me.

Dave Knipp
Ranch Hand

Joined: Oct 14, 2003
Posts: 146

posted Nov 18, 2003 12:35:00

0

Jim, Ok that sounds logical. I think what confused me was how sun worded it. Made it sound like we had to do more than just let the user supply the path to the db. Thanks again man! Dave

Jim Yingst
Wanderer
Sheriff

Joined: Jan 30, 2000
Posts: 18671

posted Nov 18, 2003 12:53:00

0

I think what confused me was how sun worded it. Made it sound like we had to do more than just let the user supply the path to the db. Yeah, I think Sun is intentionally trying to sound like a company that's a little confused what they want. Some requirements get explained twice (sometimes with subtle differences, as in the search requirements); others aren't really explained at all (as in DuplicateKeyException). We get to sort through their mess and make some sort of sense out of it.

Dave Knipp
Ranch Hand

Joined: Oct 14, 2003
Posts: 146

posted Nov 18, 2003 13:04:00

0

Jim, So thats what we pay all that money to them for! hah! Did you by chance deal with the server notifying the clients that it went down? I think im going to do this, but was curious if others had too. Dave [ November 18, 2003: Message edited by: Dave Knipp ]

I think the key to this good score is allowing bookings to be un-booked. A well known source mentioned this to me after looking at my submission. Tony

Bill Robertson
Ranch Hand

Joined: Mar 21, 2003
Posts: 234

posted Nov 18, 2003 15:29:00

0

I think the key to this good score is allowing bookings to be un-booked. A well known source mentioned this to me after looking at my submission.

But in a sense he doesn't really provide un-booking. He just allows for overwrites. And who knows, the points he lost was in general considerations and this may be one of them because allowing overwrites is a lot easier then making sure the record has not already been booked. A lot easier!! Did you provide an un-book button. I implemented un-book functionality but I am hesitant to put it on the GUI.

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 18, 2003 15:33:00

0

Bill, I think the metadata approach is overkill for this assignment. kktec SCJP, SCWCD, SCJD

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 18, 2003 15:50:00

0

Dave, Regarding "server notifying the clients", the following describes what I did. If the server goes down and the user sends it a request, the exception thrown is caught and logged. The gui then displays a simple warning dialog before exiting. I didn't send any message to the clients if the server is shutdown. That would be a nice thing to do for users in the real world but may not always be possible, i.e. server is about to crash. kktec SCJP, SCWCD, SCJD "The journey is the reward."

Dave Knipp
Ranch Hand

Joined: Oct 14, 2003
Posts: 146

posted Nov 19, 2003 07:13:00

0

Ken, ok, that sounds like a good alternative, b/c you are correct in saying that the server may be crashing and the client would never know if the server did indeed go down, so it should be handled on the client side. One other thing though, did you have the server communicate with the client at all? For example, does the server inform all the clients connected that the information in the database is updated and therefore the client should do a refresh? I'm torn between implementing this, on the one hand the client should be the one performing the actions, booking, unbooking, etc. So if the server didnt notify the client the client would basically do a refresh himself when he performed an action, book, unbook, or search. But, this could create many problems, what if the user has been logged in for 2 hours and hasnt done anything, he has very very old data displayed on his screen. Should he try to book a record, and then get a message back saying it was already booked, and then after that he would get refreshed? It seems like all client server systems use some sort of server to client communication. Think of any online game you ever played, if you didnt get any info from the server you would be able to play at, b/c you couldnt tell what everyone else was doing in the game! What is your opinion? Dave

Ken Krebs
Ranch Hand

Joined: Nov 27, 2002
Posts: 451

posted Nov 19, 2003 20:00:00

0

Dave,

does the server inform all the clients connected that the information in the database is updated ?

This could very well be a good feature for this type of system, particularly if the number of simultaneous users is not high, but it simply is not required for this assignment. It's extra work that probably won't help your score but might hurt it if you don't get it right. Now, if you're just interested in solving such a problem anyway , don't let me discourage you. The learning itself is probably the most valuable part of the exam anyway. kktec SCJP, SCWCD, SCJD "The journey is the reward."

Dave Knipp
Ranch Hand

Joined: Oct 14, 2003
Posts: 146

posted Nov 20, 2003 10:30:00

0

Ken, I totally agree. A system like this DOES need some way for the server to call back to the clients, but you're right in saying its out of the scope of this assignment. I actually implemented rmi callback to my client, but took it out after considering it might hurt my grade if i didnt handle it correctly. But i learned how and like you said thats the most important thing. Thanks again! Dave btw. i'm submitting tomorrow!

Bill Robertson
Ranch Hand

Joined: Mar 21, 2003
Posts: 234

posted Nov 21, 2003 09:40:00

0

Ken, Did you synchronize your reads/searches. Or did you use a cache. Thanks, Bill