• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

FBN Design Brainstorm!

 
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I'm quite far down the line with the FBN assignment and have researched quite a lot of books regarding some of the issues that I've come across within the requirements. The Habibi et al book has been very useful and has helped along the way on some of the topics regarding the certification.

The reason for this e-mail is to request a brainstorm on my current design to see whether or not there is anything missing that someone has come across during the submission or any other advice that would be helpful.
The system pattern is based upon the MVC, as I find this quite flexible for future enhancements, encapsulating the three logical areas into behaviour based division.
Within the "view" package I have a GuiTableView class that basically displays the data extracted from "model" to the user and captures user interaction. The fine details of gui design is still being considered.
There is also an array of GuiViews so that the refreshGuiViews() method can be used to update any "views" implemented. At present, the FBN says that the database updating the ui is not required (although optional) but to make this model flexible for the future I have decided to include it.
Within the "controller" package I have a GuiTableController that basically captures events from the GuiTableView and interacts with the "model" via the DatabaseModel.
Within the "model" package I have the DatabaseModel, which basically is a facade in providing the GuiTableController (or any future controllers) with a class that handles the locking and unlocking of records. The DatabaseModel hides the true database from the controllers (by wrapping it via the DatabaseClient) and in doing so can easily be amended to become an adaptor and therefore a future database can be introduced with a little modification.
Within the "model" package is the "db" (original Sun) package that holds the three supplied classes; Data, DataInfo and FieldInfo. I've amended the Data class to include the three required new methods and introduced a DatabaseClient interface, including all public methods, so that the database itself is further hidden from the outside world. The DatabaseClient plays an important role as it is used by the DatabaseModel to interact with this variant of the database.
Also within the "model" package is the DatabaseConnector that programmatically creates a local or remote connection.
Within the "db" package, apart from the introduction of the DatabaseClient, the locking mechanism is based upon recording the record in question within a Vector. This is very similar to how Denny's DVDs works within the Habibi et al book. By the way, the Data class now implements the DatabaseClient interface.
Question: Are there other types of locking mechanism that can be used or preferred? I find this one very simple to use and easy to code.
The decision to use RMI was preferred over sockets and I've introduced a "remote" package to hold the RMI classes. The DatabaseClient is used again and the DatabaseRemote interface extends the DatabaseClient and Remote interfaces. The DatabaseImpl class implements the DatabaseRemote interface and also holds a reference to the Data class.
Going back to the DatabaseConnector, the getRemoteConnection returns a DatabaseClient that is an instance of DatabaseImpl, which in turn invokes methods on the Data class. The getLocalConnection returns a DatabaseClient that is an instance of the Data class.
I think I've covered everything as far as I am with the assignment. At first I thought that the introduction of the DatabaseModel was a bit of an overkill but it does separate the "model" from the actual database and therefore the "model" can interact with different databases depending upon the implementation. It looks so much easier to understand with a class diagram!!!
Is there anything I should know about the FBN assignment that could come back and haunt me?
Any comments would be helpful.
 
author and jackaroo
Posts: 12200
280
Mac IntelliJ IDE Firefox Browser Oracle C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ian
Welcome to JavaRanch.

It looks so much easier to understand with a class diagram!!!



I know what you mean. I ended up putting class diagrams in my submission just because it made it easier for someone to see how everything hung together. I was able to follow your description easily because I had something almost identical in my submission.

Question: Are there other types of locking mechanism that can be used or preferred? I find this one very simple to use and easy to code.


There is no "one correct way" to develop this assignment. That is, for every issue, there are multiple ways to solve the issue and all of them are correct! So if what you have done works, and is easy to use and maintain, then you will be fine with it.

Is there anything I should know about the FBN assignment that could come back and haunt me?


Obviously there are many things you have not gone into detail on, so it is hard to pick anything that you should be concerned about.
One thing that I did notice you havent explained, and that is not clear given your comment about using Vectors, is how you are ensuring that only the connection which locked a record can unlock it. Care to comment on that?
Regards, Andrew
 
