• 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

NX: Exception handling implementing the DBAccess

 
Ranch Hand
Posts: 36
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
The DBAccess interface specifies the implementation of readRecord(long) must throw only a RecordNotFoundException (a class implementating this interface can not throw additional exceptions ???).
In the implementation IOExceptions can be thrown by the RandomAccess file methods. How is the best way to handle/throw these, handling would not be a good idea at this level as the IO exception is probably unrecoverable.
I am chaining the IOException into a RecordNotFoundException and throwing that with a description (to be displayed in a dialog box in the client GUI).
Ideas?
 
Ranch Hand
Posts: 435
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have the same problem how do you report an IOException or UnsupportedEncodingException to the user.
I know they are unlikely ever to be thrown but I think we need to bring them to the attention of the user, as they need to know a record wasn't created, updated or deleted. I supose the choices are throw a Runtime exception or wrap the exceptions in the exceptions defined in the interface ?
Tony
 
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I don't think we can wrap the IO exception in the RecordNotFoundException. My assignment has this clause


Any methods that throw RecordNotFoundException should do so if a specified record does not exist or is marked as deleted in the database file


This leaves only one choice - throwing them us RuntimeException's. But, is it justified to catch a checked exception and throw a runtime exception.
Also, my other methods which are not part of the interface, throw IOException. This results in a inconsistency.
Maybe, Sun wanted us to ponder on this..
 
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I've always felt that this application should have a middle, in addition to a front and a back. That is, the sorts of exceptions you're concerned with should, IMO, be caught in the middle layer, and friendly errors should be displayed to the user. Specifically, I don't think user does need to know that a remote exception was thrown: however, they probably do need to know that the record wasn't locked, etc.
The sum total of my suggestion is that your backbend throw whatever exceptions are appropriate( including your our, non-runtime exceptions). The middle layer, in turn, should then produce friendly error messages fro the front end. The GUI user really shouldn't ever see an Exception unless it's a JVM sort of thing.
All best,
M
[ July 30, 2003: Message edited by: Max Habibi ]
 
S Bala
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Max,
I can understand in case of checked exceptions. But, in this scenario we are forced to rethrow an IO exception as a runtime exception.
where do we handle that?
Maybe only one record is corrupted. Then it is necessary to continue with the rest of the operation (eg. of reading the rest of the records).
thanks.
 
Tony Collins
Ranch Hand
Posts: 435
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I also wondered about createRecord and upDateRecord, should they throw overflow exceptions if the user tries to create/update a field with too many fields? This seems to be the norm in Java Buffer API's from what I can see.
Tony
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by S Bala:
Hi Max,
I can understand in case of checked exceptions. But, in this scenario we are forced to rethrow an IO exception as a runtime exception.
where do we handle that?
thanks.


Can you please refresh me on where you're forced to do this? I want to make sure my advice is in context.
M
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Tony Collins:
I also wondered about createRecord and upDateRecord, should they throw overflow exceptions if the user tries to create/update a field with too many fields? This seems to be the norm in Java Buffer API's from what I can see.
Tony


I don't think I'm following Tony: Are you saying that throwing overflow exception and then going on is the norm in the Java Buffers?
As an aside, don't forget that you can chain exceptions if you're using JDK 1.4. I'm happy to review that, if it's useful.
M
 
S Bala
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Max,
Here is one of the method signature in the interface provided by Sun looks like --


// Reads a record from the file. Returns an array where each
// element is a record value.
public String[] read(int recNo) throws RecordNotFoundException;


The assignment also mentions that ..


Any methods that throw RecordNotFoundException should do so if a specified record does not exist or is marked as deleted in the database file.


So any IOExceptions we get need to be chained back as RuntimeException. This is true for all the methods in the data class which implements the interface.
SB
 
