From 4dd689795a6fc63baef1cb14a6fc4716c26fcbb9 Mon Sep 17 00:00:00 2001 From: Nathanael Jourdane Date: Fri, 19 Feb 2016 15:35:00 +0100 Subject: [PATCH] Improve Exception management and display better error messages for the user. --- src/main/java/eu/omp/irap/vespa/epntapclient/controller/EpnTapController.java | 10 +++------- src/main/java/eu/omp/irap/vespa/epntapclient/utils/Log.java | 3 +++ src/main/java/eu/omp/irap/vespa/epntapclient/view/RequestView.java | 7 ++++--- src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableConnection.java | 92 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------------------- src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableController.java | 66 ++++++++++++++++++++++++++++++------------------------------------ src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableDataParser.java | 6 ++++-- src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableException.java | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java | 19 +++++++++++-------- src/main/java/eu/omp/irap/vespa/epntapclient/votable/view/VOTableView.java | 24 +++++++++++++++++++----- 9 files changed, 208 insertions(+), 95 deletions(-) create mode 100644 src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableException.java diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/controller/EpnTapController.java b/src/main/java/eu/omp/irap/vespa/epntapclient/controller/EpnTapController.java index a552b5f..f8e161d 100644 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/controller/EpnTapController.java +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/controller/EpnTapController.java @@ -16,15 +16,12 @@ package eu.omp.irap.vespa.epntapclient.controller; -import java.io.IOException; - -import org.xml.sax.SAXException; - import eu.omp.irap.vespa.epntapclient.utils.Const; import eu.omp.irap.vespa.epntapclient.utils.Log; import eu.omp.irap.vespa.epntapclient.utils.Queries; import eu.omp.irap.vespa.epntapclient.view.EpnTapMainView; import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableController; +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException; import eu.omp.irap.vespa.epntapclient.votable.view.VOTableView; /** @@ -94,10 +91,9 @@ public class EpnTapController { /** * @param query The query to send to the selected service. - * @throws SAXException Can not change the VOTable schema location. - * @throws IOException If VOTable can not be parsed or there is more than one VOTable. + * @throws VOTableException Can not fill the Table */ - public void sendQuery(String query) throws IOException, SAXException { + public void sendQuery(String query) throws VOTableException { Log.LOGGER.info("Sending query: " + query + " on " + selectedServiceURL); resultsController.fillTable(selectedServiceURL, "ADQL", query); } diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/utils/Log.java b/src/main/java/eu/omp/irap/vespa/epntapclient/utils/Log.java index 93aa57a..5f89c98 100644 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/utils/Log.java +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/utils/Log.java @@ -37,6 +37,9 @@ public class Log { /** The logger. */ public static final Logger LOGGER = Logger.getAnonymousLogger(); + /** The log message displayed when errors appends. */ + public static String ERROR_MSG = "-- error --\n%1s\nbecause:\n%2s\n-- end of error --\n"; + /** Constructor to hide the implicit public one. */ private Log() { } diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/view/RequestView.java b/src/main/java/eu/omp/irap/vespa/epntapclient/view/RequestView.java index a9d1037..e5847ec 100644 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/view/RequestView.java +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/view/RequestView.java @@ -19,7 +19,6 @@ package eu.omp.irap.vespa.epntapclient.view; import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; -import java.util.logging.Level; import javax.swing.JButton; import javax.swing.JLabel; @@ -28,6 +27,7 @@ import javax.swing.JTextArea; import eu.omp.irap.vespa.epntapclient.utils.Log; import eu.omp.irap.vespa.epntapclient.utils.Queries; +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException; /** * @author N. Jourdane @@ -68,8 +68,9 @@ public class RequestView extends JPanel implements ActionListener { if (((JButton) evt.getSource()).getName() == "btnSend") { try { mainView.getController().sendQuery(queryArea.getText()); - } catch (Exception e) { - Log.LOGGER.log(Level.SEVERE, "Can not send query after clicking on the button.", e); + } catch (VOTableException e) { + Log.LOGGER.warning( + "Can not send query when clicking on the send button:\n" + e.getMessage()); } } } diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableConnection.java b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableConnection.java index b9edc8f..0f6d7d9 100644 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableConnection.java +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableConnection.java @@ -24,7 +24,6 @@ import java.io.PrintWriter; import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.MalformedURLException; -import java.net.ProtocolException; import java.net.URL; import java.net.URLEncoder; import java.text.SimpleDateFormat; @@ -32,6 +31,8 @@ import java.util.Date; import eu.omp.irap.vespa.epntapclient.utils.Const; import eu.omp.irap.vespa.epntapclient.utils.Log; +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.BadRequestException; +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.HTTPRequestException; /** * This class provide HTTP connection support to send requests through POST / GET protocols. @@ -50,26 +51,28 @@ public final class VOTableConnection { * @param targetURL The url of the registry to communicate (ie. "http://reg.g-vo.org"). * @param queryLanguage The language used for the queries (ie. "ADQL"). * @param query The query to ask to the registry. - * @throws IOException If the query can not be sent or got a bad response code. + * @throws HTTPRequestException Can not send the query. + * @throws BadRequestException The response code is not 200. * @return The path of the temporary XML file containing the http response. */ public static String sendQuery(String targetURL, String queryLanguage, - String query) throws IOException { + String query) throws HTTPRequestException, BadRequestException { - SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd_hhmmss_S"); + SimpleDateFormat ft = new SimpleDateFormat("yyyyMMdd_hhmmss_SSS"); String voTablePath = Const.TMP_DIR + "/votable" + ft.format(new Date()) + ".xml"; String uri = targetURL + "/sync"; String parameters = "REQUEST=doQuery&LANG=" + queryLanguage + "&QUERY="; - parameters += URLEncoder.encode(query, Const.CHARACTER_SET).replace("+", "%20") - .replace(".", "%2E").replace("-", "%2D").replace("*", "%2A").replace("_", "%5F"); + try { + parameters += URLEncoder.encode(query, Const.CHARACTER_SET).replace("+", "%20") + .replace(".", "%2E").replace("-", "%2D").replace("*", "%2A") + .replace("_", "%5F"); + } catch (UnsupportedEncodingException e) { + throw new HTTPRequestException("Can not encode URI " + uri, e); + } Log.LOGGER.info("request: " + uri + "?" + parameters); - int responseCode = VOTableConnection.sendGet(uri, parameters, voTablePath); - if (responseCode != HttpURLConnection.HTTP_OK) { - throw new IOException( - "The query:\n" + query + "\n got a bad response code: " + responseCode); - } + VOTableConnection.sendGet(uri, parameters, voTablePath); return voTablePath; } @@ -78,51 +81,72 @@ public final class VOTableConnection { * @param url The target URL of the request. * @param urlParameters The parameters of the request. * @param resultFileName The name of the file where the request response content is writed. - * @return The response code of the request (200 if successful). - * @throws IOException Can not connect to the specified URL. - * @throws IllegalArgumentException Can not send the specified request. + * @throws HTTPRequestException Can not send the request. + * @throws BadRequestException If the */ - private static int sendGet(String url, String urlParameters, String resultFileName) - throws IOException { + private static void sendGet(String url, String urlParameters, String resultFileName) + throws HTTPRequestException, BadRequestException { String inputLine; StringBuilder response = new StringBuilder(); URL obj; + String uri = url + "?" + urlParameters; + try { - obj = new URL(url + "?" + urlParameters); + obj = new URL(uri); } catch (MalformedURLException e) { - Log.LOGGER.severe("The URL is not correctly formated: " + e.getMessage()); - throw e; + throw new HTTPRequestException("The uri " + uri + "is not correctly formated", e); } HttpURLConnection con; - // TODO: Get the error message of the VOTableTable (VOTABLE/RESOURCE/INFO) try { con = (HttpURLConnection) obj.openConnection(); + con.setRequestMethod("GET"); } catch (IOException e) { - Log.LOGGER.severe("Can not connect to the specified URL: " + e.getMessage()); - throw e; + throw new HTTPRequestException("Can not open HTTP GET connection with uri " + uri, e); } + con.setRequestProperty("User-Agent", USER_AGENT); + int code = -1; + try { - con.setRequestMethod("GET"); - } catch (ProtocolException e) { - Log.LOGGER.severe("Not a valid HTTP method: " + e.getMessage()); - throw e; + code = con.getResponseCode(); + } catch (IOException e) { + throw new HTTPRequestException("Can not get the HTTP response code", e); } - con.setRequestProperty("User-Agent", USER_AGENT); - int responseCode = con.getResponseCode(); - BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream())); + if (code != HttpURLConnection.HTTP_OK + && code != HttpURLConnection.HTTP_BAD_REQUEST) { + throw new HTTPRequestException("The server returned a bad response code: " + code); + } - while ((inputLine = in.readLine()) != null) { - response.append(inputLine); + try (BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()))) { + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + in.close(); + } catch (IOException e1) { + try (BufferedReader in = new BufferedReader( + new InputStreamReader(con.getErrorStream()))) { + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + in.close(); + } catch (IOException e2) { + throw new HTTPRequestException("Can not get the error stream.", e2); + } + if (code != HttpURLConnection.HTTP_BAD_REQUEST) { + throw new HTTPRequestException( + "The server returned a bad response code (not 200 neither 400).", e1); + } } - new BufferedReader(new InputStreamReader(con.getInputStream())).close(); - printRequestResult(response, resultFileName); + try { + printRequestResult(response, resultFileName); + } catch (IOException e) { + throw new HTTPRequestException("Can not print the result in a file.", e); + } - return responseCode; } /** diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableController.java b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableController.java index c7cd517..0ee6327 100644 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableController.java +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableController.java @@ -17,11 +17,9 @@ package eu.omp.irap.vespa.epntapclient.votable.controller; import java.io.IOException; -import java.util.logging.Level; - -import org.xml.sax.SAXException; import eu.omp.irap.vespa.epntapclient.utils.Log; +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.VOTableParsingException; import eu.omp.irap.vespa.epntapclient.votable.model.Table; import eu.omp.irap.vespa.epntapclient.votable.model.VOTABLE; import eu.omp.irap.vespa.epntapclient.votable.view.VOTableView; @@ -51,13 +49,10 @@ public class VOTableController { */ public VOTableController(String voTablePath) { view = new VOTableView(); - try { fillTable(voTablePath); - } catch (Exception e) { - view.displayError("VOTable can not be displayed.\nReason:\n", e.getMessage()); - Log.LOGGER.log(Level.SEVERE, "VOTable can not be displayed.", e); - + } catch (VOTableException e) { + view.displayError("Can not fil the VOTable.", e); } } @@ -73,9 +68,8 @@ public class VOTableController { try { fillTable(VOTableConnection.sendQuery(targetURL, queryLanguage, query)); - } catch (Exception e) { - view.displayError("VOTable can not be displayed.\nReason:\n", e.getMessage()); - Log.LOGGER.log(Level.SEVERE, "VOTable can not be displayed.", e); + } catch (VOTableException e) { + Log.LOGGER.info("VOTableController error: " + e.getMessage()); } } @@ -83,52 +77,52 @@ public class VOTableController { * @param targetURL The url of the registry to communicate (ie. "http://reg.g-vo.org"). * @param queryLanguage The language used for the queries (ie. "ADQL"). * @param query The query to ask to the registry. - * @throws IOException If VOTable can not be parsed or there is more than one VOTable. - * @throws SAXException Can not change the VOTable schema location. + * @throws VOTableException Can not send the query or VOTable can not be parsed or can not fill + * the JTable. */ public void fillTable(String targetURL, String queryLanguage, String query) - throws IOException, SAXException { + throws VOTableException { fillTable(VOTableConnection.sendQuery(targetURL, queryLanguage, query)); } /** * @param voTablePath The path of the VOTable file. - * @throws IOException If VOTable can not be parsed or there is more than one VOTable. - * @throws SAXException Can not change the VOTable schema location. + * @throws VOTableException Can not fill the VOTable data in the JTable. */ - public void fillTable(String voTablePath) throws IOException, SAXException { + public void fillTable(String voTablePath) throws VOTableException { + try { voTable = VOTableParser.parseVOTable(voTablePath); - } catch (IOException e) { - view.displayError("Can not parse the VOTable", "Can not parse the VOTable.\nReason:\n" + - e.getMessage()); - Log.LOGGER.log(Level.SEVERE, "Can not parse the VOTable.", e); - } catch (SAXException e) { - view.displayError("Can not change the VOTable schema location", - "Can not change the VOTable schema location.\nReason:\n" + e.getMessage()); - Log.LOGGER.log(Level.SEVERE, "Can not change the VOTable schema location.", e); + } catch (VOTableParsingException e1) { + view.displayError("Can not parse the VOTable.", e1); } // TODO: Handle the case when there are more than 1 resource or table. if (voTable.getRESOURCE().size() > 1) { - view.displayError("Several resources", - "VOTable with more than one resource are not yet supported.\n" - + "See VOTable file for debug:\n" + voTablePath); + view.displayError("VOTable with more than one resource are not yet supported.\n" + + "See VOTable file for more informations: " + voTablePath); + return; } - // TODO: Iterate over all potential errors + // TODO: Iterate over all potential ERROR tags if ("ERROR".equals(voTable.getRESOURCE().get(0).getINFO().get(0).getValueAttribute())) { - view.displayError("Bad query", "There is an error on the query:\n" - + voTable.getRESOURCE().get(0).getINFO().get(0).getValue()); + String errorInfo = voTable.getRESOURCE().get(0).getINFO().get(0).getValue(); + view.displayError("The query is not valid.\n" + errorInfo); + return; } if (voTable.getRESOURCE().get(0).getLINKAndTABLEOrRESOURCE().size() > 1) { - view.displayError("Several tables", - "VOTable with more than one table are not yet supported. See VOTable file for debug:\n" - + voTablePath); + view.displayError("VOTable with more than one table are not yet supported.\n" + + "See VOTable file for more informations: " + voTablePath); + return; } Table table = (Table) (voTable.getRESOURCE().get(0).getLINKAndTABLEOrRESOURCE().get(0)); - VOTableDataParser dataParser = new VOTableDataParser(table); - view.fillTable(dataParser.getColumnsName(), dataParser.getDataArray()); + VOTableDataParser dataParser; + try { + dataParser = new VOTableDataParser(table); + view.fillTable(dataParser.getColumnsName(), dataParser.getDataArray()); + } catch (IOException e) { + throw new VOTableException("Can not fill the VOTable data in the JTable.", e); + } } /** diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableDataParser.java b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableDataParser.java index 922b178..4fda507 100644 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableDataParser.java +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableDataParser.java @@ -73,7 +73,7 @@ public class VOTableDataParser { for (int i = 0; i < fields.size(); i++) { columnsName[i] = fields.get(i).getName(); } - Log.LOGGER.info("Columns name: \n " + new Gson().toJson(columnsName)); + Log.LOGGER.info("Columns name: " + new Gson().toJson(columnsName)); data = new ArrayList<>(); @@ -185,7 +185,8 @@ public class VOTableDataParser { Object[] row = new Object[columnsName.length]; Log.clearFile(); - for (int nValue = 0; cursor < bytes.length; nValue++) { + int nValue = 0; + while (cursor < bytes.length) { int nColumn = nValue % columnsName.length; Field column = fields.get(nColumn); DataType dataType = column.getDatatype(); @@ -247,6 +248,7 @@ public class VOTableDataParser { if (nColumn == columnsName.length - 1) { data.add(row); } + nValue++; } } diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableException.java b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableException.java new file mode 100644 index 0000000..f28b165 --- /dev/null +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableException.java @@ -0,0 +1,76 @@ +/* + * This file is a part of EpnTAPClient. + * This program aims to provide EPN-TAP support for software clients, like CASSIS spectrum analyzer. + * See draft specifications: https://voparis-confluence.obspm.fr/pages/viewpage.action?pageId=559861 + * Copyright (C) 2016 Institut de Recherche en Astrophysique et Planétologie. + * + * This program is free software: you can + * redistribute it and/or modify it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, or (at your option) any later + * version. This program is distributed in the hope that it will be useful, but WITHOUT ANY + * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. You should have received a copy of + * the GNU General Public License along with this program. If not, see + * . + */ + +package eu.omp.irap.vespa.epntapclient.votable.controller; + +import java.util.logging.Level; + +import eu.omp.irap.vespa.epntapclient.utils.Log; + +/** + * VOTable Exception class. + * + * @author N. Jourdane + */ +@SuppressWarnings({ "javadoc", "serial" }) +public class VOTableException extends Exception { + public VOTableException() { + Log.LOGGER.log(Level.SEVERE, "A VOTable error occured."); + } + + public VOTableException(String message) { + Log.LOGGER.log(Level.SEVERE, message); + } + + public VOTableException(String message, Exception e) { + Log.LOGGER.log(Level.SEVERE, String.format(Log.ERROR_MSG, message, e.getMessage())); + } + + public VOTableException(Exception e) { + Log.LOGGER.log(Level.SEVERE, e.getMessage()); + } + + public static class HTTPRequestException extends VOTableException { + public HTTPRequestException(String message) { + Log.LOGGER.log(Level.SEVERE, message); + } + + public HTTPRequestException(String message, Exception e) { + Log.LOGGER.log(Level.SEVERE, String.format(Log.ERROR_MSG, message, e.getMessage())); + } + } + + public static class VOTableParsingException extends VOTableException { + public VOTableParsingException(String message, Exception e) { + Log.LOGGER.log(Level.SEVERE, String.format(Log.ERROR_MSG, message, e.getMessage())); + } + } + + public static class BadRequestException extends VOTableException { + private String info; + + public BadRequestException(String message, String info) { + super(message); + this.info = info; + Log.LOGGER.log(Level.WARNING, message + "\nDetails: " + info); + } + + public String getInfo() { + return info; + } + } + +} diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java index 8ad80db..61b27c0 100644 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/controller/VOTableParser.java @@ -20,6 +20,7 @@ import java.io.File; import java.io.IOException; import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; import javax.xml.bind.Unmarshaller; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; @@ -35,6 +36,7 @@ import org.w3c.dom.NamedNodeMap; import org.xml.sax.SAXException; import eu.omp.irap.vespa.epntapclient.utils.Log; +import eu.omp.irap.vespa.epntapclient.votable.controller.VOTableException.VOTableParsingException; import eu.omp.irap.vespa.epntapclient.votable.model.VOTABLE; /** @@ -61,23 +63,24 @@ public final class VOTableParser { /** * @param voTablePath The path of the VOTable. * @return The VOTable resulting of the XML document. - * @throws IOException Can not parse the VOTable. - * @throws SAXException Can not change the VOTable schema location. + * @throws VOTableParsingException Can not parse the VOTable. */ - public static VOTABLE parseVOTable(String voTablePath) throws IOException, SAXException { + public static VOTABLE parseVOTable(String voTablePath) throws VOTableParsingException { try { changeVOTableSchemaLocation(voTablePath); - } catch (Exception e1) { - throw new IOException("Can not change the VOTable schema location.", e1); + } catch (IOException e1) { + throw new VOTableParsingException("Can not change the VOTable schema location.", e1); } + // TODO: Change the name of the 2nd INFO tag instead of editing the XSD file. VOTABLE voTable; + JAXBContext jc; try { - JAXBContext jc = JAXBContext.newInstance(VOTABLE_MODEL_PACKAGE); + jc = JAXBContext.newInstance(VOTABLE_MODEL_PACKAGE); Unmarshaller unmarshaller = jc.createUnmarshaller(); voTable = (VOTABLE) unmarshaller.unmarshal(new File(voTablePath)); - } catch (Exception e) { - throw new SAXException("Can not parse the VOTable.", e); + } catch (JAXBException e) { + throw new VOTableParsingException("Can not change the VOTable schema location.", e); } return voTable; diff --git a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/view/VOTableView.java b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/view/VOTableView.java index 501b1fb..2eaf49f 100644 --- a/src/main/java/eu/omp/irap/vespa/epntapclient/votable/view/VOTableView.java +++ b/src/main/java/eu/omp/irap/vespa/epntapclient/votable/view/VOTableView.java @@ -18,6 +18,7 @@ package eu.omp.irap.vespa.epntapclient.votable.view; import java.awt.BorderLayout; import java.util.List; +import java.util.logging.Level; import javax.swing.JOptionPane; import javax.swing.JPanel; @@ -28,13 +29,15 @@ import javax.swing.event.TableModelEvent; import javax.swing.event.TableModelListener; import javax.swing.table.DefaultTableModel; +import eu.omp.irap.vespa.epntapclient.utils.Log; + /** * The main class of the View of the application. * * @author N. Jourdane */ public class VOTableView extends JPanel implements TableModelListener { - + // TODO: Create classes VOTableGUI and VOTableCLI which implements an interface VOTableView /** The serial version UID (affected with a random number). */ private static final long serialVersionUID = -6131752938586134234L; @@ -99,11 +102,22 @@ public class VOTableView extends JPanel implements TableModelListener { /** * Display an error. * - * @param title The title of the window. - * @param message The error message to display. + * @param message The error message displayed in the window. + */ + public void displayError(String message) { + JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE); + Log.LOGGER.log(Level.WARNING, message); + } + + /** + * Display an error. + * + * @param message The error message displayed in the window. + * @param e The exception displayed in the log for debug. */ - public void displayError(String title, String message) { - JOptionPane.showMessageDialog(this, message, title, JOptionPane.ERROR_MESSAGE); + public void displayError(String message, Exception e) { + JOptionPane.showMessageDialog(this, message, "Error", JOptionPane.ERROR_MESSAGE); + Log.LOGGER.log(Level.SEVERE, String.format(Log.ERROR_MSG, message, e.getMessage())); } @Override -- libgit2 0.21.2