-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhandling-exceptions-in-webui.html
61 lines (57 loc) · 17.8 KB
/
handling-exceptions-in-webui.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<!DOCTYPE html><html lang="de-ch"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><title>Handling Exceptions in Web UI - Finecloud</title><meta name="description" content="The Issue There is nothing worse than presenting a Java Stacktrace in a WebUI, full of technical Details about your Server environment of the Web App itself: So how can we avoid this? You don't want to share this informations with the users, it would…"><meta name="generator" content="Publii Open-Source CMS for Static Site"><link rel="stylesheet" href="https://www.finecloud.ch/media/plugins/syntaxHighlighter/prism-black.css"><link rel="canonical" href="https://www.finecloud.ch/handling-exceptions-in-webui.html"><link rel="alternate" type="application/atom+xml" href="https://www.finecloud.ch/feed.xml"><link rel="alternate" type="application/json" href="https://www.finecloud.ch/feed.json"><meta property="og:title" content="Handling Exceptions in Web UI"><meta property="og:site_name" content="Finecloud"><meta property="og:description" content="The Issue There is nothing worse than presenting a Java Stacktrace in a WebUI, full of technical Details about your Server environment of the Web App itself: So how can we avoid this? You don't want to share this informations with the users, it would…"><meta property="og:url" content="https://www.finecloud.ch/handling-exceptions-in-webui.html"><meta property="og:type" content="article"><link rel="shortcut icon" href="https://www.finecloud.ch/media/website/finecloud.png" type="image/png"><link rel="stylesheet" href="https://www.finecloud.ch/assets/css/style.css?v=39da73365516a098a9b73b721fc970e2"><script type="application/ld+json">{"@context":"http://schema.org","@type":"Article","mainEntityOfPage":{"@type":"WebPage","@id":"https://www.finecloud.ch/handling-exceptions-in-webui.html"},"headline":"Handling Exceptions in Web UI","datePublished":"2022-09-27T17:47","dateModified":"2022-09-27T17:49","description":"The Issue There is nothing worse than presenting a Java Stacktrace in a WebUI, full of technical Details about your Server environment of the Web App itself: So how can we avoid this? You don't want to share this informations with the users, it would…","author":{"@type":"Person","name":"Finecloud","url":"https://www.finecloud.ch/authors/finecloud/"},"publisher":{"@type":"Organization","name":"Finecloud"}}</script><meta name="google-site-verification" content="seFY9U12uiEq5U3_MyZiX6XWzk0AVFl9zITr2ZKsytY"></head><body><div class="site-container"><header class="top" id="js-header"><a class="logo" href="https://www.finecloud.ch/">Finecloud</a><nav class="navbar js-navbar"><button class="navbar__toggle js-toggle" aria-label="Menu" aria-haspopup="true" aria-expanded="false"><span class="navbar__toggle-box"><span class="navbar__toggle-inner">Menu</span></span></button><ul class="navbar__menu"><li><a href="https://www.finecloud.ch/" target="_self">Blog</a></li><li><a href="https://www.finecloud.ch/tags/" target="_self">Tags</a></li></ul></nav><div class="search"><div class="search__overlay js-search-overlay"><div class="search__overlay-inner"><form action="https://www.finecloud.ch/search.html" class="search__form"><input class="search__input js-search-input" type="search" name="q" placeholder="search..." aria-label="search..." autofocus="autofocus"></form><button class="search__close js-search-close" aria-label="Close">Close</button></div></div><button class="search__btn js-search-btn" aria-label="Search"><svg role="presentation" focusable="false"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#search"/></svg></button></div></header><main><article class="post"><div class="hero"><figure class="hero__image hero__image--overlay"><img src="https://www.finecloud.ch/media/website/download.jpg" srcset="https://www.finecloud.ch/media/website/responsive/download-xs.jpg 300w, https://www.finecloud.ch/media/website/responsive/download-sm.jpg 480w, https://www.finecloud.ch/media/website/responsive/download-md.jpg 768w, https://www.finecloud.ch/media/website/responsive/download-lg.jpg 1024w, https://www.finecloud.ch/media/website/responsive/download-xl.jpg 1360w, https://www.finecloud.ch/media/website/responsive/download-2xl.jpg 1600w" sizes="100vw" loading="eager" alt=""></figure><header class="hero__content"><div class="wrapper"><div class="post__meta"><time datetime="2022-09-27T17:47">September 27, 2022</time></div><h1>Handling Exceptions in Web UI</h1></div></header></div><div class="wrapper post__entry"><div class="post__toc"><h3>Table of Contents</h3><ul><li><a href="#mcetoc_1gdv9jdoksv">The Issue</a></li><li><a href="#mcetoc_1gdv9jdokt0">Custom Error Page</a></li><li><a href="#mcetoc_1gdv9jdokt1">Error Controller</a></li></ul></div><h2 id="mcetoc_1gdv9jdoksv">The Issue</h2><p>There is nothing worse than presenting a Java Stacktrace in a WebUI, full of technical Details about your Server environment of the Web App itself:</p><figure class="post__image"><img loading="lazy" src="https://www.finecloud.ch/media/posts/66//Screenshot-2022-09-27-at-10.37.26.png" alt="" width="1077" height="1032" sizes="100vw" srcset="https://www.finecloud.ch/media/posts/66//responsive/Screenshot-2022-09-27-at-10.37.26-xs.png 300w, https://www.finecloud.ch/media/posts/66//responsive/Screenshot-2022-09-27-at-10.37.26-sm.png 480w, https://www.finecloud.ch/media/posts/66//responsive/Screenshot-2022-09-27-at-10.37.26-md.png 768w, https://www.finecloud.ch/media/posts/66//responsive/Screenshot-2022-09-27-at-10.37.26-lg.png 1024w, https://www.finecloud.ch/media/posts/66//responsive/Screenshot-2022-09-27-at-10.37.26-xl.png 1360w, https://www.finecloud.ch/media/posts/66//responsive/Screenshot-2022-09-27-at-10.37.26-2xl.png 1600w"></figure><p>So how can we avoid this? You don't want to share this informations with the users, it would scare them and they wouldn't understand it.</p><p>What is happing here, is that the Page will try to redirect to the /error Page. This Page does not exist as real HTML Page. This is just a generated default page out of the box. This is generated in code. But we can create our own error page to avoid this.</p><h2 id="mcetoc_1gdv9jdokt0">Custom Error Page</h2><p>Let's create a new HTML Page under <em>resources/templates/error.html</em>:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-meta" style="color: #bbb529;"><!DOCTYPE html></span>
<span class="hljs-tag"><<span class="hljs-name" style="color: #e8bf6a;">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string" style="color: #6a8759;">"en"</span>></span>
<span class="hljs-tag"><<span class="hljs-name" style="color: #e8bf6a;">head</span>></span>
<span class="hljs-tag"><<span class="hljs-name" style="color: #e8bf6a;">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string" style="color: #6a8759;">"UTF-8"</span>></span>
<span class="hljs-tag"><<span class="hljs-name" style="color: #e8bf6a;">title</span>></span>Error Page<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">title</span>></span>
<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">head</span>></span>
<span class="hljs-tag"><<span class="hljs-name" style="color: #e8bf6a;">body</span>></span>
Something went horribly, terribly wrong. Please try again.
<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">body</span>></span>
<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">html</span>></span></pre><p>To use this Page, because it's under the templates folder it needs a controller in order to work.</p><h2 id="mcetoc_1gdv9jdokt1">Error Controller</h2><p>So we need to create an error Controller for this. Let's create a new Java Class called ErrorController.java with this content:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-keyword" style="color: #cc7832;">package</span> ch.finecloud.peopledbweb.web.controller;
<span class="hljs-keyword" style="color: #cc7832;">import</span> org.springframework.stereotype.Controller;
<span class="hljs-keyword" style="color: #cc7832;">import</span> org.springframework.web.bind.annotation.GetMapping;
<span class="hljs-keyword" style="color: #cc7832;">import</span> org.springframework.web.bind.annotation.RequestMapping;
<span class="hljs-meta" style="color: #bbb529;">@Controller</span>
<span class="hljs-meta" style="color: #bbb529;">@RequestMapping</span>(<span class="hljs-string" style="color: #6a8759;">"error"</span>)
<span class="hljs-keyword" style="color: #cc7832;">public</span> <span class="hljs-class"><span class="hljs-keyword" style="color: #cc7832;">class</span> <span class="hljs-title" style="color: #ffc66d;">ErrorController</span> </span>{
<span class="hljs-meta" style="color: #bbb529;">@GetMapping</span>
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> String <span class="hljs-title" style="color: #ffc66d;">getErrorPage</span><span class="hljs-params">()</span> </span>{
<span class="hljs-keyword" style="color: #cc7832;">return</span> <span class="hljs-string" style="color: #6a8759;">"error"</span>;
}
}
</pre><p>If a User now again hits an error, this will be shown:</p><figure class="post__image"><img loading="lazy" src="https://www.finecloud.ch/media/posts/66/Screenshot-2022-09-27-at-13.08.06-2.png" alt="" width="413" height="131" sizes="100vw" srcset="https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.08.06-2-xs.png 300w, https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.08.06-2-sm.png 480w, https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.08.06-2-md.png 768w, https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.08.06-2-lg.png 1024w, https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.08.06-2-xl.png 1360w, https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.08.06-2-2xl.png 1600w"></figure><p>Much better, isn't it? But we can do even better. If we know what kind of error could be thrown, we can provide a more accurate error page. In our current case we need to add a specific try catch block in the save method, which can catch StorageExceptions:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"> <span class="hljs-meta" style="color: #bbb529;">@PostMapping</span>
<span class="hljs-function"><span class="hljs-keyword" style="color: #cc7832;">public</span> String <span class="hljs-title" style="color: #ffc66d;">savePerson</span><span class="hljs-params">(Model model, @Valid Person person, Errors errors, @RequestParam(<span class="hljs-string" style="color: #6a8759;">"photoFilename"</span>)</span> MultipartFile photoFile) <span class="hljs-keyword" style="color: #cc7832;">throws</span> IOException </span>{
log.info(person);
log.info(<span class="hljs-string" style="color: #6a8759;">"Filename: "</span> + photoFile.getOriginalFilename());
log.info(<span class="hljs-string" style="color: #6a8759;">"File size: "</span> + photoFile.getSize());
log.info(<span class="hljs-string" style="color: #6a8759;">"Errors: "</span> + errors);
<span class="hljs-keyword" style="color: #cc7832;">if</span> (!errors.hasErrors()) {
<span class="hljs-keyword" style="color: #cc7832;">try</span> {
fileStorageRepository.save(photoFile.getOriginalFilename(), photoFile.getInputStream());
personRepository.save(person);
<span class="hljs-keyword" style="color: #cc7832;">return</span> <span class="hljs-string" style="color: #6a8759;">"redirect:people"</span>;
} <span class="hljs-keyword" style="color: #cc7832;">catch</span> (StorageException e) {
model.addAttribute(<span class="hljs-string" style="color: #6a8759;">"errorMsg"</span>, <span class="hljs-string" style="color: #6a8759;">"System is currently unable to accept photo files at this time."</span>);
<span class="hljs-keyword" style="color: #cc7832;">return</span> <span class="hljs-string" style="color: #6a8759;">"people"</span>;
}
}
<span class="hljs-keyword" style="color: #cc7832;">return</span> <span class="hljs-string" style="color: #6a8759;">"people"</span>;
}</pre><p>Now let's add this custom error Message to the people.html page like so:</p><pre class="hljs" style="color: #a9b7c6; background: #282b2e none repeat scroll 0% 0%; display: block; overflow-x: auto; padding: 0.5em;"><span class="hljs-tag"><<span class="hljs-name" style="color: #e8bf6a;">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string" style="color: #6a8759;">"alert alert-danger"</span> <span class="hljs-attr">role</span>=<span class="hljs-string" style="color: #6a8759;">"alert"</span> <span class="hljs-attr">th:text</span>=<span class="hljs-string" style="color: #6a8759;">"${errorMsg}"</span> <span class="hljs-attr">th:if</span>=<span class="hljs-string" style="color: #6a8759;">"${errorMsg}"</span>></span>
A simple danger alert-check it out!
<span class="hljs-tag"></<span class="hljs-name" style="color: #e8bf6a;">div</span>></span></pre><p>The final result looks like this:</p><figure class="post__image"><img loading="lazy" src="https://www.finecloud.ch/media/posts/66/Screenshot-2022-09-27-at-13.35.45.png" alt="" width="2312" height="1560" sizes="100vw" srcset="https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.35.45-xs.png 300w, https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.35.45-sm.png 480w, https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.35.45-md.png 768w, https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.35.45-lg.png 1024w, https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.35.45-xl.png 1360w, https://www.finecloud.ch/media/posts/66/responsive/Screenshot-2022-09-27-at-13.35.45-2xl.png 1600w"></figure><p>The User will be redirected back to the people page with the provided values. The Error Message will be displayed in the middle of the page.</p><p> </p></div><footer class="wrapper post__footer"><p class="post__last-updated">This article was updated on September 27, 2022</p><ul class="post__tag"><li><a href="https://www.finecloud.ch/tags/api/">api</a></li><li><a href="https://www.finecloud.ch/tags/database/">database</a></li><li><a href="https://www.finecloud.ch/tags/gui/">gui</a></li><li><a href="https://www.finecloud.ch/tags/http/">http</a></li><li><a href="https://www.finecloud.ch/tags/java/">java</a></li><li><a href="https://www.finecloud.ch/tags/java-basics/">java basics</a></li><li><a href="https://www.finecloud.ch/tags/softwareentwicklung/">software development</a></li><li><a href="https://www.finecloud.ch/tags/spring/">spring</a></li><li><a href="https://www.finecloud.ch/tags/spring-framework/">spring-framework</a></li><li><a href="https://www.finecloud.ch/tags/thymeleaf/">thymeleaf</a></li></ul><div class="post__share"></div></footer></article><nav class="post__nav"><div class="post__nav-inner"><div class="post__nav-prev"><svg width="1.041em" height="0.416em" aria-hidden="true"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#arrow-prev"/></svg> <a href="https://www.finecloud.ch/getting-stared-with-spring-framework.html" class="post__nav-link" rel="prev"><span>Previous</span> Getting stared with the Spring Framework</a></div><div class="post__nav-next"><a href="https://www.finecloud.ch/threema-backup-to-nextcloud.html" class="post__nav-link" rel="next"><span>Next</span> Threema Safe backup to Nextcloud </a><svg width="1.041em" height="0.416em" aria-hidden="true"><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#arrow-next"/></svg></div></div></nav><div class="post__related related"><div class="wrapper"><h2 class="h5 related__title">You should also read:</h2><article class="related__item"><div class="feed__meta"><time datetime="2023-04-10T08:36" class="feed__date">April 10, 2023</time></div><h3 class="h1"><a href="https://www.finecloud.ch/spring-exception-handling.html">Spring Exception Handling</a></h3></article><article class="related__item"><div class="feed__meta"><time datetime="2022-08-23T10:05" class="feed__date">August 23, 2022</time></div><h3 class="h1"><a href="https://www.finecloud.ch/java-exceptions.html">Java basics: Exceptions</a></h3></article></div></div></main><footer class="footer"><div class="footer__copyright"><p>Powered by Publii</p></div><button onclick="backToTopFunction()" id="backToTop" class="footer__bttop" aria-label="Back to top" title="Back to top"><svg><use xlink:href="https://www.finecloud.ch/assets/svg/svg-map.svg#toparrow"/></svg></button></footer></div><script>window.publiiThemeMenuConfig = {
mobileMenuMode: 'sidebar',
animationSpeed: 300,
submenuWidth: 'auto',
doubleClickTime: 500,
mobileMenuExpandableSubmenus: true,
relatedContainerForOverlayMenuSelector: '.top',
};</script><script defer="defer" src="https://www.finecloud.ch/assets/js/scripts.min.js?v=6ca8b60e6534a3888de1205e82df8528"></script><script>var images = document.querySelectorAll('img[loading]');
for (var i = 0; i < images.length; i++) {
if (images[i].complete) {
images[i].classList.add('is-loaded');
} else {
images[i].addEventListener('load', function () {
this.classList.add('is-loaded');
}, false);
}
}</script><script defer="defer" src="https://www.finecloud.ch/media/plugins/syntaxHighlighter/prism.js"></script></body></html>