現場で、フロントエンド側(JavaScript)で発生したエラーを、
servlet側に渡して、ログに出力したいという要件が有りました。
あまり求められたことが無い、珍しい要件だったので、
その時とったアプローチ方法をメモしておこうと思います。
対応方法
大まかに以下のような形で対応を行いました。
①JavaScriptでエラーが発生→window.onerror(JavaScript)でエラーをキャッチ
②キャッチしたエラー情報を、servlet側に渡せるように、jsp上のhiddenタグに設定
③jspからservletに、エラー情報をポスト
④JavaScriptで発生したエラー情報を、servlet内で文字列の情報として利用
◯参考情報:MDN window.onerror
その時に、検証用に作成したプロジェクトのソースをメモしておこうと思います。
検証プロジェクト 内容
JavaScriptエラーを意図的に発生させるdoErrorボタンと、
発生したエラー内容をservlet側にpostするpostErrorボタンを用意しました。
doErrorボタンを実行すると、JavaScriptエラーが発生し、
エラー内容を、htmlに表示します。
エラーが表示されている状態で、postErrorボタンをクリックすると、
postされてservlet側にエラー内容が届きます。
検証用ファイル JavaScript
意図的にJavaScriptエラーを発生させるFunctionを作成しました。
また、windows.onerrorをエラーハンドリングとして利用しています。
// 意図的にJavaScriptエラーを発生させるFunction. function doError(){ let aa = ""; aa - bb; // do error. console.log("click test."); } // JavaScript内でエラーが発生した場合、呼び出されるFunction. window.onerror = function (msg, file, line, column, err) { // ブラウザコンソール出力 console.log("msg:" + msg) console.log("err:" + err) console.log("file:" + file) console.log("line:" + line) console.log("colum:" + column) // エラー内容整形 let em = "msg:" + msg; em += " </br> err:" + err; em += " </br> file:" + file; em += " </br> line:" + line + " colum:" + column; // 画面上部に表示 document.getElementById("showErrorDiv").innerHTML = em; // form内のhiddenに値設定 document.getElementById("showErrorInput").value = em; };
検証用ファイル Jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>JsError Practice01</title> <script src="/jsErrorPractice01/js/errorTest.js"></script> </head> <body> <div>JsError Practice01</div> <hr> <div id="showErrorDiv"></div> <input type="button" onclick="doError()" value="doError" /> <hr> <form action="./CatchJsError" method="post"> <input type="hidden" id="showErrorInput" name="showErrorInput" /> <input type="submit" value="postError" /> </form> </body> </html>
検証用ファイル Servlet
postされたエラー情報を抽出して、出力確認を行なっています。
import java.io.IOException; import javax.servlet.RequestDispatcher; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; /** * Servlet implementation class HelloWorld */ @WebServlet("/CatchJsError") public class CatchJsError extends HttpServlet { private static final long serialVersionUID = 1L; /** * @see HttpServlet#HttpServlet() */ public CatchJsError() { super(); // TODO Auto-generated constructor stub } /** * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */ protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String view = "/index.jsp"; RequestDispatcher dispatcher = request.getRequestDispatcher(view); dispatcher.forward(request, response); } /** * @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */ protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { // Postされた、JavaScriptエラーをhttpParamから抽出 String errorMsg = request.getParameter("showErrorInput"); // 画面表示用に改行置き換え System.out.println(errorMsg.replace("</br>", System.getProperty("line.separator"))); // 画面更新処理 String view = "/index.jsp"; RequestDispatcher dispatcher = request.getRequestDispatcher(view); dispatcher.forward(request, response); } }
以上が、メモ内容となります。
余談ですが、JavaScriptのフレームワークを採用している場合、
window.onerrorでは、全てのエラーを拾うことが出来ない場合もあります。
フレームワークを採用している場合、フレームワークで実装されている
エラーハンドラを利用することをお勧めします。