Greenhorn
Posts: 11
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hey guys
"One thing that I did notice you havent explained, and that is not clear given your comment about using Vectors, is how you are ensuring that only the connection which locked a record can unlock it. Care to comment on that?"
I would like to discuss this matter also. In my instructions, it says, regarding this issue:
"You are required to implement the criteriaFind(String), lock(int) and unlock(int) methods: " and:
"The unlock method simply removes the lock from the specified record. If an attempt is made to unlock a record that has not been locked by this connection, then no action is be taken."
I was thinking about maintaining a map of some sort, which should hold the record numers that was locked, and something describing the client that locked the record should be held as their value (hashcode, toString value or something).
However, this is not really possible if the lock method can only take one parameter. I would want to pass one more paramter, to identify the client calling the method.
Have anyone succesfully added a parameter to the lock and unlock methods, and passed? Or is it necessary to evolve into reflection or something, to get the callers ID?
Regards,
Flemming Mertz
 
Ian Roberts
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I was intending to use a "trust" protocol between the invoking client and lock() and unlock() methods. This would be explained in my design choices document. I did play with the idea of allowing the DatabaseModel to control the source of the invoking client object but was not sure how to implement this without using the Math.random() method.

I'm not intending to change the signature of the lock() and unlock() methods because I think that this would violate the constraints defined within the supplied document. Anyway, by changing the methods you are isolating them from being used by other clients, which may happen to be objects calling from another system but using the same interface. So, without actually changing the signatures I'm not sure how you can introduce control over the locking source - any ideas?
The example provided by the Habibi et al also uses a "trust" protocol but is this enough to pass or is there something else that Sun are expecting you to use without amending the signatures?
 
Ian Roberts
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Andrew, one thing I forgot to ask was how you managed to put Class diagrams into your return text document? This might be a silly question with an obvious answer but I was thinking about doing the same thing but not sure how to put diagrams into a text format?
 
Andrew Monkhouse
author and jackaroo
Posts: 12200
280
Mac IntelliJ IDE Firefox Browser Oracle C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ian
I am still reading Max's book, and I have not yet read about a "trust" protocol. So I do not know how well it can be applied. My concern would be whether it meets the requirement that " If an attempt is made to unlock a record that has not been locked by this connection, then no action is be taken."
You might be interested in reading No need for a locking manager? - it is very long, and some of the ideas that I suggested in there I am no longer convinced about, but you will see quite a few comments talking about how to track ownership of locks for FBNS. I am not saying that any of them are better than what you have, just giving you some more ideas.

Andrew, one thing I forgot to ask was how you managed to put Class diagrams into your return text document?


I had the class diagrams in HTML pages, linked from my HTML design decisions document (that doesnt have to be plain text).
If you did want to work in plain text mode, you can still draw your class diagrams using text characters - it just is more hard work, and doesnt look as pretty:

Regards, Andrew
 
Ian Roberts
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Andrew,
Thanks for the information. I will certainly check out the notes regarding a LockingManager and review this area of my design.
 
Ranch Hand
Posts: 62
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi, Ian,
It seems that for every client you have a instance of databaseClient for it. Where do you fire the database change listener so that every views' refreshGuiView() will work?
Regards
Davidd
 
Ian Roberts
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Davidd,
This is an area that I have been trying to decide whether to progress or not, well at least for the submission of the project. In order to update all gui objects, a collection of the connection objects DatabaseModel would have to be maintained and the Data object would have to task to a specialised object or provide a method that iterated through the collection of DatabaseModel objects, invoking the updateView() method. The updateView() method will iterate through a collection of gui objects, active for this model, and call the refreshView() method. This is a draft idea so, in reality, it would require much more thought before being implemented.
The reason I am trying to decide whether or not to include a refresh mechanism is basically that it is not a specific requirement for the assignment and that it would require much more extensive testing then providing the simple data request and display mechanism that the assignment specifically requires.
My intention at the moment is to drop the refresh mechanism for the submission but to create another version of the application and to play with the refresh design. A bit like an iterative RUP approach, I suppose!
Have you included a refresh mechanism into your design? It is quite easy in this job to over-engineer the requirements into something you want rather than something the client wants. In this scenario, there is no way of going back to the client and asking for more money so it is probably safer to drop it.
Ian R.
 
