How to throw exceptions for the init() method for servlets
Asked Answered
P

3

5

well I'll first show my code:

@Override
public void init() throws ServletException {
    super.init();

    try {
        securityController = SecurityControllerFactory.getInstance().create();
    } catch (Exception e) {
        System.err.println("Error creating security controller; " + e.getMessage());
    }

    // max allowed uploaded uploadedFile size is 10 MB
    maxFileSize = getBytes(10);
    maxMemSize = getBytes(2);
}

As you can see the compiler is forcing me to use try/catch for instantiating the SecurityController. In my case however I believe it should stop instantiating the Servlet and throw an exception in general if the security controller can't be instantiated. Any suggestions/explanations to this?

Puttee answered 30/4, 2013 at 1:2 Comment(1)
Why not re-throw the exception?Batting
C
8

Carefully read the javadoc of init() method:

init

public void init() throws ServletException

...

Throws:

ServletException - if an exception occurs that interrupts the servlet's normal operation

Look there, you're supposed to rethrow it as ServletException. Conform chapter 2.3.2.1 of the Servlet API specification, the servlet will not be placed in service:

2.3.2.1 Error Conditions on Initialization

During initialization, the servlet instance can throw an UnavailableException or a ServletException. In this case, the servlet must not be placed into active service and must be released by the servlet container. The destroy method is not called as it is considered unsuccessful initialization.

...

Thus, just do what the docs state (this is the normal process, by the way, you should as being a Java beginner understand/realize that very good):

@Override
public void init() throws ServletException {
    try {
        securityController = SecurityControllerFactory.getInstance().create();
    } catch (Exception e) {
        throw new ServletException("Error creating security controller", e);
    }

    maxFileSize = getBytes(10);
    maxMemSize = getBytes(2);
}

Please note that I removed the unnecessary super.init() call. The javadoc isn't telling anywhere that you're required to do that for init(), only for init(ServletConfig).


Unrelated to the concrete problem, having an overly generic catch on Exception is considered poor practice. You certainly don't want to cover RuntimeExceptions with your overly generic catch on Exception as that may unintentionally hide away programmer's mistakes/bugs.

You should try to be as specific as possible in your catch, try to catch as specific as possible the exception(s) being declared in throws of those methods. For example:

    try {
        securityController = SecurityControllerFactory.getInstance().create();
    } catch (SecurityControllerCreationException e) {
        throw new ServletException("Error creating security controller", e);
    }

Another cause could also be that the methods in question are so badly designed that they are by themselves declared as throws Exception. You should in turn fix that part as well.

Cochineal answered 30/4, 2013 at 2:43 Comment(0)
R
3

Or you can wrap them in a ServletException:

try {
    securityController = SecurityControllerFactory.getInstance().create();
} catch (Exception e) {
    throw new ServletException ("Failed to create controller.", e);
}

However it's not good form to just catch Exception, you should be catching just the specific one that is thrown by the create method.

Resistant answered 30/4, 2013 at 1:19 Comment(2)
Hmm, what exactly do you mean by saying this is not a good form that you demonstrated? The create() method throws it's exceptions so they will probably be visible too, right? But in this case we just need to throw something critical to stop the Servlet from further initialising, right? Can you explain?Puttee
Normally classes don't throw an instance of the base class Exception, but rather a more specific subclass like ClassNotFoundException, IOException, etc, which give you more information. So in the catch block you would declare that you are just catching that exception. And as you said in this case by wrapping the thrown Exception with a ServletException you will stop the Servlet from loading.Resistant
P
-1

If you really want to throw them you can throw a runtime exception:

try {
   //do stuff
} catch (Exception e) {
   throw new RuntimeException("There was an exception initializing the servlet:  ", e);
}
Polyphyletic answered 30/4, 2013 at 1:17 Comment(5)
ServletException would have been a much better choice.Katheleenkatherin
Oh well you could always fix it.Katheleenkatherin
@EJP I would, but two other people already have that answer. No real point. With the -1, I don't think anybody is going to be confused as to which approach to use. It's nice to have a record of your mistakes, don't you think? And anyway, there are really only two possible ways to solve the problem here, and even though my answer might not be the preferred approach, it still technically works. There is nothing special about a SerlvetException either really, it's just a convenience class provided. It's not actually important for the exception to be checked, though, because the servlet isPolyphyletic
container managed, i.e. it's not being called by any other code that is going to need be informed to handle the checked exception. It really just doesn't matter.Polyphyletic
Well I'm also glad about this answer, it was useful because this case is more general, I can probably use it everywhere else if I encounter a similar situation to this, even though it may not be the best suited for particular one. Thanks!Puttee

© 2022 - 2024 — McMap. All rights reserved.