• 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
  • Tim Cooke
  • paul wheaton
  • Liutauras Vilda
  • Ron McLeod
Sheriffs:
  • Jeanne Boyarsky
  • Devaka Cooray
  • Paul Clapham
Saloon Keepers:
  • Scott Selikoff
  • Tim Holloway
  • Piet Souris
  • Mikalai Zaikin
  • Frits Walraven
Bartenders:
  • Stephan van Hulst
  • Carey Brown

More on locking

 
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hello there,

As I saw, it seens to me that you preferer to give the control of the locking to the client.
In my assignment, I received that old interface:

..
public void update(int recNo, String[] data) throws RecordNotFoundException;
...
public void lock(int recNo) throws RecordNotFoundException;
...

I think locking could be done in two (or more ways):

1) the client calls lock, update and unlock
2) the client calls update and the update calls lock then unlock

Advantages:
1) nothing important to relate
2) one record never gets locked for ever (if i client fails to unlock);
it's more simple, I guess

Disadvantages:
1) nothing important to relate
2) a call to lock then update deadlocks the client and locks the record (it could be documented that the client shouldn't do this);
there would be no reason for lock/unlock methods to be part of the interface

So, I ask my self (and you) could I be penalized if I choosed number (2)?

Thanks,
Itapaj�.
 
Ranch Hand
Posts: 697
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

So, I ask my self (and you) could I be penalized if I choosed number (2)?



No.
 
Itapaj� Takeguma
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thanks.

but there's going to be no reason to have the lock, unlock and is locked methods.

Itapaj�.
 
Ranch Hand
Posts: 64
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Itapaj�,

The database that has the methods update(), delete(), lock(), unlock(), isLocked() etc..

When the user presses the BOOK button can we just call book() on the server and it in turn calls update() on the database?

No. If there are multiple users we need to shield the call to update to prevent corruption of the data. Either have your server expose the lock() / unlock() methods in which case the Client must call lock(), update() and unlock(). Alternatively use your Server to ensure that a call to book() calls lock(), update(), and unlock().

I prefer the second method as you retain control of locking in the Server. Future developments may bring new Clients in contact with your Server can we assume that they'll all follow the locking rules you have set?

Does that help at all?

Steven
 
Itapaj� Takeguma
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thanks Steven. That really helps. As a matter of fact, I started doind that way (the server controlling the locking. Doing it, would make easier to turn the application a web-based application).

What really worries me is that the lock/unlock methods would have no reason to exist (or almost no reason), even worse, if someone calls lock and update, the client deadlocks.

Is it reasonable to happen if this fact is documented?

thanks,
Itapaj�.
 
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 Itapaj�,

I would recommend that you think about one of the major values of having interfaces - they provide a contract that can be relied upon to work.

The interface that was provided to you is supposed to do certain things. If you do not meet these requirements you may fail, even if your solution is generally agreed upon to be a better solution. Your clients ("Bodgitt & Scarper" or "URLyBird") presumably had a reason for specifying the interface that they provided, and you cannot reasonably change it without discussing the changes with them (which you cannot do). This is the same in real life - if you are asked to design a tank and you come up with a Volkswagon, you will probably be sacked, even though your solution is more economical .

Starting with that premise, you have to assume that a client can call lock() before calling update(). So you will have to handle this case.

Note that this is a totally different discussion than the "Should lock methods be callable by the client?" That discussion is about where the calls to the lock methods belong. Your discussion is whether to even expose the lock() method to classes using the Data class.

Regards, Andrew
 
Itapaj� Takeguma
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Andrew,

Although I still think my solution is better, I agree with you.

Helped a lot,
thanks,
Itapaj�
 
Bartender
Posts: 1872
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Oh! A discussion about locking, just when I come back from my two-weeks vacation...
Thank you Itapaj�!

Although I still think my solution is better, I agree with you.



I agree with you that you may agree with everything Andrew wrote *above*. (I insist a bit on the "above" word, because I still disagree with what he wrote behind the link he mentioned above. (Of course.) )

But are you sure your solution is better? It lets me think to multiple past discussions I had with people who accepted the given interface with no such restriction in the use of the interface (a given public method (update) cannot be called if another public method was called before (lock)), but well in its implementation: they decided - just because of implementation-level reasons - to allow only one lock to be granted per client. If the latter was bad (IMO), your solution is even worst (still IMO).
Just because it holds both limitations.

What's interesting (still IMO) is that what you want to do (integrating lock/unlock to update/delete), which - de facto - disallows multiple locks to be granted to a given client, just proves that the interface's designers had multiple-locks-per-client case in mind.

Best regards,

Phil.
[ August 18, 2004: Message edited by: Philippe Maquet ]
 
Itapaj� Takeguma
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
thanks Philippe Maquet,

thinking this way, You seen right to me.
When I thought about restrict the lock to the server, I was just thinking that it would be easier for me to implement because many problems that can occur, for example, if the client goes down before calling unlock.

but I'm convinced that my old solution is neither acceptable nor good (until some one convinces me the oposite).

thanks,
Itapaj�.
 
Itapaj� Takeguma
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I remembered that I have one more question. I think that, above of all, locking is good to prevent data corruption. Then, when a client calls lock, my database has to gurantee that everything goes right.

but when a client calls update without calling a lock, that's his fault.
(even because there's no way to know (in my case) whoever locked the record).

isn't supposition right?

Thanks again,
Itapaj�.
 
Philippe Maquet
Bartender
Posts: 1872
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Itapaj�:
but I'm convinced that my old solution is neither acceptable nor good (until some one convinces me the oposite).



Well, I hope someone will try to convince you of the opposite... so the discussion can go on!

Itapaj�:
but when a client calls update without calling a lock, that's his fault.



Exactly! And that's why most of update method signatures in other assignments than yours (AFAIK) throw a SecurityException in the case the caller didn't successfully call lock() before calling update().

But are you sure that your assignment doesn't have - at least implicitly - a similar requirement? Could you post here the comment attached to your lock() method?

Itapaj�:
(even because there's no way to know (in my case) whoever locked the record).



Even in your case there is a way to identify lock owners: if you have one Data instance per client, the Data instance itself may identify the client, hence the locks owner. Depending on your design, you may need - or not - an additional layer though. But I'd suggest to keep it as simple as possible.

Regards,

Phil.
[ August 18, 2004: Message edited by: Philippe Maquet ]
 
Itapaj� Takeguma
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I think you may be right. Perhaps i have to worry about who locked a record:



but I'm still no sure.
I'll think a little more.

Itapj�
 
Philippe Maquet
Bartender
Posts: 1872
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Itapaj�,

// Locks a record so that it can only be updated or deleted by this client.



That's what I suspected.

Regards,

Phil.
 
Itapaj� Takeguma
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
hello Philippe Maquet (or anyone who wants to participate),

I was completely sure about your opinion about locking. And I did my system distinguish two clients some way that I could identify whoever locked a record. But no I think I shouldn't do that. Read what my assignment says:

Your data access class must be called "Data.java", must be in a package called "suncertify.db", and must implement the following interface:



But to distinguish betwenn clients I created a new class that really makes the access to the data and that has methods like update(recNo, newData, cookie). and my Data.java calls this class's methods.
So, my question is: How can I make my data access class (as says the assignment) implements DBMain.java and still make it have the power to detect the client who is calling it?

Thanks for your time,
Itapaj� Takeguma.
 
Ranch Hand
Posts: 1033
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Itapaj� Takeguma:
But to distinguish betwenn clients I created a new class that really makes the access to the data and that has methods like update(recNo, newData, cookie). and my Data.java calls this class's methods.
So, my question is: How can I make my data access class (as says the assignment) implements DBMain.java and still make it have the power to detect the client who is calling it?



I set up a session using a call to a method defined in a second interface that is also implemented by Data. The session manager passes the session id back to the client. This session id is then used in all subsequent network commands. The network server code sets the thread name to contain the session id when it accesses the database. This will work regardless of whether your network uses RMI, one socket per data command, one per business command or one per session as the thread name is set on each command.

Be aware if using RMI that a client doesn't always get the same thread, if you are using sockets with one per data command the client will never get the same thread, so you can't just use the thread object. The thread should be named to include a session id and a command sequence if you want to allow multiple concurrent commands from the same client.

If you are using a single socket for each session, you can just use the thread. This may be a good choice if the number of commands per user is high and the number of users is low. It does have the drawbacks that a client can only have one command active at a time, and each client occupies a socket for the whole of their session.

If your interface uses cookies, you can use the lock cookie to do this, but it still doesn't give you a way to remove all the locks if a client vanishes. This is not a requirement as far as i can tell, but in a real system it certainly would be.

There are two alternative choices to all of this:
- define a DataAdapter that provides all the data methods, with the interface cleaned up and reasonable exception handling.
- move the business layer code to the server, this is called thin client. It was the model I used in my first attempt, but now I've moved to the rich client camp. I don't feel that thin client actually meets the requirements and would have a hard time arguing that if I got an automatic failure for using it, but it is much easier than the rich client and some people have passed using it.
 
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 Itapaj�,


So, my question is: How can I make my data access class (as says the assignment) implements DBMain.java and still make it have the power to detect the client who is calling it?



Have you considered creating an instance of the Data class for each connected client? Then you could use the instance of the Data class itself as the owner identifier.

Regards, Andrew
 
Itapaj� Takeguma
Ranch Hand
Posts: 41
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Andrew Monkhouse:
Hi Itapaj�,



Have you considered creating an instance of the Data class for each connected client? Then you could use the instance of the Data class itself as the owner identifier.

Regards, Andrew



Sory for the late answer.
I did considered creating an instance of Data class for each client, but if I do that, the job of accessing the data should me moved to another place.
And that is what I'm doing now and I think it may be wrong:



but I think that it is possible that DataAccessObject should not exists to Sun's eyes, because if a programmer is supposed to put all File access in Data.java, it may be possible that a Sun Inspector will look first the Data.java to see how IO is implemented.

thanks,
Itapaj�.
 
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 Itapaj�,


but I think that it is possible that DataAccessObject should not exists to Sun's eyes, because if a programmer is supposed to put all File access in Data.java, it may be possible that a Sun Inspector will look first the Data.java to see how IO is implemented.



You might want to check your instructions to see whether that highlighted section is indeed required.

My memory is that the instructions are written in such a way that Data class can be (and in some ways, should be) a Facade to the real classes doing the work. The important bit is that your client / server applications all go through the Data class to access the data file.

Regards, Andrew
 
Ranch Hand
Posts: 69
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Ok, I'm starting to look at my locking design.... and I have the plain Jane interface that looks like this (ie: no cookies):



I've read tons of threads here on locking and I have Habibi's book.

Here's what I'm thinking... these quotes both come under the SERVER section:

Locks a record so that it can only be updated or deleted by this client.

You may assume that at any moment, at most one program is accessing the database file; therefore your locking system only needs to be concerned with multiple concurrent clients of your server.

To me this means either the standalone program is accessing the DB or the server program is accessing the DB (see my use case below):

http://www3.telus.net/rmch/Pics/use_case_diagram.jpg

The first locking comment is just common sense. If I'm client 1 and I need to update a record, I need to lock it before client 2 comes along and tries to lock/update it in mid-stride. Also, after I lock a record I need to know it stays locked until I'm done with it. That means at the very least, a list of records currently locked.

If the Data class (which implements public methods from the DB interface) is available directly to a client application that doesn't enforce the lock/change/unlock rule, then I can see why you'd need to know who the client was that just locked a record. It's possible that the client application did not perform an atomic operation, and has come back looking to do an update.

However, if an Adapter pattern is used on a class that lies between the Data class and the client application, then create/update/delete operations in this class can enforce an atomic operation by doing the lock, then the modify, then the unlock in a single method.

The same class can be retrofitted to run in the RMI server as a UnicastRemoteObject.

This is essentially what I see in Max's code as well. But, his project doesn't have cookies defined in his interface either.

Do you guys see any problem with my thinking?
 
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 Robert,

Nice use case diagrams. It looks like you have separate packages identified as "Data layer" for server and stand alone mode. Is that correct? If so, why?

You are partially right - if you have all your business logic on the server, then your business methods can ensure that any data modification methods are callled from inside lock and unlock calls.

But the question is - does this really meet the requirements? Your instructions indicate (at least in my opinion) that Data must track which client called lock regardless of whether business logic is in the client or the server. So you cannot just ignore the requirement because you found a simple workaround. (If you do, you will probably pass, but you may not get full marks).

I have tried to avoid the general discussion on whether business logic should be on the client or server. If you would like to read up on that, take a look at the thread "Should lock methods be callable by the client".

Regards, Andrew
 
peter wooster
Ranch Hand
Posts: 1033
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Andrew Monkhouse:
Hi Robert,

Nice use case diagrams. It looks like you have separate packages identified as "Data layer" for server and stand alone mode. Is that correct? If so, why?

You are partially right - if you have all your business logic on the server, then your business methods can ensure that any data modification methods are callled from inside lock and unlock calls.

But the question is - does this really meet the requirements? Your instructions indicate (at least in my opinion) that Data must track which client called lock regardless of whether business logic is in the client or the server. So you cannot just ignore the requirement because you found a simple workaround. (If you do, you will probably pass, but you may not get full marks).

I have tried to avoid the general discussion on whether business logic should be on the client or server. If you would like to read up on that, take a look at the thread "Should lock methods be callable by the client".

Regards, Andrew




I have read that thread end to end a few times, I started using the "thin client" model and have since moved to a "rich client" because I can't really justify the bending of the requirements that is needed to go that route.

Under the heading "What you must do" My assignment says "the following are top level features that must be implemented
- a client program with a graphical user interface that connects to the database
- a data access system that provides record locking and a flexible search mechanism
- network server functionality for the database system."

Later the assignment says "your user interface should be designed with the expectation of future functionality enhancements, and it should establish a framework that will support this with minimal distruption to the users when this occurs."

The first quote says that they really want three parts
- client
- network
- database
not
- client
- network
- business

The second part says that if the customer wanted to add the feature of being able to add new records to database or do arbitrary updates, that adding these to a specific client should not require changes to the server that would have global impact. Rather the framework to do just about anything you want in the client without changing the server should be there.

Given these two requirements, one of which uses the magic word "must" twice tells me that the thin client is not really a good choice. If I did that and got an automatic failure, I'd have very hard time defending it.

I have concidered a third option, that is both thin and rich, in this option I would define a Data Access Object on the server (currently its on my client) that provides the following methods:

- search, returns an array of Transfer Objects matching criteria, criteria supports matching on any fields, both and and or and both partial and complete.
- validated update, takes 2 Transfer Objects, old value and new value, does
{lock, read, check old value, update, unlock} throws an exception if the old value doesn't match.
- validated delete, takes a Transfer Object, does {lock, read, check, delete, unlock} throws an exception if the old value isn't valid.
- create new record, take a Transfer Object.

This option allows the client to be totally ignorant of locking issues, performs the current business operations as single calls to the DAO, and still be flexible enough to be able to implement any data access without requiring server changes. The fact that the DAO acts as an adapter to the Data class means that all the Exception hassles go away, you get to throw what you need. This DAO provides all the CRUD operations and would allow the client to plug in other data providers.

In my next iteration I may actually try implementing this. It has the advantage that it provides a flexible framework, yet relieves many of the issues related to things like lost network connections and absent minded users who go to lunch with records locked.
 
Robert Chisholm
Ranch Hand
Posts: 69
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi guys,

Thanks for the comments. Before I make any more, I'll point you to my current class diagram. Maybe it will give you a better idea of what I'm planning:

http://www3.telus.net/rmch/Pics/db_diagram.jpg

Peter... sounds like your next iteration is exactly what I'm prototyping now.
[ September 10, 2004: Message edited by: Robert Chisholm ]
 
She's out of the country right now, toppling an unauthorized dictatorship. Please leave a message with this tiny ad:
Smokeless wood heat with a rocket mass heater
https://woodheat.net
reply
    Bookmark Topic Watch Topic
  • New Topic