I have following code using hibernate to throw a custom exception on error and I also want to close the session in this case, since the exception won\'t be catched unless receiv
While closeSessionAndThrow always throws the remote exception, the compiler doesn't dive into the method to find that out, therefore the compiler only knows that it COULD throw a RemoteException, not that it WILL. I would maybe do something like this:
public RemoteException closeSessionAndThrow(final Session session, final Exception e, String msg)
{
SessionManager.logger.log(Level.SEVERE, msg, e);
this.closeSession(session);
return new RemoteException(msg);
}
public <T> T get(final Session session, final String queryName) throws RemoteException
{
final Query query = // query using given session ...
try
{
return (T) query.uniqueResult();
}
catch (final HibernateException e)
{
throw this.closeSessionAndThrow(session, e, "Could not retrieve Data");
}
}
add finally to try-catch block finally { return null; } - If execution goes into try block and result is success it would return, so finally would never get executed. - If execution goes into catch block, the finally block gets executed after catch and would return null. Safe execution!
Not correct answer!
This is the problem with methods like closeSessionAndThrow
. The JLS rules do not allow the compiler to infer that since the method unconditionally throws an exception it can never return normally. The calling code therefore has to be written as if the method could return ... even though "we know" it cannot happen.
You simply have to go with the flow. This is an "unusual" control pattern that the Java language doesn't support as well as you / we would like.
(Under certain circumstances, one can prove that the method will always throw an exception under certain assumptions. However, since the method is public
and in a different class, one of the assumptions is that the classes that define and use the method won't be changed and compiled independently of each other. Of course, that is not the kind of assumption that a compiler can make ... and it partly explains why the JLS rules don't attempt to cover this pattern.
If they were to "fix" this problem, it would require something like an annotation, or change to the java syntax to declare that the helper method cannot return.)
Since this method must return something, you should put a return null;
after
this.closeSessionAndThrow(session, new RemoteException("Could not retrieve Data"));
but still within the catch
clause or use a finally
clause.
Why do you need to do this? Because your function must return something. and since one it returns from:
this.closeSessionAndThrow(session, new RemoteException("Could not retrieve Data"));
and doesn't return anything, this causes a compiler error.
Change the declaration of closeSessionAndThrow
to return RemoteException
and then "throw" the return result of calling it in your client code.
public RemoteException closeSessionAndThrow( ... ) // <-- add return type here
throws RemoteException { ... }
public <T> T get( ... ) throws RemoteException
{
try { ... }
catch (final HibernateException e)
{
throw this.closeSessionAndThrow( ... ); // <-- add "throw" here
}
}
This tricks the compiler into thinking it will always throw whatever exception is returned from closeSessionAndThrow
. Since the helper method throws that exception itself, this second throw
never comes into play. While you could return the exception from the helper, this invites error when someone forgets to add throw
before the call.