{"id":22741,"date":"2014-03-14T16:00:56","date_gmt":"2014-03-14T14:00:56","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=22741"},"modified":"2014-03-13T23:50:42","modified_gmt":"2014-03-13T21:50:42","slug":"tracking-exceptions-with-spring-part-2-delegate-pattern","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html","title":{"rendered":"Tracking Exceptions With Spring &#8211; Part 2 &#8211; Delegate Pattern"},"content":{"rendered":"<p>In <a href=\"http:\/\/www.javacodegeeks.com\/2014\/03\/tracking-application-exceptions-with-spring.html\" target=\"new\">my last blog<\/a>, I started to talk about the need to figure out whether or not your application is misbehaving in it&#8217;s production environment. I said that one method of monitoring your application is by checking its log files for exceptions and taking appropriate action if one is found. Obviously, log files can take up hundreds of megabytes of disk space and it&#8217;s impractical and really boring to monitor them by hand.<\/p>\n<p>I also said that there were several ways of automatically monitoring log files and proposed a Spring based utility that combs log files daily and sends you an email if \/ when it finds any exceptions.<\/p>\n<p>I only got as far as describing the first class: the <code>FileLocator<\/code>, which will search a directory and it&#8217;s sub-directories for log files. When it finds one, it passes it to the <code>FileValidator<\/code>.<br \/>\n<a name=\"more\"><\/a><\/p>\n<p>The <code>FileValidator<\/code> has to perform several checks on the file. Firstly, it has to determine whether the file is young enough to examine for exceptions. The idea is that as the application runs periodically, there&#8217;s no point in checking all the files found in the directory for errors, we only want those files that have been created or updated since the application last ran.<\/p>\n<p>The idea behind this design is to combine several implementations of the same interface, creating an aggregate object that\u2019s responsible for validating files. The eagle-eyed reader will notice that this is an implementation of the <a href=\"http:\/\/en.wikipedia.org\/wiki\/Delegation_pattern\" target=\"new\">Delegate Pattern<\/a>.<\/p>\n<p><a href=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/03\/Screen+Shot+2014-03-08+at+16.59.55.png\"><img decoding=\"async\" class=\"aligncenter size-full wp-image-22813\" alt=\"Screen+Shot+2014-03-08+at+16.59.55\" src=\"http:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/03\/Screen+Shot+2014-03-08+at+16.59.55.png\" width=\"320\" height=\"224\" srcset=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/03\/Screen+Shot+2014-03-08+at+16.59.55.png 574w, https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2014\/03\/Screen+Shot+2014-03-08+at+16.59.55-300x210.png 300w\" sizes=\"(max-width: 320px) 100vw, 320px\" \/><\/a><\/p>\n<p>In the class diagram above instances of <code>RegexValidator<\/code> and <code>FileAgeValidator<\/code> are injected into the <code>FileValidator<\/code> and it delegates its validation tasks to these classes.<\/p>\n<p>Taking each of these in turn and dealing with the <code>Validator<\/code> interface first\u2026<\/p>\n<pre class=\" brush:java\">public interface Validator { \r\n\r\n\u00a0 \/** The validation method *\/ \r\n\u00a0 public &lt;T&gt; boolean validate(T obj); \r\n\r\n}<\/pre>\n<p>The code above demonstrates the simplicity of the <code>Validator<\/code> interface. It has a single method <code>validate(T obj)<\/code>, which is a <a href=\"http:\/\/docs.oracle.com\/javase\/tutorial\/extra\/generics\/methods.html\" target=\"new\">Generic Method<\/a> call that increases the flexibility and re-usability of this interface. When classes implement this interface, they can change the input argument type to suit their own purposes\u2026 as demonstrated by the first implementation below:<\/p>\n<pre class=\" brush:java\">public class RegexValidator implements Validator { \r\n\r\n\u00a0 private static final Logger logger = LoggerFactory.getLogger(RegexValidator.class); \r\n\r\n\u00a0 private final Pattern pattern; \r\n\r\n\u00a0 public RegexValidator(String regex) { \r\n\u00a0\u00a0\u00a0 pattern = Pattern.compile(regex); \r\n\u00a0\u00a0\u00a0 logger.info(\"loaded regex: {}\", regex); \r\n\u00a0 } \r\n\r\n\u00a0 @Override \r\n\u00a0 public &lt;T&gt; boolean validate(T string) { \r\n\r\n\u00a0\u00a0\u00a0 boolean retVal = false; \r\n\u00a0\u00a0\u00a0 Matcher matcher = pattern.matcher((String) string); \r\n\u00a0\u00a0\u00a0 retVal = matcher.matches(); \r\n\u00a0\u00a0\u00a0 if (retVal &amp;&amp; logger.isDebugEnabled()) { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 logger.debug(\"Found error line: {}\", string); \r\n\u00a0\u00a0\u00a0 } \r\n\r\n\u00a0\u00a0\u00a0 return retVal; \r\n\u00a0 } \r\n}<\/pre>\n<p>The <code>RegexValidator<\/code> class has a single argument constructor that takes a Regular Expression string. This is then converted to a <code>Pattern<\/code> instance variable and is used by the <code>validate(T string)<\/code> method to test whether or not the <code>String<\/code> input argument matches original constructor arg regular expression. If it does, then <code>validate(T string)<\/code> will return true.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<pre class=\" brush:java\">@Service \r\npublic class FileAgeValidator implements Validator { \r\n\r\n\u00a0 @Value(\"${max.days}\") \r\n\u00a0 private int maxDays; \r\n\r\n\u00a0 \/** \r\n\u00a0\u00a0 * Validate the age of the file. \r\n\u00a0\u00a0 * \r\n\u00a0\u00a0 * @see com.captaindebug.errortrack.Validator#validate(java.lang.Object) \r\n\u00a0\u00a0 *\/ \r\n\u00a0 @Override \r\n\u00a0 public &lt;T&gt; boolean validate(T obj) { \r\n\r\n\u00a0\u00a0\u00a0 File file = (File) obj; \r\n\u00a0\u00a0\u00a0 Calendar fileDate = getFileDate(file); \r\n\r\n\u00a0\u00a0\u00a0 Calendar ageLimit = getFileAgeLimit(); \r\n\r\n\u00a0\u00a0\u00a0 boolean retVal = false; \r\n\u00a0\u00a0\u00a0 if (fileDate.after(ageLimit)) { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 retVal = true; \r\n\u00a0\u00a0\u00a0 } \r\n\r\n\u00a0\u00a0\u00a0 return retVal; \r\n\u00a0 } \r\n\r\n\u00a0 private Calendar getFileAgeLimit() { \r\n\r\n\u00a0\u00a0\u00a0 Calendar cal = Calendar.getInstance(); \r\n\u00a0\u00a0\u00a0 cal.add(Calendar.DAY_OF_MONTH, -1 * maxDays); \r\n\u00a0\u00a0\u00a0 return cal; \r\n\u00a0 } \r\n\r\n\u00a0 private Calendar getFileDate(File file) { \r\n\r\n\u00a0\u00a0\u00a0 long fileDate = file.lastModified(); \r\n\u00a0\u00a0\u00a0 Calendar when = Calendar.getInstance(); \r\n\u00a0\u00a0\u00a0 when.setTimeInMillis(fileDate); \r\n\u00a0\u00a0\u00a0 return when; \r\n\u00a0 } \r\n\r\n}<\/pre>\n<p>The second <code>Validator(T obj)<\/code> implementation is the <code>FileAgeValidator<\/code> shown above and the first thing to note is that the whole thing is driven by the <code>max.days<\/code> property. This is injected into the <code>FileAgeValidator<\/code>\u2019s <code>@Value<\/code> annotated <code>maxDays<\/code> instance variable. This variable determines the maximum age of the file in days. This the file is older than this value, then the <code>validate(T obj)<\/code> will return false.<\/p>\n<p>In this implementation, the <code>validate(T obj)<\/code> \u2018obj\u2019 argument is cast to a <code>File<\/code> object, which is then used to convert the date of the file into a <code>Calendar<\/code> object. The next line of code converts the <code>maxDays<\/code> variable into a second <code>Calendar<\/code> object: <code>ageLimit<\/code>. The <code>ageLimit<\/code> is then compared with the <code>fileDate<\/code> object. If the <code>fileDate<\/code> is after the <code>ageLimit<\/code> then <code>validate(T obj)<\/code> returns true.<\/p>\n<p>The final class in the <code>validator<\/code> package is the <code>FileValidator<\/code>, which as shown above delegates a lot of its responsibility to the other three other aggregated validators: one <code>FileAgeValidator<\/code> and two <code>RegexValidator<\/code>\u2019s.<\/p>\n<pre class=\" brush:java\">@Service \r\npublic class FileValidator implements Validator { \r\n\r\n\u00a0 private static final Logger logger = LoggerFactory.getLogger(FileValidator.class); \r\n\r\n\u00a0 @Value(\"${following.lines}\") \r\n\u00a0 private Integer extraLineCount; \r\n\r\n\u00a0 @Autowired \r\n\u00a0 @Qualifier(\"scan-for\") \r\n\u00a0 private RegexValidator scanForValidator; \r\n\r\n\u00a0 @Autowired(required = false) \r\n\u00a0 @Qualifier(\"exclude\") \r\n\u00a0 private RegexValidator excludeValidator; \r\n\r\n\u00a0 @Autowired \r\n\u00a0 private FileAgeValidator fileAgeValidator; \r\n\r\n\u00a0 @Autowired \r\n\u00a0 private Results results; \r\n\r\n\u00a0 @Override \r\n\u00a0 public &lt;T&gt; boolean validate(T obj) { \r\n\r\n\u00a0\u00a0\u00a0 boolean retVal = false; \r\n\u00a0\u00a0\u00a0 File file = (File) obj; \r\n\u00a0\u00a0\u00a0 if (fileAgeValidator.validate(file)) { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 results.addFile(file.getPath()); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 checkFile(file); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 retVal = true; \r\n\u00a0\u00a0\u00a0 } \r\n\u00a0\u00a0\u00a0 return retVal; \r\n\u00a0 } \r\n\r\n\u00a0 private void checkFile(File file) { \r\n\r\n\u00a0\u00a0\u00a0 try { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 BufferedReader in = createBufferedReader(file); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 readLines(in, file); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 in.close(); \r\n\u00a0\u00a0\u00a0 } catch (Exception e) { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 logger.error(\"Error whilst processing file: \" + file.getPath() + \" Message: \" + e.getMessage(), e); \r\n\u00a0\u00a0\u00a0 } \r\n\u00a0 } \r\n\r\n\u00a0 @VisibleForTesting \r\n\u00a0 BufferedReader createBufferedReader(File file) throws FileNotFoundException { \r\n\u00a0\u00a0\u00a0 BufferedReader in = new BufferedReader(new FileReader(file)); \r\n\u00a0\u00a0\u00a0 return in; \r\n\u00a0 } \r\n\r\n\u00a0 private void readLines(BufferedReader in, File file) throws IOException { \r\n\u00a0\u00a0\u00a0 int lineNumber = 0; \r\n\u00a0\u00a0\u00a0 String line; \r\n\u00a0\u00a0\u00a0 do { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 line = in.readLine(); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 if (isNotNull(line)) { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 processLine(line, file.getPath(), ++lineNumber, in); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 } \r\n\u00a0\u00a0\u00a0 } while (isNotNull(line)); \r\n\u00a0 } \r\n\r\n\u00a0 private boolean isNotNull(Object obj) { \r\n\u00a0\u00a0\u00a0 return obj != null; \r\n\u00a0 } \r\n\r\n\u00a0 private int processLine(String line, String filePath, int lineNumber, BufferedReader in) throws IOException { \r\n\r\n\u00a0\u00a0\u00a0 if (canValidateLine(line) &amp;&amp; scanForValidator.validate(line)) { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 List&lt;String&gt; lines = new ArrayList&lt;String&gt;(); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 lines.add(line); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 addExtraDetailLines(in, lines); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 results.addResult(filePath, lineNumber, lines); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 lineNumber += extraLineCount; \r\n\u00a0\u00a0\u00a0 } \r\n\r\n\u00a0\u00a0\u00a0 return lineNumber; \r\n\u00a0 } \r\n\r\n\u00a0 private boolean canValidateLine(String line) { \r\n\u00a0\u00a0\u00a0 boolean retVal = true; \r\n\u00a0\u00a0\u00a0 if (isNotNull(excludeValidator)) { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 retVal = !excludeValidator.validate(line); \r\n\u00a0\u00a0\u00a0 } \r\n\u00a0\u00a0\u00a0 return retVal; \r\n\u00a0 } \r\n\r\n\u00a0 private void addExtraDetailLines(BufferedReader in, List&lt;String&gt; lines) throws IOException { \r\n\r\n\u00a0\u00a0\u00a0 for (int i = 0; i &lt; extraLineCount; i++) { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 String line = in.readLine(); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 if (isNotNull(line)) { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 lines.add(line); \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 } else { \r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 break; \r\n\u00a0\u00a0\u00a0\u00a0\u00a0 } \r\n\u00a0\u00a0\u00a0 } \r\n\u00a0 } \r\n\r\n}<\/pre>\n<p>The <code>FileValidator<\/code>\u2019s <code>validate(T obj)<\/code> takes a <code>File<\/code> as an argument. Its first responsibility is to validate the age of the file. If that validator returns true, then it informs the <code>Report<\/code> class that it\u2019s found a new, valid file. It then checks the file for errors, adding any it finds to the <code>Report<\/code> instance. It does this by using a <code>BufferedReader<\/code> to check each line of the file in turn. Before checking whether a line contains an error, it checks that the line isn\u2019t excluded from the check &#8211; i.e. that it doesn\u2019t match the excluded exceptions or ones we&#8217;re not interested in. If the line doesn\u2019t match the excluded exceptions, then it\u2019s checked for exceptions that we need to find using the second instance of the <code>RegexValidator<\/code>. If the line does contain an error it\u2019s added to a <code>List&lt;String&gt;<\/code> object. A number of following lines are then read from the file added to the list to make the report more readable.<\/p>\n<p>And so, the file parsing continues, checking each line at a time looking for errors and building up a report, which can be processed later.<\/p>\n<p>That cover\u2019s validating files using Delegate Pattern adding any exceptions found to the <code>Report<\/code>, but how does this <code>Report<\/code> object work? I&#8217;ve not mentioned it, and how is the output generated? More on that next time.<\/p>\n<ul>\n<li>The code for this blog is available on Github at: <a href=\"https:\/\/github.com\/roghughe\/captaindebug\/tree\/master\/error-track\" target=\"new\">https:\/\/github.com\/roghughe\/captaindebug\/tree\/master\/error-track<\/a>.<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<div style=\"border: 1px solid #D8D8D8; background: #FAFAFA; width: 100%; padding-left: 5px;\"><b><i>Reference: <\/i><\/b><a href=\"http:\/\/www.captaindebug.com\/2014\/03\/tracking-exceptions-with-spring-part-2.html\">Tracking Exceptions With Spring &#8211; Part 2 &#8211; Delegate Pattern<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\">JCG partner<\/a> Roger Hughes at the <a href=\"http:\/\/www.captaindebug.com\/\">Captain Debug&#8217;s Blog <\/a> blog.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>In my last blog, I started to talk about the need to figure out whether or not your application is misbehaving in it&#8217;s production environment. I said that one method of monitoring your application is by checking its log files for exceptions and taking appropriate action if one is found. Obviously, log files can take &hellip;<\/p>\n","protected":false},"author":65,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30],"class_list":["post-22741","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Tracking Exceptions With Spring - Part 2 - Delegate Pattern<\/title>\n<meta name=\"description\" content=\"In my last blog, I started to talk about the need to figure out whether or not your application is misbehaving in it&#039;s production environment. I said that\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tracking Exceptions With Spring - Part 2 - Delegate Pattern\" \/>\n<meta property=\"og:description\" content=\"In my last blog, I started to talk about the need to figure out whether or not your application is misbehaving in it&#039;s production environment. I said that\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2014-03-14T14:00:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Roger Hughes\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Roger Hughes\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html\"},\"author\":{\"name\":\"Roger Hughes\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/c9feacaf8e783104a69621cd65bf1f07\"},\"headline\":\"Tracking Exceptions With Spring &#8211; Part 2 &#8211; Delegate Pattern\",\"datePublished\":\"2014-03-14T14:00:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html\"},\"wordCount\":789,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Spring\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html\",\"name\":\"Tracking Exceptions With Spring - Part 2 - Delegate Pattern\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2014-03-14T14:00:56+00:00\",\"description\":\"In my last blog, I started to talk about the need to figure out whether or not your application is misbehaving in it's production environment. I said that\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2014\\\/03\\\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"Tracking Exceptions With Spring &#8211; Part 2 &#8211; Delegate Pattern\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/c9feacaf8e783104a69621cd65bf1f07\",\"name\":\"Roger Hughes\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/db9d1e5362dbc3f8007b383b852473b59fb8c5282a6066a13ab1cef761a9d5d6?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/db9d1e5362dbc3f8007b383b852473b59fb8c5282a6066a13ab1cef761a9d5d6?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/db9d1e5362dbc3f8007b383b852473b59fb8c5282a6066a13ab1cef761a9d5d6?s=96&d=mm&r=g\",\"caption\":\"Roger Hughes\"},\"sameAs\":[\"http:\\\/\\\/www.captaindebug.com\\\/\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/Roger-Hughes\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tracking Exceptions With Spring - Part 2 - Delegate Pattern","description":"In my last blog, I started to talk about the need to figure out whether or not your application is misbehaving in it's production environment. I said that","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html","og_locale":"en_US","og_type":"article","og_title":"Tracking Exceptions With Spring - Part 2 - Delegate Pattern","og_description":"In my last blog, I started to talk about the need to figure out whether or not your application is misbehaving in it's production environment. I said that","og_url":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2014-03-14T14:00:56+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Roger Hughes","twitter_card":"summary_large_image","twitter_creator":"@javacodegeeks","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Roger Hughes","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html"},"author":{"name":"Roger Hughes","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/c9feacaf8e783104a69621cd65bf1f07"},"headline":"Tracking Exceptions With Spring &#8211; Part 2 &#8211; Delegate Pattern","datePublished":"2014-03-14T14:00:56+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html"},"wordCount":789,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Spring"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html","url":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html","name":"Tracking Exceptions With Spring - Part 2 - Delegate Pattern","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2014-03-14T14:00:56+00:00","description":"In my last blog, I started to talk about the need to figure out whether or not your application is misbehaving in it's production environment. I said that","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2014\/03\/tracking-exceptions-with-spring-part-2-delegate-pattern.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"Tracking Exceptions With Spring &#8211; Part 2 &#8211; Delegate Pattern"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/c9feacaf8e783104a69621cd65bf1f07","name":"Roger Hughes","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/db9d1e5362dbc3f8007b383b852473b59fb8c5282a6066a13ab1cef761a9d5d6?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/db9d1e5362dbc3f8007b383b852473b59fb8c5282a6066a13ab1cef761a9d5d6?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/db9d1e5362dbc3f8007b383b852473b59fb8c5282a6066a13ab1cef761a9d5d6?s=96&d=mm&r=g","caption":"Roger Hughes"},"sameAs":["http:\/\/www.captaindebug.com\/"],"url":"https:\/\/www.javacodegeeks.com\/author\/Roger-Hughes"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/22741","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/65"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=22741"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/22741\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=22741"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=22741"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=22741"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}