Hmmm .. looks like my problem. I did have a "hacked" solution for it
though.
The real solution would have been to be able to throw unexpected
exceptions
(a checked exception not declared in the serviceMethod's signature) as
the Throwable in
onFailure(...). Sadly, I have not been able to do that. If anybody
knows, do tell.
Generally, I like security to be non-intrusive and this case, I don't
like to write my
method to throw an authentication exception, otherwise, every method
that needs to be
authenticated would have the "throw AuthenticationException" which is
quite tedious
and you have to write the "authentication checking code" in the method
itself, another tedious job.
My solution for this is to extend the RemoteServiceServlet, so it can
examine every RPC method
call and check if the user's role that you saved in the session has
authority to execute it, and if it has,
continue the execution, but if not, halt the execution and throw the
authentication exception.
The method to override in RemoteServiceServlet to be able to do that
is
public String processCall( String payload ) throws
SerializationException
which does the decoding of the rpc request and turns it into a Method
to be executed. From
there, you can intercept the rpc call and do the appropriate action
( to continue it or throw the
authentication exception ). The problem though is that if you throw an
unexpected exception
(a checked exception not declared in the serviceMethod's signature),
it doesn't reach the client
(maybe it can, I just don't know how.). So, the next thing to override
is
protected void doUnexpectedFailure(Throwable e)
which handles any unexpected exception, and throw a customized failure
message with enough
information as to be able to recreate the exception in the client.
This failure message will reach your
client via the "InvocationException" passed to the onFailure(...) as
the Throwable. You can then
get the message from the InvocationException, try to recreate the
"authentication exception" based
on the message. Voila, you have passed your "authentication exception"
to the client non-intrusively.
Of course, your service implementations would need to extend your
customized servlet, not the
RemoteServiceServlet.
When that exception reaches the client, it is then trivial to
implement an asynccallback that calls
the login dialog, and if it authenticates, execute the onSuccess()
part of it.
Maybe I'll write a blog about this detailing the actual solution.