0

Scenario:

For a web-site which requires registration based on user id, the user id must be unique. Lets say a user has attempted to register with 'foo' user id, which already exists (with other required fields). Now, without using checked exceptions (database API will throw SQLException for duplicate insert), I wonder how advocates of unchecked exception handle this situation and intimate to the user that the id was already chosen?

Let's say this web-site is on Struts (no no, I'm not working on a project, it's just that I understand it better). User submits filled information to Struts Action which calls DAO to insert new record. So, ultimately, DAO will issue INSERT statement which will fail. So, if Action (calling DAO) does not explicitly handle this situation (DAO method may just declare that it throws SQLException or method may catch SQLException and throw a business-checked-exception like DuplicateUserIDExceptoion which extends Exception), how can this be handled with unchecked exception?

Bottom line - I read many articles stating that Java does not require checked exceptions so, this scenario will help me understand it better, I hope. Please do not point to articles as I had read many, many and I'm really very confused. The best way you can help me is by providing answer to the above scenario.

Note: I do understand that any recoverable exceptional scenario must be handled by a checked exception (which I have been implementing in my projects) but, I'm really confused by un-checked exception ONLY advocates. How do you people handle above scenario?

Thanks in advance.

user1418717
  • 425
  • 2
  • 5
  • 13

2 Answers2

4

An unchecked exception can be caught exactly as a checked exception is. I would use the following to handle such a case:

  1. Check if the user ID already exists. If so, throw a checked DuplicateUserIdException. I think a checked exception makes more sense here. But you could also make the exception a runtime one, and catch it in the presentation layer as you would catch a checked exception
  2. insert the user. If a SQLException occurs, it's not easy at all to be sure that it's precisely due to an already existing user ID. Plus the constraint could be checked at commit time if deferred. This exception would only occur in case of a race condition between two threads, and should thus be very seldom. So I would treat it like a technical runtime exception and display a generic error message.
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Most DB abstraction frameworks will convert vendor-specific errors into typed exceptions for you so I would probably skip the query. – David Harkness May 30 '12 at 17:35
  • And what if the constraint is deferred? What if the process involves inserting 100 lines in 8 tables? How do you know which insertion causes the ConstraintViolationException, and which constraint is violated? – JB Nizet May 30 '12 at 17:37
  • Separate the process into two transactions: one that does the minimal work to create the user with the requested ID and another that builds the related information. – David Harkness May 30 '12 at 17:41
  • And you throw ACIDity through the window. No thank you. I prefer my database to contain consistent data. – JB Nizet May 30 '12 at 17:44
  • If you *cannot* split that operation into two valid transactions, then of course you're stuck. We are, however, talking about registering a user here. This doesn't typically require creating an order or credit card or history or the myriad other things that get attached to the user over time. It requires a single row in the `users` table. – David Harkness May 30 '12 at 18:50
  • @JBN, DH and Jeshurun, Thanks much for your inputs. As I had stated in subject (I'm not concerned about how to persist/handling transactions), I'm interested to learn about how to handle exceptional situations with runtime/un-chechked exceptions ONLY because, as stated earlier, I found many advocates of same on SO and other sites. So, I'm yet to see a point to implement the same. The OP scenario is just to demonstrate that of an exceptional situation and how to handle with runtime/un-chechked exceptions ONLY. – user1418717 May 31 '12 at 01:49
  • @JBN, My take away point is your statement '...could also make the exception a runtime...'. There's big difference and few advantages of using checked over un-checked exception in above situations. First, it clearly states to client that, it must be ready to handle exception, clearly documents method contract which helps in all future client-coders too and big advantage of compile time check. So, given OP scenario, exception must be thrown to client either as checked or un-checked. Given advantages of checked exceptions, why would runtime exception ONLY advocates use even in these scenarios? – user1418717 May 31 '12 at 01:57
  • I don't know. I'm not one of those advocates. A checked exception is the right thing to use in this case. But the SQLException should be a runtime exception (BTW, JPA only uses runtime exceptions) – JB Nizet May 31 '12 at 05:50
  • I too agree, checked exception is more apt in these OP kind of scenarios. Interesting to note your statement - '...SQLException should be a run-time exception..', please help me understand as to why do you think so? If I'm correct, even Hibernate and Spring DAOs favor run-time exceptions, need to test how these technologies handle OP scenario... – user1418717 May 31 '12 at 06:27
0

How about starting a transaction, querying the database to check if the id exists, if it doesn't, perform the insert, and then committing the transaction? If it does exist, tell the user the id already exists. Even better, you could perform the check on blur of the username field in the form as an ajax request and indicate to them that it is already taken. Why do you want to rely on a database exception to determine if the id exists or not?

Jeshurun
  • 22,940
  • 6
  • 79
  • 92