commit 092ba8cb17a1127dc11aa6d992275fe9cf8e644e
Author: Tomáš Šimandl <tomas.simandl@gmail.com>
Date:   Mon Feb 11 09:37:05 2019 +0100

    #24 throws exceptions early, catch them late
    
    - throw own exception and handle it with error page

diff --git a/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/servlets/DataAccessError.java b/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/servlets/DataAccessError.java
new file mode 100644
index 0000000..c53c5a1
--- /dev/null
+++ b/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/servlets/DataAccessError.java
@@ -0,0 +1,36 @@
+package cz.zcu.kiv.offscreen.servlets;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonObject;
+
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.io.PrintWriter;
+
+public class DataAccessError extends HttpServlet {
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        handleRequest(req, resp);
+    }
+
+    @Override
+    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
+        handleRequest(req, resp);
+    }
+
+
+    private void handleRequest(HttpServletRequest request, HttpServletResponse response) throws IOException {
+        Throwable throwable = (Throwable) request.getAttribute("javax.servlet.error.exception");
+        response.setContentType("application/json");
+        PrintWriter out = response.getWriter();
+
+        JsonObject json = new JsonObject();
+        json.addProperty("exception", throwable.getMessage());
+
+        out.println(new Gson().toJson(json));
+    }
+}
diff --git a/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/DB.java b/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/DB.java
index b61e012..629e210 100644
--- a/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/DB.java
+++ b/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/DB.java
@@ -34,6 +34,7 @@ public class DB {
 			connection.setAutoCommit(true);
 		} catch (ClassNotFoundException | SQLException e) {
 			logger.error("Can not open database connection: ", e);
+			throw new DataAccessException(e);
 		}
 	}
 
