41

In the @PostConstruct doc it says about the annotated methods:

"The method MUST NOT throw a checked exception."

How would one deal with e.g. an IOException which can be thrown in such a method? Just wrap it in a RuntimeException and let the user worry about the faulty initial state of the object? Or is @PostConstruct the wrong place to validate and initialize objects which got their dependencies injected?

skaffman
  • 398,947
  • 96
  • 818
  • 769
fasseg
  • 17,504
  • 8
  • 62
  • 73
  • Interesting, I hadn't noticed that. Seems like an odd restriction, given that the method is called reflectively. – skaffman Jan 05 '12 at 09:41
  • `PostConstruct` method is for initializing objects. Why would you put something that throws `IOException` in an initialize method? – mohdajami Jan 05 '12 at 09:41
  • 2
    @Medopal: I'm checking for the existence of DB tables in the init method of a service, which throws IOException – fasseg Jan 05 '12 at 09:43
  • 2
    @medopal redirecting or sending an HTTP error code also throw `IOException` – Elias Dorneles May 22 '12 at 19:18
  • Is this constraint mostly from a philosophical viewpoint as in Exception must not be thrown while initializing objects or there is a bigger practical issue attached to it? I didn't fully understand this part why PostConstruct must not throw a checked exception – comiventor Mar 23 '18 at 09:02

3 Answers3

51

Yes, wrap it in a runtime exception. Preferebly something more concrete like IllegalStateException.

Note that if the init method fails, normally the application won't start.

Bozho
  • 588,226
  • 146
  • 1,060
  • 1,140
5

Generally, if you want or expect application start-up failure when one of your beans throws an exception you can use Lombok's @SneakyThrows.

It is incredibly useful and succinct when used correctly:

@SneakyThrows
@PostConstruct
public void init() {
    // I usually throw a checked exception
}

There's a recent write-up discussing its pros and cons here: Prefer Lombok’s @SneakyThrows to rethrowing checked exceptions as RuntimeExceptions

Enjoy!

wild_nothing
  • 2,845
  • 1
  • 35
  • 47
  • 1
    You can have similar effect without using Lombok. Assuming you throw `SomeCheckedException` in your `init` method you could write `public void init() throws SomeCheckedException {` and result should be the same as with Lombok `@SneakyThrows`. – luke Dec 31 '20 at 08:02
0

Use a softened exception like so, in effect wrapping in RuntimeException:

private static RuntimeException softenException(Exception e) {
    return new RuntimeException("Softened exception.", e);
}

Then usage is like:

} catch (IOException e) {
        throw softenException(e);
}
djangofan
  • 28,471
  • 61
  • 196
  • 289
  • How can this work? From what I see, you cannot just take an arbitrary exception and cast it to a `RuntimeException`. Sure the code will compile, but have you tried running this on the said `IOException`? I'm pretty sure you'll get a `ClassCastException` due to the fact that `IOException` does not inherit from `RuntimeException`. To truly get a `RuntimeException` you have to wrap the original exception in a new instance of `RuntimeException` or a subclass of choice. – inkassso Oct 31 '22 at 12:51
  • Yeah, my code doesn't work right, but hopeully the basic idea, as you can see, is possible. – djangofan Nov 03 '22 at 21:12