<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>dpromanko</title>
    <link>/</link>
    <description>Recent content on dpromanko</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en-us</language>
    <lastBuildDate>Mon, 20 May 2019 18:32:19 -0400</lastBuildDate><atom:link href="/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>My Java Spring @Scheduled methods stopped running in production</title>
      <link>/posts/spring-scheduled-annotation/</link>
      <pubDate>Mon, 20 May 2019 18:32:19 -0400</pubDate>
      
      <guid>/posts/spring-scheduled-annotation/</guid>
      <description>The first time The first time I encountered this issue was an @Scheduled annotation wrapping a method that performed a long(ish) running query. For example:
java    @Scheduled(fixedRate = 600000) public void scheduledMethod() { System.out.println(&amp;#34;I am running&amp;#34;); performSomeLongRunningQuery(); System.out.println(&amp;#34;I am done&amp;#34;); }   This works great, right? For months in production, my query had been running every 10 minutes as I so clearly told it to until one day I got a call that indicated to me that is was no longer running.</description>
      <content>&lt;h3 id=&#34;the-first-time&#34;&gt;The first time&lt;/h3&gt;
&lt;p&gt;The first time I encountered this issue was an @Scheduled annotation wrapping a method that performed a long(ish) running query. For example:&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;1&#34; type=&#34;checkbox&#34;  /&gt;
    &lt;label for=&#34;1&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;java&lt;/span&gt;
      
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-java&#34; &gt;&lt;code&gt;
@Scheduled(fixedRate = 600000)
public void scheduledMethod() {
  System.out.println(&amp;#34;I am running&amp;#34;);
  performSomeLongRunningQuery();
  System.out.println(&amp;#34;I am done&amp;#34;);
}
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;p&gt;This works great, right? For months in production, my query had been running every 10 minutes as I so clearly told it to until one day I got a call that indicated to me that is was no longer running. Sure enough, after checking the logs of this code above I saw a message stating &amp;ldquo;I am running&amp;rdquo;, but there was no &amp;ldquo;I am done&amp;rdquo; message. To my knowledge, once this happens to a snippet such as the one above your only option is to restart the application. As expected after a restart we were back up and running every 10 minutes. So what went wrong? I was able to confirm that the query did indeed finish executing on the database, so why didn&amp;rsquo;t it return? I won&amp;rsquo;t get into details, but I believe the connection to the database was severed. At this point, I figured we just got lucky (or unlucky) and I forgot about it.&lt;/p&gt;
&lt;h3 id=&#34;the-second-time&#34;&gt;The second time&lt;/h3&gt;
&lt;p&gt;The second time I encountered an @Scheduled method that stopped running (in a different application) was an @Scheduled annotation wrapping a method that performed an API call. Another developer and I were looking into this and I immediately knew what was wrong and how to fix it, although this time I had no idea what caused it. We restarted the application and everything was back to normal. I should also note, this application has more than just one @Scheduled method and we noticed those were no longer running either.&lt;/p&gt;
&lt;h3 id=&#34;time-to-figure-out-what-happened&#34;&gt;Time to figure out what happened&lt;/h3&gt;
&lt;p&gt;Clearly now it was time for me to better understand what is actually going on under the hood of the @Scheduled annotation. As soon as I got home from work I started playing around with the little demo below.&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;1&#34; type=&#34;checkbox&#34;  /&gt;
    &lt;label for=&#34;1&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;java&lt;/span&gt;
      
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-java&#34; &gt;&lt;code&gt;
public class DemoSchedule {

  @Scheduled(fixedRate = 1000)
  public void scheduledMethod() {
    System.out.println(&amp;#34;I am only going to run once&amp;#34;);
    sleepy();
  }

  public void sleepy() {
    System.out.println(&amp;#34;sleeping&amp;#34;);
    try {
      Thread.sleep(60000);
    } catch (InterruptedException e) {
      e.printStackTrace();
    }
    sleepy();
  }

}
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;p&gt;This example demonstrates what happens to an @Scheduled method that never returns and more importantly never throws an exception. Simply adding&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;1&#34; type=&#34;checkbox&#34;  /&gt;
    &lt;label for=&#34;1&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;java&lt;/span&gt;
      
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-java&#34; &gt;&lt;code&gt;
throw new Exception();
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;p&gt;anywhere inside the method &lt;code&gt;sleepy()&lt;/code&gt; will cause the behavior I want/expect. When the exception is thrown the scheduled method will complete and run again.&lt;/p&gt;
&lt;p&gt;Even more to my surprise if you add another @Scheduled method, it won&amp;rsquo;t run while &lt;code&gt;scheduledMethod()&lt;/code&gt; is running forever. I didn&amp;rsquo;t know why this was the case because I never looked at the documentation for @EnableScheduling.&lt;/p&gt;
&lt;h3 id=&#34;the-documentation&#34;&gt;The documentation&lt;/h3&gt;
&lt;p&gt;Taken from the Spring &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableScheduling.html&#34;&gt;EnableScheduling&lt;/a&gt; documentation:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;By default, will be searching for an associated scheduler definition: either a unique TaskScheduler bean in the context, or a TaskScheduler bean named &amp;ldquo;taskScheduler&amp;rdquo; otherwise; the same lookup will also be performed for a ScheduledExecutorService bean. If neither of the two is resolvable, a local single-threaded default scheduler will be created and used within the registrar.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Takeaways from the above documentation:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;The default scheduler is only allotted one thread, which is why the method above will only run once.&lt;/li&gt;
&lt;li&gt;All @Scheduled annotations share the same thread pool, which means all other @Scheduled annotations would be blocked from executing in the above example.&lt;/li&gt;
&lt;/ol&gt;
&lt;blockquote class=&#34;twitter-tweet&#34;&gt;&lt;p lang=&#34;en&#34; dir=&#34;ltr&#34;&gt;Remember, a few hours of trial and error can save you several minutes of looking at the README.&lt;/p&gt;&amp;mdash; I Am Devloper (@iamdevloper) &lt;a href=&#34;https://twitter.com/iamdevloper/status/1060067235316809729?ref_src=twsrc%5Etfw&#34;&gt;November 7, 2018&lt;/a&gt;&lt;/blockquote&gt;
&lt;script async src=&#34;https://platform.twitter.com/widgets.js&#34; charset=&#34;utf-8&#34;&gt;&lt;/script&gt;

&lt;h3 id=&#34;how-many-scheduled-methods-could-be-executed-simultaneously&#34;&gt;How many @Scheduled methods could be executed simultaneously?&lt;/h3&gt;
&lt;p&gt;If you only have one @Scheduled method in your application then technically you are fine with leaving it with the default single thread. Although, I&amp;rsquo;m willing to bet when you add another you won&amp;rsquo;t remember to increase the thread pool so it is probably worth doing it now.&lt;/p&gt;
&lt;p&gt;If more than one @Scheduled method in your application could be overlap, then you should look at implementing &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/SchedulingConfigurer.html&#34;&gt;SchedulingConfigurer&lt;/a&gt;. As you can see in the example below you will implement this on a class that is annotated with @Configuration and @EnableScheduling. One thing to note about the example below is they are using 100 as the thread pool size. To my knowledge, the number here doesn&amp;rsquo;t really matter as long as it is at least the number of @Scheduled methods that could overlap, that way no @Scheduled method is ever waiting on another to finish before running.&lt;/p&gt;
&lt;p&gt;Taken from the Spring &lt;a href=&#34;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/scheduling/annotation/EnableScheduling.html&#34;&gt;EnableScheduling&lt;/a&gt; documentation:&lt;/p&gt;



  &lt;div class=&#34;collapsable-code&#34;&gt;
    &lt;input id=&#34;1&#34; type=&#34;checkbox&#34;  /&gt;
    &lt;label for=&#34;1&#34;&gt;
      &lt;span class=&#34;collapsable-code__language&#34;&gt;java&lt;/span&gt;
      
      &lt;span class=&#34;collapsable-code__toggle&#34; data-label-expand=&#34;Show&#34; data-label-collapse=&#34;Hide&#34;&gt;&lt;/span&gt;
    &lt;/label&gt;
    &lt;pre class=&#34;language-java&#34; &gt;&lt;code&gt;
@Configuration
@EnableScheduling
public class AppConfig implements SchedulingConfigurer {

    @Override
    public void configureTasks(ScheduledTaskRegistrar taskRegistrar) {
        taskRegistrar.setScheduler(taskExecutor());
    }

    @Bean(destroyMethod=&amp;#34;shutdown&amp;#34;)
    public Executor taskExecutor() {
        return Executors.newScheduledThreadPool(100);
    }
}
&lt;/code&gt;&lt;/pre&gt;
  &lt;/div&gt;


&lt;h3 id=&#34;is-there-any-chance-your-scheduled-method-will-never-exit&#34;&gt;Is there any chance your @Scheduled method will never exit?&lt;/h3&gt;
&lt;p&gt;This one is on you to figure out based on what you are doing in each of your @Scheduled methods. As I showed with the &lt;code&gt;sleepy()&lt;/code&gt; example, if the method never returns, or throws an exception, it will never run again. Both times my @Scheduled methods stopped running in production could have been prevented with the proper timeout configurations on the datasource/HTTP client.&lt;/p&gt;
&lt;h3 id=&#34;the-end&#34;&gt;The end&lt;/h3&gt;
&lt;p&gt;If you made it this far, thanks for reading my first technical blog post! I acknowledge this is nothing profound and nothing you couldn&amp;rsquo;t learn from reading the documentation. I just wanted to share a little story about something that broke in production and what I learned from it.&lt;/p&gt;
&lt;p&gt;If you think any of this information is wrong, have questions/comments, or have any feedback then please reach out to me on &lt;a href=&#34;https://twitter.com/dpromanko&#34;&gt;Twitter&lt;/a&gt;!&lt;/p&gt;
</content>
    </item>
    
    <item>
      <title>Hello, World!</title>
      <link>/posts/hello-world/</link>
      <pubDate>Wed, 01 May 2019 07:17:29 -0400</pubDate>
      
      <guid>/posts/hello-world/</guid>
      <description>The man behind the blog post I have been working as a software developer for 3 years now. I write primarily Java and Angular at work but I have been spending my mornings before work learning Go. I have been practicing yoga for just over 2 years and I have my wife to thank for getting me into it. I enjoy two cups of coffee a day and my preferred brewing method is pour over.</description>
      <content>&lt;h3 id=&#34;the-man-behind-the-blog-post&#34;&gt;The man behind the blog post&lt;/h3&gt;
&lt;p&gt;I have been working as a software developer for 3 years now. I write primarily Java and Angular at work but I have been spending my mornings before work learning Go. I have been practicing yoga for just over 2 years and I have my wife to thank for getting me into it. I enjoy two cups of coffee a day and my preferred brewing method is pour over. My local coffee shop introduced me to this method and I haven&amp;rsquo;t looked back (shout out to The Clay Cup in Altoona). Meditation is the newest addition to my list of favorite things. I have been practicing 20 minutes of meditation a day for the last 102 days.&lt;/p&gt;
&lt;h3 id=&#34;why-hugo&#34;&gt;Why Hugo?&lt;/h3&gt;
&lt;p&gt;I&amp;rsquo;m sure a lot of you are wondering why I made a site with Hugo&amp;hellip;and by a lot of you I mean nobody because I&amp;rsquo;ve never written a blog post before. Here is a short list of why I am choosing Hugo because if you have made it this far I&amp;rsquo;m sure you are just dying to know.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It is written in Go and I can&amp;rsquo;t get enough of that Gopher.&lt;/li&gt;
&lt;li&gt;I get to use a theme which means I don&amp;rsquo;t have to write any CSS.&lt;/li&gt;
&lt;li&gt;It was recommended by a co-worker. Check out his blog &lt;a href=&#34;https://adminwillie.github.io/&#34;&gt;here&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Even if I don&amp;rsquo;t stick with writing blog posts, this is better than my old website.&lt;/li&gt;
&lt;li&gt;Markdown is pretty cool I guess.&lt;/li&gt;
&lt;/ul&gt;
</content>
    </item>
    
    <item>
      <title>About me</title>
      <link>/about/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      
      <guid>/about/</guid>
      <description>I am Devon Romanko, a senior software engineer at DICK&amp;rsquo;s Sporting Goods. I work remotely from Pittsburgh, PA.
I am primarily a Java developer but I am also comfortable on the front end with Angular. I love building resilient applications that keep working when things go wrong, writing tools/scripts that help other developers be more efficient, and reviewing code from my peers. My current hobby language has been Go for the past few years and I look for any excuse to use it.</description>
      <content>&lt;p&gt;I am Devon Romanko, a senior software engineer at DICK&amp;rsquo;s Sporting Goods. I work remotely from Pittsburgh, PA.&lt;/p&gt;
&lt;p&gt;I am primarily a Java developer but I am also comfortable on the front end with Angular. I love building resilient applications that keep working when things go wrong, writing tools/scripts that help other developers be more efficient, and reviewing code from my peers. My current hobby language has been Go for the past few years and I look for any excuse to use it.&lt;/p&gt;
&lt;p&gt;A few of my favorite things outside of tech include yoga, meditation, video games, and single-origin coffee. I have been practicing yoga since 2017, practicing meditation since 2019, and playing video games my whole life.&lt;/p&gt;
&lt;h3 id=&#34;where-you-can-find-me&#34;&gt;Where you can find me&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&#34;https://github.com/dpromanko&#34;&gt;GitHub&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&#34;https://twitter.com/dpromanko&#34;&gt;Twitter&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&#34;/me.jpg&#34; alt=&#34;Me&#34;&gt;&lt;/p&gt;
</content>
    </item>
    
  </channel>
</rss>
