This week's book giveaway is in the OCAJP 8 forum. We're giving away four copies of OCA Java SE 8 Programmer I Study Guide and have Edward Finegan & Robert Liguori on-line! See this thread for details.
91% pretty happy but just a bit disappointed with the GUI mark, I mean my GUI was really simple, no fancy stuff just a menu bar with an �Exit� menu item, two text fields to filter by name and location, a JTable and then lastly a �Book� button. I guess the only fancy functionality that I had was my runtime filtering using a DocumentListener on the two text fields, other than that simple.
To help understand how I implemented my solution here�s a snippet of my choices.txt (if this is not allowed then please notify me so I can amend the posting):
1. Overview 1.1 Assignment: Bodgitt and Scarper Version 2.3.2 ...
2. Architecture The application design makes use of a 3-tier architecture model, namely: 2.1 Presentation Layer (suncertify.ui): The user interface. 2.2 Business Logic Layer (suncertify.bl): Data access functionality exposed to the presentation layer, this layer includes service implementations for both local and remote services. Subsequently the reason for this layer in the overall architecture of the application is to provide transparency for standalone and network modes and decouple the business logic from the presentation and data access layer. 2.3 Data Access Layer (suncertify.db): I/O access, the ability to read and write to the database file.
3. Start Up The ApplicationRunner class is responsible for the start up process of the application which includes setting of the look and feel, handling the start up parameters and instantiating a new Application objects. The class will evaluate the parameter and determine which Application object to instantiate based on the selected mode flag, the mode flags are as follows are per parameter: 3.1 Standalone: The user is required to choose the path to the database file. 3.2 Network Client: The user is required to enter the hostname of the target remote server and port number of which the server is running on. 3.3 Server: The user is required to choose the path to the database file and enter the port number of which to run the server on.
If unexpected exceptions occur the application reveals the error to the user and represents the configuration view, recursively, so the user can change the configuration options or exit the application.
4. Client Design ...
5. Server Design The design objective for the server is simpler to that of the client design as the server operates without a user interface. When the user has selected the configuration for the server the configuration view closes and the server continues to run in the console window. I decided to implement no user interface for the server as not to over complicate the server implementation as the only operation available on the server is to stop the server, of which this can be done through the console window by pressing Ctrl + C and then confirming the termination of the process.
5.1 Network Implementation For the network connection protocol I implemented RMI with binding the implementation of the remote stub RemoteService. The RemoteService implementation is the RemoteServiceImpl which makes use of the decorator design pattern to wrap the LocalServiceImpl in the RemoteServiceImpl class. The advantage of the using the decorator design pattern is that: 5.1.1 Increases the usage of LocalServiceImpl implementation to be accessed remotely, 5.1.2 Conforms to OO principles and supports code reuse which creates transparency between standalone and network modes and 5.1.3 Increases the ease of maintainability as the business logic implementations only exist in one class (LocalServiceImpl).
5.2 Motivation for RMI ...
5.3 Network Implementation Design The design of the network implementation increases flexibility of the system as the network implementation design considers the change of the network connection protocol. The design includes two abstract super type classes of type Application, namely, NetworkClientApplication and ServerApplication which are used to define the different network client and server protocol implementations. Consequently to provide a network connection protocol, a sub type for the network client and a sub type for the server must be implemented as seen with the RMI implementation; RMINetworkClientApplicationImpl and RMIServerApplicationImpl. To provide an additional network connection protocol, such as sockets or http (web access), a new network client sub type and server sub type can be defined and the ApplicationRunner service method must be changed to instantiate the new network client and server sub type classes. More so from the above discussion of the design of the network implementation, it is evident that the design supports minimum change to the system and additionally provides the flexibility to easily implement additional network connection protocols.
6. Data Access Layer (DAL) Design As defined in the Sun specifications for the assignment I created the Data class that implements the DBMain interface however the Data class is a facade as the I/O data access and locking implementations are not defined in the Data class. The logical locking is implemented in the DataLock class and the I/O data access is defined in the DataAccess interface. The reason for the separation of the code is to create strong cohesion, subsequently one class responsible for locking records and another class responsible for data access. Additionally the data access design makes use of the adapter design pattern, as classes that use the DataAccess implementation (ContractorDataAccess) are oblivious to the fact if the DataAccess implementation class is accessing a flat file or a commercial database. The advantage of the making use of the adapter design pattern with the data access operation is that the system has the flexibility to easily change from accessing a flat file to accessing a commercial database without affecting references to the DataAccess implementations.
6.1 I/O Operations ...
6.2 Primary Key: Another data access layer decision that I had to make is the structure of the primary key. I decided that as concurrent CRUD operations can occur I decided not to use record position or index of elements but rather than information attached to a record that can uniquely identify each record. More so I decided that the primary key for each record would be a composite primary key which includes the concatenation of the hash code of the contractor�s name and contractor�s location, which is exposed through the getRecNo method in the Contractor class. The advantage of exposing the primary key implementation through the getRecNo method is that the implementation of the primary key is transparent to all dependencies so the structure of the primary key can change and all dependencies would remain unaffected. 6.3 Value Object: For simplicity of manipulating contractor data and concealing contractor data I adopted the value object design pattern to encapsulate the raw String contractor data read from the flat file into a Contractor value object. For ease of use with I/O operations I created a Contractor constructor to create an instance of a Contractor from a String which is primarily used for read operations where raw String data is parsed into a Contractor value object. I additionally implemented a toStringArray method which would parse the Contractor value object into a raw data of String which is primarily used for write operations.
7. Record Locking implementation The implementation of the Service book method in the LocalServiceImpl and is the only code that makes use of the locking API. The RemoteServiceImpl is a facade and encapsulates a reference to the LocalServiceImpl that uses the locking API through the LocalServiceImpl. I specified 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 record is locked, if the record is locked the current thread will wait for 5 seconds. When the record becomes available the longest waiting thread will be notified through invoking signal in the unlock method. In the event that the time elapses the thread will stop waiting without processing the locked record. If the record is not locked a LockInformation object is instantiated and put into a synchronized Map with the unique identifier of the record (Contractor) as the key. The LockInformation object stores a reference to the current thread to ensure only this thread can unlock the record and a reference to the Condition object used to yield other threads gaining access the locked record and to signal the waiting threads that the record has become available. More importantly implementing a reference to the Condition object in the LockInformation class creates a more efficient locking design as the records are locked at a record level, meaning that threads interested in other available records don�t have to wait for this locked record to become available. The locking API is implemented in the DataLock class, the locking of records implements a hand-over-hand locking with the concept of a master lock which would block access to the Map used to store individual record locks and a slave lock which is the actual record lock which blocks access to an individual record. Access to the record lock object can only be accessed through the locking/unlocking of the master map lock this design supports a more efficient concurrency model. I further provide read/write locking capabilities with I/O operation of the DataAccess implementation in the ContractorDataAccess class. The ContractorDataAccess class is responsible for accessing and manipulating the physical file that contains the raw contractor data. The reason for the read/write locks in the ContractorDataAccess class is to ensure thread safe data access operations and the flexibility to allow for a multiply threaded server environment if the requirement should arouse.
8. Record Search implementation ...
9. Use of Standard Design Patterns 9.1 Observer Pattern: Implemented to strive for loosely coupled designs between object that interact with each other. The pattern is used in controllers to define the actions on their associated view, as seen in with the ContractorController, the ContractorController implements the actions for the filter and book button of the ContractorView. 9.2 Compound Pattern: Model-View-Controller (MVC) a powerful compound pattern that is made up of a few patterns put together. 9.2.1 Model: The model holds the data state and the application logic and is oblivious to the view and the controller. The Contractor Model class can be seen as the model of the application. 9.2.2 View: Gives a presentation of the model. The ContractorView class is used to present the data of the model. 9.2.3 Controller: Takes the user input and figures out what the action means to the model. This functionality is handled in the ContractorController class. The MVC is implemented to define the flow between the data layer and presentation layer and decouple the data layer from the presentation layer. Additional usage of MVC can be seen with the implementation of the configuration classes, namely, ConfigurationModel, ConfigurationView and the ConfigurationController. 9.3 Decorator Pattern: Used to wrap an object to provide new behaviour. The pattern is implemented with the RemoteServiceImpl class which wraps an instance of the LocalServiceImpl to change the behaviour of the LocalServiceImpl for network clients to remotely reference the book and find methods. The usage of the design pattern supports the OO principle that, "classes should be open for extension and closed for modification". 9.4 Adapter Pattern: Implemented with the ContractorDataAccess class which encapsulates the low level access to the database file from references to this class. Subsequently classes that instantiate the ContractorDataAccess class are oblivious to the type of database accessed (flat file or a commercial database). The use of the Adapter design pattern for data access is that the design provides transparency when changing the type of database from a flat file to a commercial database and additionally will not affect any implementations or behaviour of the implementation that reference the ContractorDataAccess class. 9.5 Facade Pattern: Provides a unified interface to a set of interfaces in the system. The Data class implementation can be seen as a facade as the Data class calls other classes, as the Data class exposes locking and data access but the implementation of the locking and data access logic is implemented in different classes. 9.6 Proxy Pattern: Provides a surrogate for another object to access to it. The usage of this pattern can be seen with the design of the relationship between the Service interface and ServiceController classes, as the controllers use an instance of a Service object to access data layer functionality (Data class) such as book and find methods where the ContractorController uses an instance of the LocalServiceImpl/RemoteServiceImpl to access methods defined in the Data class.
10. Final Packaging for Submission 10.1 Package Structure ...
Alecsandru No idea why I lost so many marks on the GUI, it seems to be quite a pitfall for this assignment. In saying that I read other posts from other users that have implemented a GUI as simple as mine, and received full marks. I wish the assignment comments included feedback so as a student one would know where they went wrong which would help them improve. I mean instead of saying �you got 10/40 for your GUI design�� that�s great but it would of be nice if they add, �your mark was low as you implement business logic in your views�.
Then with the server again no idea, I implement a generic design to allow the flexibility of an RMI server or a Socket server (but obviously not a web server) and for each server implementation there is a client implementation respectively so a RMI server knows how to communicate with a RMI client and visa versa.
Mohini No I did not go into such details as 1) I work full-time, and 2) I felt my preparation pertaining to this assignment was suffice. More so I read Head First Design Patterns and the SCJD Exam by Andrew Monkhouse, two great books and I can REALLY recommend both.
However my design did include making use of a piece of paper and a pencil as I sketched the layout of the view to get an idea how was going implement the view (I did this a couple of times). I also "roughly sketched" how the objects were related and how they were going to interact with each other.
Good luck! [ November 25, 2008: Message edited by: Justin Rundle ]