• 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

How should I handle this exception?

 
Ranch Hand
Posts: 74
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I have a class that implements ServletContextListener. The method contextInitialized(ServletContextEvent sce) is implemented so that when the context is initialized the application will load property values from a property file, like so:



So loadProperties() will examine a properties file and load all the property values from the file into a Properties object. It will put this Properties object in the ServletContext, so that the properties are made available throughout the application. If the properties file is not found anywhere, loadProperties() throws a FileNotFoundException. The contextInitialized() method catches the IOException, and simply logs the error. However the contextInitialized() method doesn't declare an exception, so I cannot rethrow another exception indicating that the property file is missing. I was thinking of wrapping the IOException and throwing a RuntimeException, because it is an unchecked exception, but it just doesn't seem like the right thing to do since you'd normally throw RuntimeExceptions for programming errors, whereas this is something that you can recover from, hence a checked exception is more appropriate.

What do others think??? Obviously if the properties object isn't set in the context, the application won't have properties values and will need to be reloaded through another context initialization.
 
Author and all-around good cowpoke
Posts: 13078
6
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I would probably throw a javax.servlet.UnavailableException with an informative message.

Bill
 
Aaron John
Ranch Hand
Posts: 74
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by William Brogden:
I would probably throw a javax.servlet.UnavailableException with an informative message.

Bill



How can I throw this type of Exception, if the method doesn't allow any exceptions to be declared in the method signature?
 
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
You can't. You can only throw some kind of RuntimeException, or an Error. I would usually prefer to make a custom subclass of RuntimeException, so that anyone who wants to catch it can catch it without accidentally catching other RuntimeExceptions like NullPointerException.

However, does throwing an exception here make a difference? It's not clear to me from the specification that throwing an exception in the listener will stop the servlet from being instantiated. It's possible that notification could happen in a separate thread from the servlet instantiation. You might simply prevent any other listeners from beign notified. The fact that there's no checked exception declared by the method means that other components aren't expecting any exception to be thrown here. You can't really be sure how they'll react. I recommend testing this to see - what happens if you throw an exception here? Be aware, though, that the result you get may depend on your web server. (Or maybe it's well-defined in a spec somewhere; I don't really know.)

In general, yes there are times when there is really no point in proceeding after an exception. And in this cases, it may be a valid option to convert the exception to some kind of RuntimeException, or even Error. But be aware that this may not have the desired effect - try it and see. It may be that the best you can do is log the error, and solve the problem when someone looks at the log.

Another possibility you might consider is to use setAttribute() to set some sort of flag in the context. Then the servlet could later retrieve this in the init() method to understand why it's not working. The init() method can then throw UnavailableException to signal that the servlet was never initialized. In fact, the way you've got it written, you don't need any extra flag. Just check if the applicationProperties attribute is null - if it is, then something went wrong in the listener, before the properties got loaded and put in the context.

Having said that though, why not load the properties in the init() method, rather than the ServletContextListener? That way, you can easily throw the UnavailableException in a place where it's expected, where the container will be able to take appropriate action.
[ January 23, 2008: Message edited by: Jim Yingst ]
 
Sheriff
Posts: 67746
173
Mac Mac OS X IntelliJ IDE jQuery TypeScript Java iOS
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Since a context listener is invoked outside the scope of any particular servlet, and called prior to any servlets being loaded, it wouldn't make much sense to throw an UnavailableException (even if you could).

I tend to do something along the lines of what Jim suggested. The purpose of my context listeners is generally to set up something (or somethings) in the application context for the rest of the app, including servlets, to use. If loading fails, I log the problem and quietly move along. When the servlet init methods start firing at a later time, any servlet that depends upon this info will check if it is there or not. If not, it logs the problem and it throws an UnavailableException to prevent the servlet from being put into service.

When that happens I can check the logs to see the source of the problem.
 
Aaron John
Ranch Hand
Posts: 74
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Originally posted by Jim Yingst:
You can't. You can only throw some kind of RuntimeException, or an Error. I would usually prefer to make a custom subclass of RuntimeException, so that anyone who wants to catch it can catch it without accidentally catching other RuntimeExceptions like NullPointerException.

However, does throwing an exception here make a difference? It's not clear to me from the specification that throwing an exception in the listener will stop the servlet from being instantiated. It's possible that notification could happen in a separate thread from the servlet instantiation. You might simply prevent any other listeners from beign notified. The fact that there's no checked exception declared by the method means that other components aren't expecting any exception to be thrown here. You can't really be sure how they'll react. I recommend testing this to see - what happens if you throw an exception here? Be aware, though, that the result you get may depend on your web server. (Or maybe it's well-defined in a spec somewhere; I don't really know.)

In general, yes there are times when there is really no point in proceeding after an exception. And in this cases, it may be a valid option to convert the exception to some kind of RuntimeException, or even Error. But be aware that this may not have the desired effect - try it and see. It may be that the best you can do is log the error, and solve the problem when someone looks at the log.

Another possibility you might consider is to use setAttribute() to set some sort of flag in the context. Then the servlet could later retrieve this in the init() method to understand why it's not working. The init() method can then throw UnavailableException to signal that the servlet was never initialized. In fact, the way you've got it written, you don't need any extra flag. Just check if the applicationProperties attribute is null - if it is, then something went wrong in the listener, before the properties got loaded and put in the context.

Having said that though, why not load the properties in the init() method, rather than the ServletContextListener? That way, you can easily throw the UnavailableException in a place where it's expected, where the container will be able to take appropriate action.

[ January 23, 2008: Message edited by: Jim Yingst ]



Yeah I guess that makes sense. The reason I didn't put it in my init() method is because I have more than one servlet, and all these servlets use the same properties. I'd like to avoid loading properties inside init() as this will lead to duplicate code across servlets, so I thought loading the properties and setting it in the context (where it is global) using a ServletContextListener would enable all servlets to access these properties.

Is this a better approach or does this lead to other problems?
 
Bear Bibeault
Sheriff
Posts: 67746
173
Mac Mac OS X IntelliJ IDE jQuery TypeScript Java iOS
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

The reason I didn't put it in my init() method is because I have more than one servlet, and all these servlets use the same properties.

This is a good reason. With all due respect to Jim, I would under no circumstances put application initialization code into a particular servlet's init() method. That's an artifact of the past before context listeners came onto the scene.
[ January 23, 2008: Message edited by: Bear Bibeault ]
 
Jim Yingst
Wanderer
Posts: 18671
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Yup, makes sense. I wasn't thinking that though - I was thinking it was just used by one servlet. Silly of course.
 
Aaron John
Ranch Hand
Posts: 74
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
Thanks for the suggestions. Here's what I think I'll do. I'll make my ServletContextListener implementation simply log an error if it can't load properties from the property file. Then once it is time for Servlet initialisation, in my init() methods for each of my Servlets, I'll check whether the Properties object is set in the context. If not, then I'll throw an UnavailableException() to the container.

Also in the contextInitialized() method, instead of throwing a RuntimeException, I thought about throwing a MissingResourceException, which is a subclass of RuntimeException. But I think throwing a checked exception is more "correct" in this case.
 
Wanna see my flashlight? How about this tiny ad?
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com
reply
    Bookmark Topic Watch Topic
  • New Topic