Improved exception handling for 301, null response body and connection issues

This commit is contained in:
Rohit Awate 2018-02-11 22:26:33 +05:30
parent 6f9fba2c51
commit bc3c576dc6
5 changed files with 172 additions and 86 deletions

View file

@ -17,6 +17,7 @@ package com.rohitawate.restaurant.dashboard;
import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXSnackbar;
import com.rohitawate.restaurant.exceptions.UnreliableResponseException;
import com.rohitawate.restaurant.models.requests.DELETERequest;
import com.rohitawate.restaurant.models.requests.DataDispatchRequest;
import com.rohitawate.restaurant.models.requests.GETRequest;
@ -37,13 +38,12 @@ import javafx.scene.layout.BorderPane;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javax.ws.rs.ProcessingException;
import javax.ws.rs.core.Response;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.ConnectException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;
import java.util.List;
import java.util.ResourceBundle;
@ -115,6 +115,9 @@ public class DashboardController implements Initializable {
snackBar = new JFXSnackbar(dashboard);
bodyTab.disableProperty().bind(Bindings.and(httpMethodBox.valueProperty().isNotEqualTo("POST"),
httpMethodBox.valueProperty().isNotEqualTo("PUT")));
errorTitle.setText("Oops... That's embarrassing!");
errorDetails.setText("Something went wrong. Try to make another request.\nRestart RESTaurant if that doesn't work.");
}
@FXML
@ -166,13 +169,18 @@ public class DashboardController implements Initializable {
});
requestManager.setOnFailed(e -> {
loadingLayer.setVisible(false);
errorLayer.setVisible(true);
Throwable exception = requestManager.getException().getCause();
promptLayer.setVisible(false);
Throwable exception = requestManager.getException();
if (exception.getClass() == UnknownHostException.class) {
errorTitle.setText("No Internet Connection");
errorDetails.setText("Could not connect to the server. Please check your connection.");
if (exception.getClass() == UnreliableResponseException.class) {
UnreliableResponseException URE = (UnreliableResponseException) exception;
errorTitle.setText(URE.getExceptionTitle());
errorDetails.setText(URE.getExceptionDetails());
} else if (exception.getClass() == ProcessingException.class) {
errorTitle.setText("RESTaurant couldn't connect.");
errorDetails.setText("Either you are not connected to the Internet or the server is offline.");
}
errorLayer.setVisible(true);
requestManager.reset();
});
requestManager.start();
@ -213,11 +221,19 @@ public class DashboardController implements Initializable {
});
requestManager.setOnFailed(e -> {
loadingLayer.setVisible(false);
promptLayer.setVisible(true);
if (requestManager.getException().getClass() == ConnectException.class)
snackBar.show("Request timed out. Server is unavailable or didn't respond.", 10000);
else if (requestManager.getException().getClass() == FileNotFoundException.class)
promptLayer.setVisible(false);
Throwable exception = requestManager.getException();
if (exception.getClass() == UnreliableResponseException.class) {
UnreliableResponseException URE = (UnreliableResponseException) exception;
errorTitle.setText(URE.getExceptionTitle());
errorDetails.setText(URE.getExceptionDetails());
} else if (exception.getClass() == ProcessingException.class) {
errorTitle.setText("RESTaurant couldn't connect.");
errorDetails.setText("Either you are not connected to the Internet or the server is offline.");
} else if (exception.getClass() == FileNotFoundException.class)
snackBar.show("File could not be found.", 5000);
errorLayer.setVisible(true);
requestManager.reset();
});
requestManager.start();
@ -253,13 +269,18 @@ public class DashboardController implements Initializable {
});
requestManager.setOnFailed(e -> {
loadingLayer.setVisible(false);
errorLayer.setVisible(true);
Throwable exception = requestManager.getException().getCause();
promptLayer.setVisible(false);
Throwable exception = requestManager.getException();
if (exception.getClass() == UnknownHostException.class) {
if (exception.getClass() == UnreliableResponseException.class) {
UnreliableResponseException URE = (UnreliableResponseException) exception;
errorTitle.setText(URE.getExceptionTitle());
errorDetails.setText(URE.getExceptionDetails());
} else if (exception.getClass() == ProcessingException.class) {
errorTitle.setText("No Internet Connection");
errorDetails.setText("Could not connect to the server. Please check your connection.");
}
errorLayer.setVisible(true);
requestManager.reset();
});
requestManager.start();

View file

@ -0,0 +1,49 @@
/*
* Copyright 2018 Rohit Awate.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.rohitawate.restaurant.exceptions;
/**
* Thrown when the server sends ambiguous responses.
* For example, some servers do not provide the new location in case of a 301 Moved Permanently.
* <p>
* Used by DashboardController to display ErrorLayer.
*/
public class UnreliableResponseException extends Exception {
private String exceptionTitle;
private String exceptionDetails;
public UnreliableResponseException(String exceptionTitle, String exceptionDetails) {
this.exceptionTitle = exceptionTitle;
this.exceptionDetails = exceptionDetails;
}
public void setExceptionTitle(String exceptionTitle) {
this.exceptionTitle = exceptionTitle;
}
public void setExceptionDetails(String exceptionDetails) {
this.exceptionDetails = exceptionDetails;
}
public String getExceptionTitle() {
return exceptionTitle;
}
public String getExceptionDetails() {
return exceptionDetails;
}
}

View file

@ -19,6 +19,7 @@ package com.rohitawate.restaurant.requestsmanager;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.rohitawate.restaurant.exceptions.UnreliableResponseException;
import com.rohitawate.restaurant.models.requests.DELETERequest;
import com.rohitawate.restaurant.models.responses.RestaurantResponse;
import javafx.concurrent.Task;
@ -26,7 +27,6 @@ import javafx.concurrent.Task;
import javax.ws.rs.client.Invocation;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@ -58,22 +58,22 @@ public class DELETERequestManager extends RequestManager {
response.setTime(initialTime, System.currentTimeMillis());
if (serverResponse == null)
throw new IOException();
throw new UnreliableResponseException("The server did not respond.",
"Like that crush from high school..");
else if (serverResponse.getStatus() == 301) {
response.setStatusCode(301);
String newLocation = serverResponse.getHeaderString("location");
String responseHelpText;
String responseHelpText;
if (newLocation == null)
responseHelpText = "The resource has been permanently moved to another location.\n\n" +
responseHelpText = "The resource has been permanently moved to another location.\n" +
"Here's what you can do:\n" +
"- Find the new URL from the API documentation.\n" +
"- Try using https instead of http if you're not already.";
else
responseHelpText = "The resource has been permanently moved to: " + newLocation;
responseHelpText = "The resource has been permanently moved to: " + newLocation +
"\nRESTaurant doesn't automatically redirect your requests.";
response.setBody(responseHelpText);
return response;
throw new UnreliableResponseException("301: Resource Moved Permanently", responseHelpText);
}
String type = (String) serverResponse.getHeaders().getFirst("Content-type");
@ -82,22 +82,26 @@ public class DELETERequestManager extends RequestManager {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
switch (type.toLowerCase()) {
case "application/json; charset=utf-8":
case "application/json":
JsonNode node = mapper.readTree(responseBody);
response.setBody(mapper.writeValueAsString(node));
break;
case "application/xml; charset=utf-8":
case "application/xml":
response.setBody(mapper.writeValueAsString(responseBody));
break;
case "text/html":
case "text/html; charset=utf-8":
response.setBody(responseBody);
break;
default:
response.setBody(responseBody);
if (type != null) {
switch (type.toLowerCase()) {
case "application/json; charset=utf-8":
case "application/json":
JsonNode node = mapper.readTree(responseBody);
response.setBody(mapper.writeValueAsString(node));
break;
case "application/xml; charset=utf-8":
case "application/xml":
response.setBody(mapper.writeValueAsString(responseBody));
break;
case "text/html":
case "text/html; charset=utf-8":
response.setBody(responseBody);
break;
default:
response.setBody(responseBody);
}
} else {
response.setBody("No body found in the response.");
}
response.setMediaType(serverResponse.getMediaType());

View file

@ -19,6 +19,7 @@ package com.rohitawate.restaurant.requestsmanager;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.rohitawate.restaurant.exceptions.UnreliableResponseException;
import com.rohitawate.restaurant.models.requests.DataDispatchRequest;
import com.rohitawate.restaurant.models.responses.RestaurantResponse;
import javafx.concurrent.Task;
@ -32,7 +33,10 @@ import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Form;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.io.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;
@ -132,22 +136,22 @@ public class DataDispatchRequestManager extends RequestManager {
response.setTime(initialTime, System.currentTimeMillis());
if (serverResponse == null)
throw new IOException();
throw new UnreliableResponseException("The server did not respond.",
"Like that crush from high school..");
else if (serverResponse.getStatus() == 301) {
response.setStatusCode(301);
String newLocation = serverResponse.getHeaderString("location");
String responseHelpText;
String responseHelpText;
if (newLocation == null)
responseHelpText = "The resource has been permanently moved to another location.\n\n" +
responseHelpText = "The resource has been permanently moved to another location.\n" +
"Here's what you can do:\n" +
"- Find the new URL from the API documentation.\n" +
"- Try using https instead of http if you're not already.";
else
responseHelpText = "The resource has been permanently moved to: " + newLocation;
responseHelpText = "The resource has been permanently moved to: " + newLocation +
"\nRESTaurant doesn't automatically redirect your requests.";
response.setBody(responseHelpText);
return response;
throw new UnreliableResponseException("301: Resource Moved Permanently", responseHelpText);
}
String type = (String) serverResponse.getHeaders().getFirst("Content-type");
@ -156,22 +160,26 @@ public class DataDispatchRequestManager extends RequestManager {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
switch (type.toLowerCase()) {
case "application/json; charset=utf-8":
case "application/json":
JsonNode node = mapper.readTree(responseBody);
response.setBody(mapper.writeValueAsString(node));
break;
case "application/xml; charset=utf-8":
case "application/xml":
response.setBody(mapper.writeValueAsString(responseBody));
break;
case "text/html":
case "text/html; charset=utf-8":
response.setBody(responseBody);
break;
default:
response.setBody(responseBody);
if (type != null) {
switch (type.toLowerCase()) {
case "application/json; charset=utf-8":
case "application/json":
JsonNode node = mapper.readTree(responseBody);
response.setBody(mapper.writeValueAsString(node));
break;
case "application/xml; charset=utf-8":
case "application/xml":
response.setBody(mapper.writeValueAsString(responseBody));
break;
case "text/html":
case "text/html; charset=utf-8":
response.setBody(responseBody);
break;
default:
response.setBody(responseBody);
}
} else {
response.setBody("No body found in the response.");
}
response.setMediaType(serverResponse.getMediaType());

View file

@ -19,13 +19,13 @@ package com.rohitawate.restaurant.requestsmanager;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.rohitawate.restaurant.exceptions.UnreliableResponseException;
import com.rohitawate.restaurant.models.responses.RestaurantResponse;
import javafx.concurrent.Task;
import javax.ws.rs.client.Invocation.Builder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
@ -53,22 +53,22 @@ public class GETRequestManager extends RequestManager {
response.setTime(initialTime, System.currentTimeMillis());
if (serverResponse == null)
throw new IOException();
throw new UnreliableResponseException("The server did not respond.",
"Like that crush from high school..");
else if (serverResponse.getStatus() == 301) {
response.setStatusCode(301);
String newLocation = serverResponse.getHeaderString("location");
String responseHelpText;
String responseHelpText;
if (newLocation == null)
responseHelpText = "The resource has been permanently moved to another location.\n\n" +
responseHelpText = "The resource has been permanently moved to another location.\n" +
"Here's what you can do:\n" +
"- Find the new URL from the API documentation.\n" +
"- Try using https instead of http if you're not already.";
else
responseHelpText = "The resource has been permanently moved to: " + newLocation;
responseHelpText = "The resource has been permanently moved to: " + newLocation +
"\nRESTaurant doesn't automatically redirect your requests.";
response.setBody(responseHelpText);
return response;
throw new UnreliableResponseException("301: Resource Moved Permanently", responseHelpText);
}
String type = (String) serverResponse.getHeaders().getFirst("Content-type");
@ -77,22 +77,26 @@ public class GETRequestManager extends RequestManager {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.INDENT_OUTPUT, true);
switch (type.toLowerCase()) {
case "application/json; charset=utf-8":
case "application/json":
JsonNode node = mapper.readTree(responseBody);
response.setBody(mapper.writeValueAsString(node));
break;
case "application/xml; charset=utf-8":
case "application/xml":
response.setBody(mapper.writeValueAsString(responseBody));
break;
case "text/html":
case "text/html; charset=utf-8":
response.setBody(responseBody);
break;
default:
response.setBody(responseBody);
if (type != null) {
switch (type.toLowerCase()) {
case "application/json; charset=utf-8":
case "application/json":
JsonNode node = mapper.readTree(responseBody);
response.setBody(mapper.writeValueAsString(node));
break;
case "application/xml; charset=utf-8":
case "application/xml":
response.setBody(mapper.writeValueAsString(responseBody));
break;
case "text/html":
case "text/html; charset=utf-8":
response.setBody(responseBody);
break;
default:
response.setBody(responseBody);
}
} else {
response.setBody("No body found in the response.");
}
response.setMediaType(serverResponse.getMediaType());