When Tomcat session times out, I want to redirect my user to the homepage of my GWT app, so that they can login again. To force this, I'm trying to use the StatusCodeException thrown by GWT when the user tries to perform any operation after their session times out -
SEVERE: com.google.gwt.user.client.rpc.StatusCodeException: 0
To achieve this, I'm using the following code -
public void onModuleLoad() {
GWT.UncaughtExceptionHandler uncaughtExceptionHandler = new GWT.UncaughtExceptionHandler() {
public void onUncaughtException(Throwable e) {
if (e instanceof StatusCodeException) {
logger.log(Level.ERROR, "Exception caught!");
logger.log(Level.ERROR, ((StatusCodeException) e).getStatusCode());
}
}
};
GWT.setUncaughtExceptionHandler(uncaughtExceptionHandler);
try {
// rest of the code in onModule() - I'm expecting any operation to throw StatusCodeException when session times out.
} catch (RuntimeException ex) {
uncaughtExceptionHandler.onUncaughtException(ex);
}
}
This is not working. Instead of getting caught by the code, the StatusCodeException is being displayed on the console. What am I doing wrong here?
The idea is to catch StatusCodeException and use its getStatusCode() method to find out if the HTTP error code is 403. If it is, I want to use Window.Location.assign("https://example.com/redirect"); to redirect them to a login page.
onFailure(Throwable caught) {
logger.error(caught);
}
Your AsyncCallback.onFailure is doing exactly what you asked it to do - it is logging the error, but not throwing it. Since it wasn't thrown, the uncaught exception handler doesn't handle it (it can't be not-caught, if it wasn't thrown... if that makes sense).
One option could be that you could populate the method with throw caught, but java won't like this. Instead, the easiest answer to your specific on is simply to pass it to the handler:
onFailure(Throwable caught) {
GWT.getUncaughtExceptionHandler().onUncaughtException(ex);
}
One other option you have: since no AsyncCallback will ever throw this, putting the StatusCodeException in the UncaughtExceptionHandler seems a bit odd. Instead, consider making your own AsyncCallback base class, something like this:
public abstract class NetworkAsyncCallback<T> implements AsyncCallback<T> {
#Override
public void onFailure(Throwable t) {
if (e instanceof StatusCodeException) {
logger.log(Level.ERROR, "Exception caught!");
logger.log(Level.ERROR, ((StatusCodeException) e).getStatusCode());
}
}
}
Now, when you make a call, you just have to pass in a new NetworkAsyncCallback<T> and only implement onSuccess. You can skip onFailure if all it was going to do was pass the exceptions to the uncaught handler. Or, if you have some other logic, you can override onFailure, handle the appropriate exceptions, and call super.onFailure(caught) with any other errors so that the superclass handles it.
myServer.getSomeData(param, new NetworkAsyncCallback<Result>() {
#Override
public void onSuccess(Result result) {
//...
}
// Skip onFailure, or if you need custom logic, implement it,
// and call super only if the exception isn't part of that logic
});
Related
Good afternoon,
I'm currently working with the code from:
https://github.com/kevinsawicki/http-request
I'm attempting to refactor the code as applicable to clear all the Android Studio warnings before I include it in a project I'm working on. Currently I'm working with the following nested abstract class:
///////////////////////////////////////////////////////////////////////////////////////////////
protected static abstract class Operation<V> implements Callable<V> {
protected abstract V run() throws HttpRequestException, IOException;
protected abstract void done() throws IOException;
public V call() throws HttpRequestException {
Log.d(TAG, "in HttpRequest nested class Operation call");
boolean thrown = false;
try {
return run();
} catch (HttpRequestException e) {
thrown = true;
throw e;
} catch (IOException e) {
thrown = true;
throw new HttpRequestException(e);
} finally {
try {
done();
} catch (IOException e) {
if (!thrown) {
throw new HttpRequestException(e);
}
}
}
}
} // end Operation
This is producing the following warning for having a throw inside a finally block:
I've been looking at this for a while but I can't seem to find a way to factor out this warning. I did see this other answer:
throws Exception in finally blocks
However I would really prefer to not introduce another function. If I was to introduce a closeQuietly function, would that go inside or outside the nested class listed above? Please advise, thanks!
It's just a warning. If you read the explanation it says (emphasis mine)
While occasionally intended, such throw statements may mask exceptions thrown and tremendously complicate debugging.
If you need to do it, then do it, but just make sure it's actually what you want to do and understand the implications (it's akin to saying "do you really want to do this?!"). Not all of IntelliJ's warnings can be eliminated.
Edit based on follow up: You have to ask yourself if your framework needs to throw that exception in the finally block. You can implement a similar approach to what was linked without using another function (just replace the throw statement in finally with a log statement), but that might not be desirable. It depends entirely on the potential error conditions.
If, for example, you're expecting done() to run into issues whenever you've previously received an IOException or an HttpRequestException then you probably don't need to throw anything in the finally block (just log it). But, if you need to make sure you alert the user if something went wrong trying to clean up, then you do need to throw there and you should ignore the warning.
I suppose you could do something like this:
protected static abstract class Operation<V> implements Callable<V> {
protected abstract V run() throws HttpRequestException, IOException;
protected abstract void done() throws IOException;
public V call() throws HttpRequestException {
Log.d(TAG, "in HttpRequest nested class Operation call");
boolean thrown = false;
try {
return run();
} catch (IOException e) {
throw new HttpRequestException(e);
} finally {
try {
done();
} catch (IOException e) {
// handle the IOException
}
}
}
} // end Operation
If an HttpRequestException is ever thrown it'll be thrown by the method, you still transform the IOException into an HttpRequestException (not quite sure why you want to do that), and in the finally block you would need to catch and handle the IOException appropriately.
I understand the basic try-catch, where we put methods that could possibly throw exceptions in the try block. But when we need to check if something is wrong, and throw an exception, is it correct to use the code below? And the exception is caught, the program will continue to execute?
I can't tell why the try is needed here, but without it eclipse says 'syntax error'. Thanks for your help in advance!
public run (){
if (something !=true) {
try{
throw new Exception();
}catch (Exception e){
}
Yes that is correct. You have to use try since that is where the exception-throwing code is entered and where exceptions are caught (just using a catch block won't serve any purpose)
Generally speaking, exceptions are used to let the calling code handle errors in your method.
If you just want to handle the error in run, you don't need exceptions:
public void run() {
if (something != true) {
// handle it
}
}
If you want the calling code to handle the error instead, this is where you need exceptions:
public void run() throws Exception {
if (something != true) {
throw new Exception();
}
}
And where you call run, use a try/catch block:
try {
run();
} catch (Exception e) {
// handle it
}
It is also recommended that you don't throw an Exception instance, use a custom subclass instead.
I have all the logic in place to check if a user is logged in and therefore is allowed to execute a RPC call. I can place this check in all my RPC methods and throw a throw new MyLoginException() if the user is not logged in. In the client side I just check for this exception and handle it accordingly.
The problem now is: I don't want to put this in every RPC method. I want a generic solution for this.
I tried to override methods like com.google.gwt.user.server.rpc.RemoteServiceServlet.processCall() which is called before every RPC call. Problem here: I can only throw unchecked exception because the method signature does not allow me to throw my own exception. The unchecked exception result then in generic exception in the client code and I can not handle them correctly because I do not know anymore which exception was thrown.
Where can I put my login check? Is there any clean solution for this problem?
I found the solution in the link posted by Baz: https://groups.google.com/forum/#!topic/google-web-toolkit/D2MPaD2EpOQ
Instead of throwing the exception like this (Which is not possible since the signature only allows SerializationException :
#Override
public String processCall(String payload) throws SerializationException {
if(!userIsAuthorized()){
throw new MyAuthorizationException();
}
return super.processCall(payload);
}
The exception has to be returned encoded in the response like this:
#Override
public String processCall(String payload) throws SerializationException {
if(!userIsAuthorized()){
return RPC.encodeResponseForFailure(null, new MyAuthorizationException());
}
return super.processCall(payload);
}
This will be called every time a RPC call is invoked and the method will not be executed if the user is not authorized and the checked exception will be transported to the front end where it can be handled accordingly.
Edit #Baz: This is how the client handling looks like for me. But I think if you get a IncompatibleRemoteServiceException you have a problem that some old stuff is cached in your browser und you need to clean your cache.
#Override
public void onFailure(Throwable caught) {
try {
throw caught;
}
catch (SessionExpiredException ex){
onSessionExpired();
}catch(Throwable e){
MyCallback.this.onFailure(e);
}
}
This is what I have:
#Test
public testSendMessageToStub() {
// under the hood sends message
// if exception occurrs
// it will be catched and message will be put on retry
object.sendMessage();
}
Is there any way to mark test as failed if exception has occurred but was handled in catch block in the sendMessage() method?
Thanks
EDIT: It seems like I was too fixated on these legacy tests and how they were used, that totally missed the fact of sendMessage returning a response with a status code (!!!). So now I just assert status codes, can expand these tests into more detailed scenarios and spin them on jenkins. I would like to avoid to answer how these tests were checked previously. The thought to check for status codes came to me after reading Plux's answer. Thanks!
Exactly what you are looking for is not possible with JUnit as far as I know.
If you really would want to test this, you could store some information about the exception in the catch-block where it is handled in the sendMessage() method.
A better option, in my opinion, could be to test the output or state of the object. If the state/output is exactly the same as when an exception doesn't occur, then whats the point of testing it? Do you have an overly broad catch-block?
EDIT: To AdityaTS, I dont have enough reputation to comment on a post, but my comment: you have not supplied all the code, so I can not say for sure, but my guess is that its the Logger.getLogger IN the catch-block that casts the ClassNotFoundException. (Either that or loadConnectionInfo()) see http://docs.oracle.com/javase/7/docs/api/java/lang/ClassNotFoundException.html
You cannot do this without modifying sendMessage method. If for example you catch the exception there but choose to ignore it and just return some value, code outside of the method doesn't know it. You can get around this by refactoring the code of object: move the code that handles the exception to a separate method, called e.g. handleException. Then, in your test you can create a subclass where handleException will execute the original handleException from superclass, but additionally set some flag which you will be able to read in your test and in this way tell that the exception was thrown. However, if you cannot modify the code for object's class, I'm afraid you're out of luck.
So you expect the exception to propagate out of the sendMessage() method, right?
This is another way to write a test that verifies an exception you expect will be thrown.
#Test (expected = MyExpectedException.class)
public testSendMessageToStub() {
// under the hood sends message
// if exception occurrs
// it will be catched and message will be put on retry
object.sendMessage();
}
And it's usually best to be as specific as possible (e.g. MyExpectedException.class over Exception.class)
The exception generated in the sendMessage() class will be available in the test method. Add a try catch block around the sendMessage() method like this
#Test
public testSendMessageToStub() {
try
{
object.sendMehssage();
}
catch(Excpetion e) //Use more specific exception type if you know
{
fail(e.getMessage());
}
}
I have tried this in my code. It worked for me. Let me know.
public DBConnectionInfo connectionInit()
{
loadConnectionInfo();
try
{
Class.forName(dbObject.getDriver());
} catch (Exception e)
{
Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
lgr.log(Level.SEVERE, e.getMessage(), e);
}
try
{
dbObject.setConnection(DriverManager.getConnection(dbObject.getDatabaseURL(), dbObject.getUserName(),
dbObject.getPassword()));
} catch (Exception e)
{
Logger lgr = Logger.getLogger(PostgreLocationManager.class.getName());
lgr.log(Level.SEVERE, e.getMessage(), e);
}
return dbObject;
}
The test case for the above class.
#Test
public void testDriverFailure()
{
when(dbModelObject.getDriver()).thenReturn("driver");
when(dbModelObject.getDatabaseURL()).thenReturn("jdbc:postgresql://127.0.0.1:5432/testdb");
when(dbModelObject.getUserName()).thenReturn("postgres");
when(dbModelObject.getPassword()).thenReturn("postgres");
try
{
dbConnector.connectionInit();
} catch (Exception e)
{
assertTrue(e instanceof ClassNotFoundException);
}
verify(dbModelObject).getDriver();
}
I want to override the global Exception Handling in my RCP app. Whenever an uncaught Exception happens I want to log it (using java logging) and then exit the app. I have already overwritten the eventLoopException(Throwable exception) method in the ApplicationWorkbenchAdvisor class. But this catches only the event loop exceptions. As of now I have also overwritten the postStartup() method like this:
public void postStartup()
{
Policy.setStatusHandler(new StatusHandler()
{
#Override
public void show(IStatus status, String title)
{
LOGGER.log(Level.SEVERE, "Uncaught Exception", status.getException());
UnexpectedErrorDialog();
PlatformUI.getWorkbench().close();
}
});
}
It logs the exception in my log file and exits the app. But it's obviously not right and the exception is shown twice in the console, cause all I do is intercepting the showing of the exception in a gui dialog to the user. So how can I properly overwrite/change the global exception handling, so that my code (log) is used instead of the default one?
I would suggest you to use org.eclipse.ui.statusHandlers extension point
Thanks to sambi reddy's tip i have now overwritten AbstractStatusHandler in the ApplicationWorkbenchAdvisor class
#Override
public synchronized AbstractStatusHandler getWorkbenchErrorHandler() {
if (myStatusHandler == null) {
myStatusHandler = new MyStatusHandler();
}
return myStatusHandler;
}
MyStatusHandler extends AbstractStatusHandler and i have overwritten the handle method like this:
#Override
public void handle(StatusAdapter statusAdapter, int style)
{
if(statusAdapter.getStatus().matches(IStatus.ERROR) && ((style != StatusManager.NONE)))
{
LOGGER.log(Level.SEVERE, "Uncaught Exception", statusAdapter.getStatus().getException());
UnexpectedErrorDialog();
PlatformUI.getWorkbench().close();
}
}
seems to work right, only downside is that i still get 2 console outputs.