I posted some parts of my choice.txt for your reference. Hope this should be helpful.
================================================== Test: Sun Certified Developer for the Java 2 Platform (310-027) Date Taken: 2005-03-04 07:58:47.577 Site: ti8 Grade: P Score: 359 Comment: This report shows the total number of points awarded for each section. The maximum number of points is 400, to pass you need a score of 320. Section Summary: Section Max Actual Points Points General Con: 100 89 Documentation: 70 62 OOD: 30 30 GUI: 40 28 Locking: 80 80 Data Store: 40 30 Network Server: 40 40 Total: 400 359 ================================================
GENERAL CONSIDERATIONS ======================= This is a 3 tier solution and MVC design pattern is adopted.
USER INTERFACE =============== Column width is adjusted automatically to fit screen size. Numerical columns are right alignment.
Lock Cookie Generation ================= Unique lock cookie is generated by a sequence number because this mechanism is easy to code and maintain.
Visibility Of Lock and Unlock ===================== lockRecord() and unlock() methods are not exposed to DBAdapter.java, which means lockRecord() and unlock() can be used only within Model tier, because incorrect using and calling these 2 methods could lead database to crashing or being in a dead lock trouble.
Thread Queue ========== In Data.java, the create/read/find functions are executed by the current thread after the only one Data object is locked by the current thread so that the basic transaction can be safe. Also, in the multiple-thread environment, the locking implementation of update/delete function I chose is to maintain a thread queue for each record. Because a thread must call lockRecord() to lock the thread specified record before calling the method updateRecord()/deleteRecord() and must call unlock() to unlock the thread specified record after calling the method updateRecord()/deleteRecord(), the thread queue mechanism can be done in lockRecord() and unlock(). There are 3 elements to the thread queue mechanism, long lockCookieCount to generate unique lock cookie, HashMap lockedRecNos to stroe which record is being locked and to store a thread waiting list corresponding to this record, and LinkedList threadWaitingList to store all the waiting threads which wait for the same record. Every time a thread accesses lockrecord(), lockCookie pluses one to generate a unique number and the thread name is set with this unique number. When more than one threads want to access the same record, the very first one thread locks the thread specified record and make an entry in HashMap lockedRecNos to notify other threads that the very first thread is being using the record. Then, all other threads have to wait for their turns and are stored in LinkedList threadWaitingList which is also stored in HashMap lockedRecNos. After the very first thread finishes its work, the thread queue wakes up the next thread, removes the very first thread and then allows only the next thread to access the same record. Due of the thread queue mechanism, threads wanting to access the same record can be executed one after one in the sequential order (first in first out with LinkedList objects) and then make basic transaction safe. And no waiting thread consumes CPU cycles until it is waken up.
Shutdown ======= The implementation of shutdown function I chose is when the server is started, Data.java registers a shutdown hook with JVM to release (close) all open resources. The registered shutdown hook is responsible for closing the RandomAccessFile Object. Also, when creating RandomAccessFile Object, the parameter "rws" is passed to require that every update to the file's content or metadata be written synchronously to the underlying storage device.
SwingInfoExceptionHandler =================== When information of an exception needs to be display, simple and short messages about this exception are shown in a dialogue to end user with OK and ADVANCED buttons. The user can click OK button to close the dialogue or can click ADVANCED button to know more details.
IllegalArgumentException ================== In Data.java, the checkInputData() method checks all input data to database. It checks the field length, the field number, data format, data value and data type. If the inputted data violates constrains, IllegalArgumentException is thrown. There are 2 more situations to throw IllegalArgumentException. A null value in primary key also throws IllegalArgumentException in createRecord(). I would throw an IllegalArgumentException with a message if any attempts to update the primary key fields are made in the update() method.
AlreadyBookedException ================== AlreadyBookedException is thrown by interface DBAdapter.java and by 2 concrete implementation classes, DBAdapterImpl.java and DBAdapterRMIImpl.java. This exception means that the contractor a user tries to book has bean already booked.
IOException And DataException ======================= The signature of the methods defined in interface DBAccess.java can not throw an IOException. But this checked exception could be thrown by methods of RandomAccessFile.java when the methods of Data.java, implementation of interface DBAccess.java, need to access database file. Therefore, I decided to add DataException.java which extends RuntimeException and to make DataException wrap IOException.
DataNotConsistencyException ===================== DataNotConsistencyException is thrown when the data of a contractor in the GUI screen is different from the current data of this contractor in the database.
ControllerException ============== ControllerException is mainly thrown by Controller.java. When Controller.java receives any exception from database, it wraps the original exception from database with ControllerException and rethrows ControllerException to its caller in stead of throwing the original exception. In this way, a client of Controller.java can deal with only ControllerException rather than many different kinds of the original exceptions from the database. This makes programming easy.
Booking Overwriting (Unbook) ===================== This optional overwriting is a procedure of unbooking implementation. I decided when a user tries to book an already booked contractors, he will be warned that the contractor has been already booked and that he must unbook the specified contractor before booking. When he tries to unbook, he presses the book bottom with empty owner id field.
Encoding ======= In the instructions.html, the character encoding is 8 bit US ASCII. However, there is no 8 bit US ASCII and I think it sould be a typo. Therefore, I used ISO-8859-1 instead of 8 bit US ASCII.
Null Termination ============ All records of data file provided are space-padded but the instructions.html mentions "all fields...null terminated" and "without altering the data file format" so there is a conflict. I think the data file should be valid. Therefore, in this project, I chose all records are space-padded.
Search Function ============ #Server Side: Data.java exposes findByCriteria() method for search function according to DBAccess.java. This method provides generic serch functions and is implemented by using String.startsWith. However, the generic search functions can't fulfill the requirements of the instructions.html and DBAdapter, a wraper class of Data.java, wraps and extends findByCriteria() to add 3 new search functions, findByCriteriaStartsWith(), findByCriteriaEquals() and findByCriteriaIndexOfIgnrCase().
#Client Side: In the user interface, a user can search database by 5 criteria, by name, by location, by name or location, by name and location, all records. These criteria can also have 3 different patterns to match records, Start With, Exact Match, Contain so a user can have at least 13 different search functions with different combinations. Start With and Exact Match patterns are case-sensitive but Contain pattern is not case- sensitive.
Primary key ======== I assume that the primary key is the composite key of Subcontractor Name and City of the contractor because there should not be any two businesses in the same location with the same name. Besides, from database theory, a primary key should not be null. My update() method would not allow the update of primary key fields.
Lock Cookie Transmission =================== The instruction doesn't explain lock cookie very much. In order to comply with MVC design patter, I chose not to send lock cookie to the client but manipulate it only in server side.
Hi Steve, sorry for my impudent und foolish questions How do you think why did you receive only 28 points for your GUI? And 30 for your Data Store. Thanks a lot for your answer!!! and for SCJD! [ March 10, 2005: Message edited by: Olena Golub ]
I have 2 kind of transactions, basic transaction and business transaction. A basic transaction is the most basic CRUD and a business transaction means it includes one or more basic transactions. Also business transaction means all basic transactions it has must be run and must not be interrupted by any other thread.
In order to handle both kinds of transaction. I made my DBAdapter.java wrap my Data.java. My Data.java handles basic transaction and implements Singleton. Every thread locks the "only one instance of Data.java" by using synchronized(this) before doing something. Also, my DBAdapter.java, which wraps Data.java, controls business transaction. All business methods in DBAdapter.java have synchronized keyword so that method unit should be the smallest execution unit and basic transactions which a business method has can be done without any interrupted.
Because, in my Data.java, Every thread locks the "only one instance of Data.java" before doing something, Sun's automatic testing program can't fail even in multi-thread. Because my DBAdapter marks all methods synchronized, I can keep my client seeing the coreect data.
I am very glad you asked these questions. In fact, I would like to pay more for knowing where and why I lost some points.
I implemented GUI as the follows:
The search feature is designed to be composed of criterion and pattern drop-down combo boxes because it is easy to add new criteria and patterns in combo boxes with minimal disruption to the users.
The information of contractors, selected contractor, search and book panels use JScrollPane. Therefore, when downsizing the optimal main window screen, a user can still see and operate the main window with scroll bar help.
The main interface uses the BorderLayout with information of contractors panel in the center part and with selected contractor, search and book panels in the south part. The main interface also contains a menu bar in the top of information of contractors panel. The selected contractor, search and book panels use GridBagLayout to manipulate JFC components so they can be fixed in size even when a user changes the size of the main window screen.
I also make columns automatically fit screen size and to set 3 numerical columns right alignment. This makes the outlook more user-friendly.
Some of my friends belived I can get a good score in GUI part since they all like my GUI. I don't know how SUN graded my GUI.
Regarding Data Store, I really don't have any idea about the bad score. I don't think the data can't be written to file correctly. The only reason I think is maybe the coding way is not easy to be maintained.
So : the Data defines the basic transaction(create/delete/find) and the client - DBAdapter warps the Datas (basic) transaction in to business transaction - here is the lock manager. But why is the Data a singleton ?
I want to stress that having a lock manager in Data.java doesn't mean you don't need to have another lock manager in DBAdapter.java.
In my program, basic transaction and business transaction have different purposes. Therefore, I have 2 locking mechanisms in different java classes (or you could say "different layers".) (But I don't think my 2 locking mechanisms are lock managers.)
One of my locking mechanism: In order to keep basic transaction safe, every thread in Data.java must lock the only one instance of Data.java before doing anything so no other thread can break CRUD. And only with Singleton, the sychronized(this) can successfully lock Data.java.
the oerh one is: DBAdapter.java marks all methods synchroized.