{"id":1258,"date":"2015-06-12T17:40:28","date_gmt":"2015-06-12T21:40:28","guid":{"rendered":"http:\/\/springframework.guru\/?p=1258"},"modified":"2019-06-01T06:00:28","modified_gmt":"2019-06-01T10:00:28","slug":"running-code-on-spring-boot-startup","status":"publish","type":"post","link":"https:\/\/springframework.guru\/running-code-on-spring-boot-startup\/","title":{"rendered":"Running Code on Spring Boot Startup"},"content":{"rendered":"<p>One of the things I love about the Grails environment is that it comes with a handy bootstrap.groovy file. This will run at startup of the Spring container. I frequently use this to setup expected data, or to create test data for integration \/ functional tests. It can be a very convenient way to seed an H2 database with startup values.<\/p>\n<p>The Spring Framework itself does not have the concept for a bootstrap file like Grails does. It does, however, have events that we can subscribe to and functionally accomplish the same thing.<\/p>\n<h2>Spring Framework Events<\/h2>\n<p>The Spring Framework comes out of the box with a number of events, and you&#8217;re able to extend the event functionality for your own purposes.<\/p>\n<h3>Spring Core Events<\/h3>\n<h4>ContextRefreshedEvent<\/h4>\n<p>This event is published whenever the Spring Context is started or refreshed.<\/p>\n<h4>ContextStartedEvent<\/h4>\n<p>This event is published when the Spring Context is started.<\/p>\n<h4>ContextStoppedEvent<\/h4>\n<p>This event is published when the Spring Context is stopped. In practice, you will not use this event very often. It can be handy for doing cleanup work, like closing connections.<\/p>\n<h4>ContextClosedEvent<\/h4>\n<p>This event is similar to the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ContextStoppedEvent<\/code>, but in this case, the Context cannot be re-started.<\/p>\n<h3>Spring Boot Events<\/h3>\n<p>Spring Boot introduces several new events on top of the events available in the core Spring Framework.<\/p>\n<h4>ApplicationStartedEvent<\/h4>\n<p>This event is published early in the startup of a Spring Application. The Spring Context is running but may change later in the lifecycle.<\/p>\n<h4>ApplicationEnvironmentPreparedEvent<\/h4>\n<p>This event is published when the Spring Boot Application is starting up and is first available for inspection and modification.<\/p>\n<h4>ApplicationPreparedEvent<\/h4>\n<p>This event is published when the Spring Context is fully prepared but not refreshed. At this point, the Spring Beans are loaded, configured and ready for use.<\/p>\n<h4>ApplicationFailedEvent<\/h4>\n<p>This event is published when the Spring Boot Application fails to start. This event is useful for error logging or alerting.<\/p>\n<h2>Using Spring Framework Events<\/h2>\n<p>Under the scenario we want to do something on startup we have two events we can consider using. Traditionally under Spring Framework, we can use the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ContextRefreshedEvent<\/code>. This event has been around since the beginning of the Spring Framework.<\/p>\n<p>If you&#8217;re using Spring Boot, you do have additional events to select from. I often want to use a startup event to seed data for tests, so in this case, I need the database connection to be set up. Reading about the Spring Boot Events, I thought the event I would like to use is <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ApplicationPreparedEvent<\/code>. But in testing it out, this was not the case. I ran into some issues with getting the event listeners set up properly in the Spring Boot Context. I found better results using the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">ContextRefreshedEvent<\/code>.<\/p>\n<h3>ContextRefreshedEvent Listener<\/h3>\n<p>Here is an example of a listener. Here, I&#8217;m injecting a simple bean to prove I got a message. In practice, this bean could be whatever you wanted. You could, for example, inject a Spring Data Repository into your listener bean.<\/p>\n<h4>ContextRefresehedListener.java<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.contextrefresh;\r\n\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.context.ApplicationListener;\r\nimport org.springframework.context.event.ContextRefreshedEvent;\r\nimport org.springframework.stereotype.Component;\r\n\r\n@Component\r\npublic class ContextRefreshedListener implements ApplicationListener&lt;ContextRefreshedEvent&gt;{\r\n\r\n    private EventHolderBean eventHolderBean;\r\n\r\n    @Autowired\r\n    public void setEventHolderBean(EventHolderBean eventHolderBean) {\r\n        this.eventHolderBean = eventHolderBean;\r\n    }\r\n\r\n    @Override\r\n    public void onApplicationEvent(ContextRefreshedEvent contextRefreshedEvent) {\r\n        System.out.println(\"Context Event Received\");\r\n        eventHolderBean.setEventFired(true);\r\n    }\r\n}<\/pre>\n<h4>EventHolderBean.java<\/h4>\n<p>Nothing very special about this bean. I have an event fired property, which I initialize to false. If it is true, I know the bean &#8216;processed&#8217; and event.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.contextrefresh;\r\n\r\nimport org.springframework.stereotype.Component;\r\n\r\n@Component\r\npublic class EventHolderBean {\r\n    private Boolean eventFired = false;\r\n\r\n    public Boolean getEventFired() {\r\n        return eventFired;\r\n    }\r\n\r\n    public void setEventFired(Boolean eventFired) {\r\n        this.eventFired = eventFired;\r\n    }\r\n}<\/pre>\n<h3>Running the Event Bean in Spring Boot<\/h3>\n<p>I can run this bean in a Spring Boot Application. Below is my application class.<\/p>\n<h4>ContextRefreshedApplication.java<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.contextrefresh;\r\n\r\nimport org.springframework.boot.SpringApplication;\r\nimport org.springframework.boot.autoconfigure.SpringBootApplication;\r\nimport org.springframework.context.ConfigurableApplicationContext;\r\n\r\n@SpringBootApplication\r\npublic class ContextRefresehedApplication {\r\n    public static void main(String[] args) {\r\n        ConfigurableApplicationContext ctx = SpringApplication.run(ContextRefresehedApplication.class, args);\r\n        EventHolderBean bean = ctx.getBean(EventHolderBean.class);\r\n        System.out.println(\"Event Processed?? - \" + bean.getEventFired());\r\n    }\r\n}\r\n<\/pre>\n<h4>Output<\/h4>\n<p>In the output, you can see my console messages.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\">   .   ____          _            __ _ _\r\n \/\\\\ \/ ___'_ __ _ _(_)_ __  __ _ \\ \\ \\ \\\r\n( ( )\\___ | '_ | '_| | '_ \\\/ _` | \\ \\ \\ \\\r\n \\\\\/  ___)| |_)| | | | | || (_| |  ) ) ) )\r\n  '  |____| .__|_| |_|_| |_\\__, | \/ \/ \/ \/\r\n =========|_|==============|___\/=\/_\/_\/_\/\r\n :: Spring Boot ::        (v1.2.3.RELEASE)\r\n\r\n2015-06-12 17:24:47.158  INFO 14158 --- [           main] g.s.b.c.ContextRefresehedApplication     : Starting ContextRefresehedApplication on Johns-MacBook-Pro.local with PID 14158 (\/Users\/jt\/src\/springframework.guru\/blogposts\/target\/classes started by jt in \/Users\/jt\/src\/springframework.guru\/blogposts)\r\n2015-06-12 17:24:47.217  INFO 14158 --- [           main] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@e874448: startup date [Fri Jun 12 17:24:47 EDT 2015]; root of context hierarchy\r\n2015-06-12 17:24:48.484  INFO 14158 --- [           main] o.s.j.e.a.AnnotationMBeanExporter        : Registering beans for JMX exposure on startup\r\nContext Event Received\r\n2015-06-12 17:24:48.564  INFO 14158 --- [           main] g.s.b.c.ContextRefresehedApplication     : Started ContextRefresehedApplication in 1.804 seconds (JVM running for 2.454)\r\nEvent Processed?? - true\r\n2015-06-12 17:24:48.566  INFO 14158 --- [       Thread-1] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@e874448: startup date [Fri Jun 12 17:24:47 EDT 2015]; root of context hierarchy\r\n2015-06-12 17:24:48.567  INFO 14158 --- [       Thread-1] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown\r\n\r\nProcess finished with exit code 0\r\n<\/pre>\n<h3>Testing the Spring Event Bean<\/h3>\n<p>I can also set this up in a JUnit test. This will actually run outside of Spring Boot and in a normal Spring context.<\/p>\n<p>To do this I need to set up a simple Java configuration bean for my test.<\/p>\n<h4>ContextRefreshConfig.java<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.contextrefresh.config;\r\n\r\nimport org.springframework.context.annotation.ComponentScan;\r\nimport org.springframework.context.annotation.Configuration;\r\n\r\n@Configuration\r\n@ComponentScan(\"guru.springframework.blog.contextrefresh\")\r\npublic class ContextRefreshConfig {\r\n}\r\n<\/pre>\n<h4>ContextRefresehedListenerTest.java<\/h4>\n<p>Here I have a simple JUnit test which brings up the Spring Context and gets an instance of the Event Holder Bean. I check to make sure the event fired is set to true, proving the bean did, in fact, get manipulated by the event listener.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">package guru.springframework.blog.contextrefresh;\r\n\r\nimport guru.springframework.blog.contextrefresh.config.ContextRefreshConfig;\r\nimport org.junit.Test;\r\nimport org.junit.runner.RunWith;\r\nimport org.springframework.beans.factory.annotation.Autowired;\r\nimport org.springframework.test.context.ContextConfiguration;\r\nimport org.springframework.test.context.junit4.SpringJUnit4ClassRunner;\r\n\r\nimport static org.junit.Assert.*;\r\n\r\n@RunWith(SpringJUnit4ClassRunner.class)\r\n@ContextConfiguration(classes = {ContextRefreshConfig.class})\r\npublic class ContextRefreshedListenerTest {\r\n\r\n    private EventHolderBean eventHolderBean;\r\n\r\n    @Autowired\r\n    public void setEventHolderBean(EventHolderBean eventHolderBean) {\r\n        this.eventHolderBean = eventHolderBean;\r\n    }\r\n\r\n    @Test\r\n    public void testContext(){\r\n         assertTrue(eventHolderBean.getEventFired());\r\n    }\r\n}\r\n<\/pre>\n<h4>Test Output<\/h4>\n<p>In the output of the test, I can see the console output of the event listener.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\" data-enlighter-linenumbers=\"false\"> 17:32:18.902 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'lifecycleProcessor'\r\n17:32:18.903 [main] DEBUG o.s.b.f.s.DefaultListableBeanFactory - Returning cached instance of singleton bean 'contextRefreshedListener'\r\nContext Event Received\r\n17:32:18.905 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemProperties]\r\n17:32:18.906 [main] DEBUG o.s.c.e.PropertySourcesPropertyResolver - Searching for key 'spring.liveBeansView.mbeanDomain' in [systemEnvironment]\r\n<\/pre>\n\r\n\t<div class=\"df_call_to_action df_content_element cta_round\"  data-cta-class=\"normal\" data-cta-bg-color=\"#D3D3D3\" data-cta-border-color=\"#0F0F0F\">\r\n\t    <div class=\"cta_wrapper\">\r\n\t    \t<div class=\"cta_header\"><h3 style=\"color:#6cb44a !important;\">Free Introduction to Spring Tutorial<\/h3><\/div>\r\n\t\t    <div class=\"cta_content\">Are you new to the Spring Framework? Checkout my Free Introduction to Spring Online Tutorial.<\/div>\r\n\t    <\/div>\r\n\t     \r\n\t    \t<div class=\"cta_button\">\r\n\t<div class=\"btn_warpper position_right\">\r\n\t\t<a class=\" btn btn_s btn_rounded\" href=\"https:\/\/go.springframework.guru\/intro-to-spring\" title=\"https:\/\/go.springframework.guru\/intro-to-spring\" target=\"_self\"  data-button-class=\"flat\" data-button-color=\"#6cb44a\" data-button-color-hover=\"#C0C0C0\" data-button-border-color=\"#000000\" data-button-border-color-hover=\"#6cb44a\" data-button-bottom-color=\"#FF8080\" data-button-bottom-color-hover=\"#FF8080\" data-font-color=\"#FFFFFF\" data-font-color-hover=\"#000000\">\r\n\t\t\t\t\t\t\r\n\t\t\t\t<span>Learn More<\/span>\r\n\t\t\t\t\t\t\r\n\t\t<\/a>\r\n\t<\/div>\r\n<\/div>\r\n\t     \r\n\t<\/div>\r\n\n<h2>Get The\u00a0Code<\/h2>\n<p>I&#8217;ve committed the source code for this post to github. It is a Maven project which you can download and build. If you wish to learn more about the Spring Framework, I have a free introduction to Spring tutorial. You can sign up for this tutorial in the section below.<\/p>\n\r\n\t<div class=\"df_call_to_action df_content_element cta_square\"  data-cta-class=\"normal\" data-cta-bg-color=\"#0F0F0F\" data-cta-border-color=\"#0F0F0F\">\r\n\t    <div class=\"cta_wrapper\">\r\n\t    \t<div class=\"cta_header\"><h3 style=\"color:#6cb44a !important;\">Source Code<\/h3><\/div>\r\n\t\t    <div class=\"cta_content\">The source code for this post is available on github. You can download it <a title=\"Blog Posts Github Repo\" href=\"https:\/\/github.com\/springframeworkguru\/blogposts\" target=\"_blank\" rel=\"noopener noreferrer\">here<\/a>.<\/div>\r\n\t    <\/div>\r\n\t     \r\n\t<\/div>\r\n\n<h2 style=\"color: #6cb44a;\"><\/h2>\n","protected":false},"excerpt":{"rendered":"<p>One of the things I love about the Grails environment is that it comes with a handy bootstrap.groovy file. This will run at startup of the Spring container. I frequently use this to setup expected data, or to create test data for integration \/ functional tests. It can be a very convenient way to seed [&hellip;]<a href=\"https:\/\/springframework.guru\/running-code-on-spring-boot-startup\/\" class=\"df-link-excerpt\">Continue reading<\/a><\/p>\n","protected":false},"author":1,"featured_media":4581,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_lmt_disableupdate":"","_lmt_disable":"","_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Running Code on Spring Boot Startup https:\/\/wp.me\/p5BZrZ-ki #spring #springboot","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[21,104,6],"tags":[60,40,29,30],"class_list":["post-1258","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-spring","category-spring-boot","category-spring-core","tag-junit","tag-spring","tag-spring-boot","tag-spring-framework"],"jetpack_publicize_connections":[],"aioseo_notices":[],"modified_by":"Simanta","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/springframework.guru\/wp-content\/uploads\/2019\/05\/Banner560x292_08Web.jpg","jetpack_shortlink":"https:\/\/wp.me\/p5BZrZ-ki","_links":{"self":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/1258"}],"collection":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/comments?post=1258"}],"version-history":[{"count":9,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/1258\/revisions"}],"predecessor-version":[{"id":5334,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/1258\/revisions\/5334"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/media\/4581"}],"wp:attachment":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/media?parent=1258"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/categories?post=1258"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/tags?post=1258"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}