@@ -43,11 +44,16 @@ public class DB {
 	 * @param query query with ? on values.
 	 * @param returnGeneratedKeys true - RETURN_GENERATED_KEYS flag is set, false - no flag is set
 	 */
-	PreparedStatement getPreparedStatement(String query, boolean returnGeneratedKeys) throws SQLException {
-		if (returnGeneratedKeys) {
-			return connection.prepareStatement(query, PreparedStatement.RETURN_GENERATED_KEYS);
-		} else {
-			return connection.prepareStatement(query);
+	PreparedStatement getPreparedStatement(String query, boolean returnGeneratedKeys) {
+		try {
+			if (returnGeneratedKeys) {
+				return connection.prepareStatement(query, PreparedStatement.RETURN_GENERATED_KEYS);
+			} else {
+				return connection.prepareStatement(query);
+			}
+		}catch (SQLException e){
+			logger.error("Can not execute query: " + query);
+			throw new DataAccessException(e);
 		}
 	}
 
@@ -63,8 +69,8 @@ public class DB {
 			return preparedStatement.getResultSet();
 		} catch (SQLException e) {
 			logger.error("Can not execute database query: ", e);
+			throw new DataAccessException(e);
 		}
-		return null;
 	}
 
 	/**
@@ -78,8 +84,8 @@ public class DB {
 			return preparedStatement.getGeneratedKeys();
 		} catch (SQLException e) {
 			logger.error("Can not execute database query: ", e);
+			throw new DataAccessException(e);
 		}
-		return null;
 	}
 
 	/**
@@ -95,8 +101,8 @@ public class DB {
 
 		} catch(SQLException | NullPointerException e) {
 			logger.error("Can not execute database query: ", e);
+			throw new DataAccessException(e);
 		}
-		return null;
 	}
 
 	/**
@@ -107,12 +113,9 @@ public class DB {
 	int executeStatement(PreparedStatement preparedStatement) {
 		try {
 			return preparedStatement.executeUpdate();
-		} catch(SQLException e) {
-			logger.error("Can not execute database query: ", e);
-			return -1;
-		} catch (NullPointerException e) {
+		} catch(NullPointerException | SQLException e) {
 			logger.error("Can not execute database query: ", e);
-			return -2;
+			throw new DataAccessException(e);
 		}
 	}
 
diff --git a/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/DataAccessException.java b/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/DataAccessException.java
new file mode 100644
index 0000000..ba9ac7d
--- /dev/null
+++ b/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/DataAccessException.java
@@ -0,0 +1,8 @@
+package cz.zcu.kiv.offscreen.user;
+
+public class DataAccessException extends RuntimeException {
+
+    public DataAccessException(Throwable cause) {
+        super(cause);
+    }
+}
diff --git a/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/Diagram.java b/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/Diagram.java
index 85fd8ae..8bbf779 100644
--- a/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/Diagram.java
+++ b/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/Diagram.java
@@ -58,6 +58,7 @@ public class Diagram {
             }
         }  catch (SQLException e){
             logger.error("Can not get owner id: ", e);
+            throw new DataAccessException(e);
         }
         return -1;
     }
@@ -78,6 +79,7 @@ public class Diagram {
             }
         }  catch (SQLException e){
             logger.error("Can not check if diagram is public: ", e);
+            throw new DataAccessException(e);
         }
         return false;
     }
@@ -97,6 +99,7 @@ public class Diagram {
             }
         }  catch (SQLException e){
             logger.error("Can not get json of diagram: ", e);
+            throw new DataAccessException(e);
         }
         return "";
     }
@@ -120,6 +123,7 @@ public class Diagram {
 
         } catch (SQLException e) {
             logger.error("Can not get diagram: ", e);
+            throw new DataAccessException(e);
         }
 
         return Collections.emptyMap();
@@ -172,6 +176,7 @@ public class Diagram {
             }
         } catch (SQLException e) {
             logger.error("Can not update diagram: ", e);
+            throw new DataAccessException(e);
         }
     }
 
@@ -190,6 +195,7 @@ public class Diagram {
 
         } catch (SQLException e) {
             logger.error("Can not delete diagram: ", e);
+            throw new DataAccessException(e);
         }
     }
 
@@ -235,9 +241,8 @@ public class Diagram {
 
         } catch (SQLException e){
             logger.error("Can not create map from input result set: ", e);
+            throw new DataAccessException(e);
         }
-
-        return new ArrayList<>();
     }
 
     /**
diff --git a/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/User.java b/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/User.java
index 691b541..0f0b51f 100644
--- a/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/User.java
+++ b/sources/imiger-core/src/main/java/cz/zcu/kiv/offscreen/user/User.java
@@ -62,6 +62,7 @@ public class User {
 			}
 		} catch (SQLException | IllegalArgumentException e) {
 			logger.error("Can not login user: ", e);
+			throw new DataAccessException(e);
 		}
 
 		return false;
@@ -98,6 +99,7 @@ public class User {
 
 		} catch (SQLException e) {
 			logger.error("Can not register user: ", e);
+			throw new DataAccessException(e);
 		}
 	}
 
@@ -130,6 +132,7 @@ public class User {
 			}
 		} catch (SQLException e) {
 			logger.error("Can not get user: ", e);
+			throw new DataAccessException(e);
 		}
 
 		return Collections.emptyMap();
@@ -159,6 +162,7 @@ public class User {
 
 			} catch (SQLException e) {
 				logger.error("Can not get user session: ", e);
+				throw new DataAccessException(e);
 			}
 		}
 	}
@@ -181,6 +185,7 @@ public class User {
 				db.executeStatement(pst);
 			} catch (SQLException e) {
 				logger.error("Can not update user: ", e);
+				throw new DataAccessException(e);
 			}
 		}
 	}
@@ -199,6 +204,7 @@ public class User {
 				}
 			}  catch (SQLException e){
 				logger.error("Can not get users nick name: ", e);
+				throw new DataAccessException(e);
 			}
 		}
 
@@ -241,6 +247,7 @@ public class User {
 			}
 		} catch (SQLException e) {
 			logger.error("Can not check if user exits: ", e);
+			throw new DataAccessException(e);
 		}
 
 		return false;
diff --git a/sources/imiger-core/src/main/webapp/WEB-INF/web.xml b/sources/imiger-core/src/main/webapp/WEB-INF/web.xml
index 0205896..2aab8de 100644
--- a/sources/imiger-core/src/main/webapp/WEB-INF/web.xml
+++ b/sources/imiger-core/src/main/webapp/WEB-INF/web.xml
@@ -80,6 +80,10 @@
 		<servlet-name>RestRawInput</servlet-name>
 		<servlet-class>cz.zcu.kiv.offscreen.servlets.rest.RawInput</servlet-class>
 	</servlet>
+	<servlet>
+		<servlet-name>DataAccessError</servlet-name>
+		<servlet-class>cz.zcu.kiv.offscreen.servlets.DataAccessError</servlet-class>
+	</servlet>
 
 	<!--
 	URL-to-servlet mappings
@@ -132,6 +136,15 @@
 		<servlet-name>RestRawInput</servlet-name>
 		<url-pattern>/rest/raw-input</url-pattern>
 	</servlet-mapping>
+	<servlet-mapping>
+		<servlet-name>DataAccessError</servlet-name>
+		<url-pattern>/data-access-error</url-pattern>
+	</servlet-mapping>
+
+	<error-page>
+		<exception-type>cz.zcu.kiv.offscreen.user.DataAccessException</exception-type>
+		<location>/data-access-error</location>
+	</error-page>
 
 	<session-config>
 		<session-timeout>120</session-timeout>