Tony Collins
Ranch Hand
Posts: 435
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yeah I see that with create/update record, you can
1) chain the BufferOverflow exceptions and pass them in a RecordNotFoundException, or
2) just make sure the buffer doesn't overflow and don't report any exceptions. (e.g chop the end of a string, or pad a string with spaces.)
I supose the jist of my question is that should every method you write act like a proffesionally written API as in 1 or as in 2 a bit of a bodge. And in that last sentance I think I have answered my own question.
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
/*

Originally posted by S Bala:
Hi Max,
Here is one of the method signature in the interface provided by Sun looks like --

So any IOExceptions we get need to be chained back as RuntimeException. This is true for all the methods in the data class which implements the interface.
SB


I guess I'm having a hard time understanding why it has it be a RuntimeException. It could
1) be a special subclass of RecordNotFoundException(say IORecordNotFoundException), or,
2) a regular, non-runtime exception chained to the RecordNotFoundException.
Both of these are pretty good answers, though I prefer the second. I don't think that throwing RuntimeExceptions are really the way you want to approach this. In a large sense, RuntimeException defeat the whole point of checked Exceptions, because your client can't(and shouldn't) catch them. What you're doing in throwing them, effectively speaking, is masking an explicit exception. Not really a good idea, IMO.
All best,
M
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Tony Collins:

I supose the jist of my question is that should every method you write act like a proffesionally written API as in 1 or as in 2 a bit of a bodge. And in that last sentance I think I have answered my own question.



[ July 30, 2003: Message edited by: Max Habibi ]
 
Tony Collins
Ranch Hand
Posts: 435
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Max that clears things up, not finding a record because of an IOException would be a specilisation of RecordNotFoundException. So your two options make perfect sense.

Tony
 
S Bala
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Tony,
Careful about the chaining mechanism, as my assignment says follows


Any unimplemented exceptions in this interface must all be created as member classes of the suncertify.db package. Each must have a zero argument constructor and a second constructor that takes a String that serves as the exception's description.


Max - Thanks for your help.
My initial reluctance to subclass RecordNotFoundException to capture an IOException was because, they are having different behaviors. You can only subclass if the parent class has a generic behavior. It is clearly stated that one should throw a RecordNotFoundException, if the record has been deleted, or not available (record number is not present).
Thanks,
SB
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Tony,
Careful about the chaining mechanism, as my assignment says follows
quote:
--------------------------------------------------------------------------------
Any unimplemented exceptions in this interface must all be created as member classes of the suncertify.db package. Each must have a zero argument constructor and a second constructor that takes a String that serves as the exception's description.
--------------------------------------------------------------------------------


I'm not sure I see the conflict? This
1) doesn't mean that you can't have additional constructors,
2) doesn't mean you can't use the initCause method on the parent exception.


Max - Thanks for your help.


Happy to be of service


My initial reluctance to subclass RecordNotFoundException to capture an IOException was because, they are having different behaviors. You can only subclass if the parent class has a generic behavior. It is clearly stated that one should throw a RecordNotFoundException, if the record has been deleted, or not available (record number is not present).
Thanks,
SB


Well, they do have different behaviors, but they could also have related behaviors: as Tony pointed out, if you fail to find a record because of an IOException, then you have an IORecordNotFoundException. remember, in this scenario, an IORecordNotFoundException is-a RecordNotFoundException.
All best,
M
 
Tony Collins
Ranch Hand
Posts: 435
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I understand how read/delete/update record can throw IOExceptions chained in RecordNotFoundExceptions. And I am reluctant to throw runtime exceptions for actual checked exceptions. But how do I justify throwing a DuplicateKeyExceptionException caused by an IOException in createRecord??
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Tony,
Could I see your directions? I'm @ the office
M
 
Bartender
Posts: 1872
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Max,

I guess I'm having a hard time understanding why it has it be a RuntimeException. It could
1) be a special subclass of RecordNotFoundException(say IORecordNotFoundException), or,
2) a regular, non-runtime exception chained to the RecordNotFoundException.
Both of these are pretty good answers, though I prefer the second. I don't think that throwing RuntimeExceptions are really the way you want to approach this. In a large sense, RuntimeException defeat the whole point of checked Exceptions, because your client can't(and shouldn't) catch them. What you're doing in throwing them, effectively speaking, is masking an explicit exception. Not really a good idea, IMO.


I think that we must have a tradeoff here between consistency and our reluctance for RunTimeExceptions.
OK to chain an IOException in a RecordNotFoundException. But in the DuplicateKeyException of createRecord() ? Does it make any sense ?
Now the big issue is that one of our methods throws no exception at all (public long[] findByCriteria(String[] criteria)). What to do then ? Just "eat" the IOException ? It would be bad too IMO.
The fact is that our DBAccess interface is not perfect and that impercfect worlds need tradeoffs...
Best,
Phil.
BTW, you never answered to my last reply to you in this thread. You pointed out there a so big issue that it would be great if your were willing to check it.
[ July 31, 2003: Message edited by: Philippe Maquet ]
 
Ranch Hand
Posts: 555
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi,
[Phil]

Now the big issue is that one of our methods throws no exception at all (public long[] findByCriteria(String[] criteria)). What to do then ? Just "eat" the IOException ? It would be bad too IMO


Exactly. That is why I was forced to use runtime exception. I explained in docs why.
Vlad
 
Tony Collins
Ranch Hand
Posts: 435
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Server
Required Interface
Your data access class must be called "Data.java", must be in a package called "suncertify.db", and must implement the following interface:

Any unimplemented exceptions in this interface must all be created as member classes of the suncertify.db package. Each must have a zero argument constructor and a second constructor that takes a String that serves as the exception's description.
Any methods that throw RecordNotFoundException should do so if a specified record does not exist or is marked as deleted in the database file.
Network Approaches
Your choice of RMI or serialized objects will not affect your grade, but no other approach is acceptable. 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. No authentication is required for database access.
Locking
Your server must be capable of handling multiple concurrent requests, and as part of this capability, must provide locking functionality as specified in the interface provided above. 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. Any attempt to lock a resource that is already locked should cause the current thread to give up the CPU, consuming no CPU cycles until the desired resource becomes available.
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hi Tony,

Let's take a look at our options here
#1 Swallow and Log the IO exception, and return a negative number. Document that this means that something went wrong @ the IO level.
POSITIVE: it adheres to the specification of your client. The client(Sun) has told you exactly the sorts of technical problems they want to know about, namely the DupliateKeyException, and that's exactly what you're doing.
NEGATIVE : In our opinion, the client should be notified of IO problems explicitly by throwing an IOException
#2 Chain an IO Exception into a DuplicateRecordException
POSITIVE: it adheres to the specification of your client. The client(Sun) has told you exactly the sorts of technical problems they want to know about, namely the DupliateKeyException, and that's exactly what you're doing.
NEGATIVE: intuitively, our hearts recoil at this. The IO exception didn't cause an DuplicateKeyException. Why should we say that it did?
#3 Subclass DuplicateKeyException.
POSITIVE: it adheres to the specification of your client. The client(Sun) has told you exactly the sorts of technical problems they want to know about, namely the DupliateKeyException, and that's exactly what you're doing.
NEGATIVE: intuitively, our hearts recoil at this. The IO exception didn't isn't DuplicateKeyException.
#4 Throw an unchecked exception
POSITIVE: tells the client exactly what went wrong, and doesn't technically violate the specification
NEGATIVE: violates the client's requirements De Facto, and causes a crash, because the client, by definition, cannot be prepared for an Unchecked Exception.
#5 Change the signature, and throw your own Exception
POSITIVE: tells the client exactly what went wrong
NEGATIVE: violates the client's requirements, but doesn't necessarily cause a crash, because the client can't ignore it
These are all listed in order by my sensibilities. This does not, of course, need to have any relationship with your own.
There's also a sixth option.
If you interpret the requirements religiously, then maybe Sun is trying to give you a hint on the implementation they'd like to see here. That is, maybe they're telling you there shouldn't be any IO in this method. And if that's true, maybe they expect you to add the record logically. That is, maybe they expected you to cache the db in memory, and simply add/remove from that store: thus, there's no IO. Then again, maybe not. This interpretation has it's own consequences. For example, when are you supposed to reconcile the cache with the actual file? When you exit? maybe, but it sounds like a lot to intuit from a single method's signature.
@ any rate, this is really your call . I'm just trying to help you see some of the issues that I've considered.
All best,
M
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Philippe Maquet:
Hi Max,

BTW, you never answered to my last reply to you in this thread. You pointed out there a so big issue that it would be great if your were willing to check it.
[ July 31, 2003: Message edited by: Philippe Maquet ]


Don't make me look through that whole thread again . Which post?
M
 
Tony Collins
Ranch Hand
Posts: 435
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks Max,
Your sixth option is interesting. But the db file is used by another system. We don't know what this system is or how often it runs, therefore we couldn't really assume how often the underlying database is required to be updated.
Tony
 
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 Max,
Interesting sixth option !


If you interpret the requirements religiously, then maybe Sun is trying to give you a hint on the implementation they'd like to see here. That is, maybe they're telling you there shouldn't be any IO in this method. And if that's true, maybe they expect you to add the record logically. That is, maybe they expected you to cache the db in memory, and simply add/remove from that store: thus, there's no IO.


Well, that's what I do as I implemented a write cache. But you bring me think to a seventh option :
As createRecord() may choose the place in the file where it writes (createRecord() returns the new recNo), maybe they expect the method to find a safer write place in case of IOException.
And eating the IOException in findByCriteria() then would be a little more acceptable (?)

Don't make me look through that whole thread again. Which post?


I understand you. But as it would really be off-topic to repeat it here, it's probably better to help you to find it : in page 2 of this thread, search for your words "they'll be obligated to fail you here" ( ). My first reply is just below it, and the second and last one (the solution I hope) is the sixth after it. Thank you very much !
Cheers,
Phil.
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Tony Collins:
Thanks Max,
Your sixth option is interesting. But the db file is used by another system. We don't know what this system is or how often it runs, therefore we couldn't really assume how often the underlying database is required to be updated.
Tony


Yes, but the file isn't used concurrently: thus, so long as our app is alive, we can assume sovereignty. Otherwise, we wouldn't be able to trust anything, inlcuding record numbers.
M
 
Tony Collins
Ranch Hand
Posts: 435
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
So caching the entire DB and writing it to a file when the server shutdown would free us from any worries regarding
dirty reads
IO Exceptions
reading the magic cookie every time you read the file
So no need for filechannels, eloborate exception structures and time consuming IO. Must admit it's the way I'd do it in 'Real Life' but is it in the spirit of the project? Can anyone see any way the examiner could fail a design like this?
I supose a powercut could lose you a days buissness at Bodgitt and Scarper.
Tony
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have private student get perfect scores with this design: however, they did write to file when a record was updated, thus compromising between practicality and ease.
M
 
S Bala
Ranch Hand
Posts: 49
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
But the problem still remains open. What will happen if we get an IO exception when we write to the db from the cache ?. I bet this has to be done synchronously with the client request. Otherwise we need to take it through a message queue.
How will the user know that the booking has not been done?
Or am I missing something here.
- Sb
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
not sure I understand the question: if you're executing a method that does allow an IOexception to be thrown, then you throw that IOException. If you have an error shutting down your application, then you simply log that error, as any professional grade application would.
M
 
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 Max,
I think that S Bala refers to a design which uses a write cache as you mentioned yourself when you wrote :

And if that's true, maybe they expect you to add the record logically. That is, maybe they expected you to cache the db in memory, and simply add/remove from that store: thus, there's no IO.


In this context, his question is clear to me :

What will happen if we get an IO exception when we write to the db from the cache ?


If a separate thread handles writes in the file from the write cache, an IOException cannot be thrown from its run() method. The only solution I can see is to somehow mark the given record as corrupted (in a HashSet ?), remove it from write and read caches and make sure that any attempt to further read or update it will throw the IOException (in any acceptable way discussed in previous posts).
Does it make sense ?
Best,
Phil.
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Philippe Maquet:
Hi Max,
I think that S Bala refers to a design which uses a write cache as you mentioned yourself when you wrote :

If a separate thread handles writes in the file from the write cache, an IOException cannot be thrown from its run() method. The only solution I can see is to somehow mark the given record as corrupted (in a HashSet ?), remove it from write and read caches and make sure that any attempt to further read or update it will throw the IOException (in any acceptable way discussed in previous posts).
Does it make sense ?
Best,
Phil.


I'm not sure it needs to be as complex as all that: if you decide to write to the file system when you're exiting, then catch the first IO exception, log it, and continue to shut down. It's a good faith effort, IMO. Of course, this is just one interpretation on the suggestion.
For example,. you could also decide to update the file when modify a given record(but use the cached data for searches and logical locks), in which case you can throw an IO exception in the event of problem. Or you could decide to add new records when you shut down, but work with existing records by doing Just in Time IO. There are a lot of choices here.
I guess my opinion is that this doesn't have to be an implementation problem: it can be an architectural one.
All best,
M
 
Vlad Rabkin
Ranch Hand
Posts: 555
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Hallo Tony, Max, Phil,

Here is a link:
http://www-106.ibm.com/developerworks/java/library/j-ejbexcept.html#8
You can find there following:

System exceptions: Most often system exceptions are thrown as subclasses of RuntimeException by the JVM. A NullPointerException, or an ArrayOutOfBoundsException, for example, will be thrown due to a bug in the code. Another type of system exception occurs when the system encounters an improperly configured resource such as a misspelled JNDI lookup. In this case, it will throw a checked exception. It makes a lot of sense to catch these checked system exceptions and throw them as unchecked exceptions. The rule of thumb is, if there isn't anything you can do about an exception, it's a system exception and it should be thrown as an unchecked exception.


I beleive that is the case:
What can a user do about if Remote or IO Exception happen?
The best what he down close client application and run it again (in case of RemoteException), or ask System Admin to restart the server (in case of I/O
problem on the remote server)
I know it is kind of excuse to use a un-checked exception,
I beleive the RecordNotFoundException has nothing to do with I/O problems,
it would even more confuse client developer.
Vlad
 
Tony Collins
Ranch Hand
Posts: 435
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
/*

Originally posted by Vlad Rabkin:
Hallo Tony, Max, Phil,

Here is a link:
http://www-106.ibm.com/developerworks/java/library/j-ejbexcept.html#8
You can find there following:


What can a user do about if Remote or IO Exception happen?
The best what he down close client application and run it again (in case of RemoteException), or ask System Admin to restart the server (in case of I/O
problem on the remote server)
I know it is kind of excuse to use a un-checked exception,
I beleive the RecordNotFoundException has nothing to do with I/O problems,
it would even more confuse client developer.
Vlad



Dammit, I had a lengthy reply for you, and got 503rd, so I lost it. Here's the quick gist of it.
1. The author and I just disagree where he says

The rule of thumb is, if there isn't anything you can do about an exception, it's a system exception and it should be thrown as an unchecked exception.

My opinion is that he's missing the point a bit, and contradicting himself from an earlier statement, where he says

The (EJB)spec states clearly that application exceptions should not extend RuntimeException or its subclasses.

So which are you supposed to do: extend Runtime Exception, or not? And if not, then why not? Remember, by throwing a Runtime Exception, you are 1) masking the original explicit exception that JVM demands that you deal with, and 2) forcing your clients to crash every time there's an IO problem, because they can't reasonably be expected to catch Runtime exceptions. More on this later.
Also, remember that he's really talking about how to design an EJB back end solution here, which is significant for two reasons.
1. It's a big pain in the ass in EJBs to change method signatures, so people resort to these sorts of tricks to avoid doing so.
2. EJB solutions are back-end solutions, which usually have a programmatic middle tier. Thus, as far as the client is concerned, the system is doing exactly what we talked about, which is logging the exception and returning an error message. He's just pushing that responsibility from the back end to the middle tier. There's some justification for this, though I feel that it's worthwhile for the back end to explicitly tell the client went wrong, and enforce a contract by throwing application specific exception.
OTOH, we're not in a EJB world here, nor do we have the luxury of defining exactly how the middle tier will interact with the back end: Sun's told us how they want this to occur.
Regarding forced crashed: Consider your own PC: do you really expect to have a unexpected system crash when you hit an invalid URL, or try to print a document and the printer jams? Because the principle is the same: these are both IO exceptions.
Finally, specifically in the case of RecordNotFound exception, how could you do anything but fail to find the record if there's a IO error ? IMO, an IORecordNotFound exception makes perfect sense, because it conveys both the fact that the record was not found, and that there was an IO problem.
Of course, as always, this is just my perspective on the issue: you need to weight the factors and make up your own mind.
M
 
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 Max,

if there's a IO error ? IMO, an IORecordNotFound exception makes perfect sense, because it conveys both the fact that the record was not found, and that there was an IO problem.


OK Max, you convinced me ... nearly. Because what to do then with this method which doesn't throw any checked exception ?!

Notice that that method has the highest probability (99.999999%) to be the one which will have to face a IOException while reading, as this typical scenario shows :

What to do in findByCriteria() ? Just "eat" the IO exception or throw some RuntimeException ?
Is there a third solution ? Thank you to take the whole context of this thread into account before/if replying.
Best,
Phil.
 
Max Habibi
town drunk
( and author)
Posts: 4118
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Notice that that method has the highest probability (99.999999%) to be the one which will have to face a IOException while reading, as this typical scenario shows :

What to do in findByCriteria() ? Just "eat" the IO exception or throw some RuntimeException ?
Is there a third solution ? Thank you to take the whole context of this thread into account before/if replying.
Best,
Phil.[/qb]<hr></blockquote>[/I]
Hi Phil,
I'm not trying to convince you of anything: but I am happy to talk over your options, if you like .
To the point of your question.
If you do what Vlad is doing by caching the database in memory, then there's zero probability of an IO exception. Thus, this is implementation specific probablity, not a forced one. However, that's really a side step of your question. So here's the answer.
In my opinion, what should probably happen(given the fact that Sun's interface does not allow you to throw an Exception here: which is the preferred course of action), is that the IOException should get logged, and the user should get back a failed search result: say a null. This is not the same thing as simply swallowing the exception, because I believe that log files are a necessary and valuable resource in an application. For example, my professional grade log file actually sends out a beeper message when it logs an exception. However, that's really outside of scope here . The point remains, however, that when something does break, the programmer will be looking through the logs anyway. The only questions are, did we adhere to the spec, and did the client get a warning before crashing?
IMO, If there's really a persistent IO problem, other methods will alert the user, and they'll shut down(or whatever their training manual says). If it's not persistent, then they'll do what we need them to, in that they'll try again.
M
[ August 01, 2003: Message edited by: Max Habibi ]
 
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 Max,
Thanks for your reply, I really enjoy this discussion.
You'll agree that the main (and only ?) benefit of checked exceptions over runtime ones is that compiler will enforce the programmer to catch (and handle) the former ones : the programer doesn't need to dig into your doc to check the @throws clauses and he may even be absent-minded as I am.
But, by using the exception chaining facility, we loose that benefit anyway (IMO) because if the programer catch the well-known checked exceptions defined in the interface without checking their getCause(), the application will have a quite weird behaviour to the user :
  • DuplicateKeyException caused by IO - message : "That key exists already in file. Try again with another key." (while the user knows the key is unique)
  • RecordNotFound caused by IO and thrown in updateRecord() just after a succesful read - message : "Record number " + recNo + " does not exist." (while the user knows that the record exists)


  • Now returning null from findByCriteria() in case of IOException, will lead in direct line to a NullPointerException if the programer does not pay attention to it.
    So I think we are quite far from the benefit of checked exceptions as mentioned above.
    Now that we know that the user of our Data class will have to read our doc anyway, what is easier for him to read and for us to write ?
    The DataIOException (runtime) solution :
    --------------------------------------
    In the global description of our class :

    Warning : methods which encounter a IOException throw a DataIOException (runtime). Please check the throws clauses in the detailed descriptions of methods.


    In any method description which may throw DataIOException :


    Throws DataIOException (runtime) if a java.io.IOException occurs.


    The exception chaining solution :
    -------------------------------
    In the global description of our class :


    Warning : methods which encounter a IOException chain it in one of their checked exceptions. If a method does not throw any checked exception, null is returned if a IOException occurs. So please check in the detailed descriptions of methods all exceptions mentioned in the throws clauses as well as the return clause in case no exception is thrown.


    Examples of method descriptions where a IOException may occur :
    findByCriteria() :


    Returns: an array of record numbers that match the specified criteria, or null if a java.io.IOException occurs.


    createRecord():


    Throws DuplicateKeyException if the new record violates the table primary key or if a java.io.IOException occurs. Use Exception.getCause() to distinct both cases.


    My previous question was "What is easier for the programer to read and for us to write ?".
    Asking the question is getting the answer IMO.
    Best,
    Phil.
     
    Vlad Rabkin
    Ranch Hand
    Posts: 555
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator
    Hi,
    Just one comment: in my assignement there null is definf for findbyCretireia
    for the case where nothing was found (So I will never get NullPointerException). A user will think there no records in the database, but actually there is something wroth with database...
    Vlad
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Philippe Maquet:
    Hi Max,
    Thanks for your reply, I really enjoy this discussion.


    Np, happy to help


    You'll agree that the main (and only ?) benefit of checked exceptions over runtime ones is that compiler will enforce the programmer to catch (and handle) the former ones : the programer doesn't need to dig into your doc to check the @throws clauses and he may even be absent-minded as I am.


    That, and the fact that you don't get random system crashed. Thus, you system doesn't crash because your print job failed.


    But, by using the exception chaining facility, we loose that benefit anyway (IMO) because if the programer catch the well-known checked exceptions defined in the interface without checking their getCause(), the application will have a quite weird behaviour to the user :


    Yes, if the programmer doesn't explore the exception then she won't know about it's root cause. One of the drawbacks of living in a world that allows chained exceptions is that you need to use them


  • DuplicateKeyException caused by IO - message : "That key exists already in file. Try again with another key." (while the user knows the key is unique)
  • RecordNotFound caused by IO and thrown in updateRecord() just after a succesful read - message : "Record number " + recNo + " does not exist." (while the user knows that the record exists)


  • I'm missing your point here?


    Now returning null from findByCriteria() in case of IOException, will lead in direct line to a NullPointerException if the programer does not pay attention to it.


    As oppposed to a system crash, even if the user does pay attention ? @ least this way, we're giving the user a chance if they read the documentation.


    So I think we are quite far from the benefit of checked exceptions as mentioned above.


    Well, it is your assignment, and you shouldn't do anything that doesn't seem right to you.
    All best,
    M
     
    Max Habibi
    town drunk
    ( and author)
    Posts: 4118
    • Mark post as helpful
    • send pies
      Number of slices to send:
      Optional 'thank-you' note:
    • Quote
    • Report post to moderator

    Originally posted by Vlad Rabkin:
    Hi,
    Just one comment: in my assignement there null is definf for findbyCretireia
    for the case where nothing was found (So I will never get NullPointerException). A user will think there no records in the database, but actually there is something wroth with database...
    Vlad



    Well, remember, you don't throw an Exception for the end user: you throw it for other programmers. The end user might think the everything is ok(or they might not, depending on how you code your connection tier: it could simply display a friendly message to the user in the case of a null result), but the middle tier programmer who's using(or maintaining) your system will know that something went wrong, and that's the important thing.
    This is entirely consistant with the Java way of doing things. For example, the ArrayList.add() method returns a boolean that returns true if the add was successful. If you don't check that result, then the ArrayList.add() might quietly fail. Is that the ArrayList's fault? No, IMO, it's not. The API told you have to use the method: it's up to you to do so.
    M
    reply
      Bookmark Topic Watch Topic
    • New Topic