Ian Roberts
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Andrew,
Thanks for your comments earlier about the LockManager and assignment requirement for a locked object to be unable to unlock a record that it does not own.
As this requirement is within the assignment instructions, the "trust" protocal I mentioned is no longer valid and I've now provided an alternative solution, although quite similar.
I agree that there is no right or wrong way of doing this and that a LockManager may be just as valid as a Data object handling its own locking mechanism but the solution I decided upon was as follows:
(a) Amend the Vector to a static HashMap (key = Integer object reference of the record number and value = Data object reference (i.e. "this").
(b) On locking a record, the lock() method does the necessary checking and, once a lock has been obtained, puts the Integer reference of the record number and data object (this) into the HashMap.
(c) On unlocking a record, the unlock() method checks first to see whether the object returned from the get(recordNumber) is equal to the invoking Data object. If it is, the key is removed from the HashMap, otherwise it is ignored - as requested in the requirement.
Thanks again! How I had forgot that requirement is beyond me (and worrying) but it could be something to do with an eight month old baby draining my memory and senses! Its hard enough going to work without finding the energy to complete the assignment!
Cheers,
Ian R.
 
Ranch Hand
Posts: 108
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator


Is there anything I should know about the FBN assignment that could come back and haunt me?
Any comments would be helpful.
[/QB]


I can only say two things about what concerned me most:
1. i could not tolerate my program to throw runtime or corrupt the database in case of invalid input,so i went overboard to validate the input: i did validation on input format and on seats and everything was very flexible and not hard-coded, so it definitely added to complexity of my program. It was only thing that i specifically enforced even nobody asked me to.
I included 'Refresh' button on client's gui so it can see latest updates on its will. If it thought that there were 2 seats available and tried to reserve but, in fact, there were 0 because it did not update its view, the explanation was posted to explain why it was refused the reservation. So, I did not bother to 'push' updates on the client.
2. thanks to this forum right before submission, i noticed that i forgot to implement the requirement of client's pointing to location of the database on the server's side , so i had to add this functionality too to my already working and kissed all over program right before the submission.
I was very impressed how the forum helped me to avoid the obvious omission of the requirements.

When i get my results i'll tell more about my design details.
 
Andrew Monkhouse
author and jackaroo
Posts: 12200
280
Mac IntelliJ IDE Firefox Browser Oracle C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ian,

Amend the Vector to a static HashMap (key = Integer object reference of the record number and value = Data object reference (i.e. "this").


This implies that you have one instance of the Data class for each connected client.
In which case, have you handled the fact that two clients adding a record simultaneously may overwrite each other, and that a record added by one client may not be visible in another client?
(I know - the GUI we write does not have to add records, but an external program might).
Regards, Andrew
 
Ian Roberts
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Andrew,
For performance issues across a network, I decided to have a dedicated Data object per connection rather using a singleton to handle all requests to the database. This is similar to how we use EBS/EGS objects at work within the commercial environment. There is too much traffic for a singleton to handle so we create our own gateway access objects.

I'm not sure what you mean by two clients overwriting each other if they requested to "add" a new record at the same time. This is surely handled by the issue of a new record number and the locking mechanism. Although there may be several Data objects there is only one lockedRecords HashMap and only one database? Am I missing something? Please can you expand on what you mean?
As I wont be introducing a "push" MVC pattern for the assignment, the Gui objects will not be updated with a new record added to the database but the idea of a "Refresh" option does sound like a good idea.
Ian R.
 
Ian Roberts
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Andrew,
I see your point now regarding the add of records. By making the recordCount a static variable it does reduce the risk but I'm not sure it solves the problem. Without using a Data object per connection you would have to use some other mechanism of checking the source of the connection prior to unlocking a record and that would mean changing the lock and unlock method signature, which I don't agree upon.
By accessing a single Data object with a number of connections there will be a performance issue concerning all the methods that are synchronized.
One idea is to change the "int recordCount" to a "static Integer recordCount" and put a synchronization block on recordCount prior to adding a new record. This would protect the recordCount from being updated until after the new record has been written.
I was wrong in thinking that you could lock a new record because (a) why would you - it doesn't exist yet so no one can access it and (b) you don't know the record number until it is created.
Does this sound reasonable? Are we allowed to change the member variables on the Data class - has anyone done this before or know if it would prompt an instant fail?
One solution creates another problem - at least it is quite interesting to solve.
Ian R.
 
Andrew Monkhouse
author and jackaroo
Posts: 12200
280
Mac IntelliJ IDE Firefox Browser Oracle C++ Java
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Ian

One idea is to change the "int recordCount" to a "static Integer recordCount" and put a synchronization block on recordCount prior to adding a new record. This would protect the recordCount from being updated until after the new record has been written.


Remember that Integers are immutable objects - you would have to be very careful with your coding here.

I was wrong in thinking that you could lock a new record because (a) why would you - it doesn't exist yet so no one can access it and (b) you don't know the record number until it is created.


Actually this is (or was) quite common in general database design (not necessarily this assignment). You currently have 5 records. Threads A & B both want to add a record. So thread A locks record 6, and thread B locks record 7. Now both thread A and B know that that they have a dedicated location to store it's record. This can be useful when you are adding to two or more tables simultaneously, and need to know what record numbers are going to be used in one table so that they can be stored in another table.
However I think it is masively overkill for this assignment. Just stick to enforcing only one thread may create a record at a time, and you should be fine.

Does this sound reasonable? Are we allowed to change the member variables on the Data class - has anyone done this before or know if it would prompt an instant fail?


I am sure that Max is laughing at the moment, because some of the warnings I am giving you are the same ones that he gave me when I did the same thing. Unfortunately I had already submitted when I started my conversation with Max.
So yes - I did change the member variables and the way some of the provided methods worked, and I did pass.
There was a recent post where one person even changed one (at least) method signature in the provided Data class to throw a different Exception than the one given. He provided good arguments why he did that, and he passed.
However Sun did tell us that the provided classes and methods were complete except for specific modifications we had to do, so I believe that we should not be changing them without a very good reason. You have to decide if your performance increase is a good enough reason (especially since performance is not a criteria in this assignment).
Regards, Andrew
[ August 27, 2003: Message edited by: Andrew Monkhouse ]
 
Ian Roberts
Ranch Hand
Posts: 46
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Andrew,
I have spent the last couple of days reviewing my original design and the justification of using multiple Data objects and, I agree, performance alone is not enough to adopt this approach.
I am currently looking at a single Data object created by the server application. During the client startup, if a remote database connection is selected, a DatabaseConnectionImpl object will be instantiated (using the Factory pattern) that will wrap the Data object.
A giu controller that invokes the lock()method on the DatabaseModel object (behaving as the remote client object) will invoke the lock() method on the DatabaseConnectionImpl object. This object (behaving as the connector) will have a collection of owned locks and, once a lock has been obtained by invoking the Data lock() method, will add the passed recordNumber parameter.
On unlock(), the DatabaseConnectionImpl object first checks to see whether or not this connection "owns" the lock and (if so) invokes the Data objects unlock() method to remove it before updating its own collection.
The reason I decided on this approach rather than a LockManager is simply because after once again reading the Sun instructions, I am assuming that the following is required:
"The unlock method simply removes the lock from the specified record."
In the same paragraph it then continues...
"If an attempt is made to unlock a record that has not been locked by this connection, then no action is taken."
It would be poor OO design to have a database object determining whether or not a connection owned a object because that is a behaviour that the connection's responsibility. So, I am assuming that the phrase "this connection" is used to describe a connection behaviour not database behaviour.
This is a very good assignment and once again I don't think there is a right and wrong way so long as you can completely justify the approach you have taken.
Good stuff!
 
reply
    Bookmark Topic Watch Topic
  • New Topic