{"id":6429,"date":"2020-09-10T08:23:14","date_gmt":"2020-09-10T12:23:14","guid":{"rendered":"http:\/\/springframework.guru\/?p=6429"},"modified":"2020-09-10T08:23:14","modified_gmt":"2020-09-10T12:23:14","slug":"immutable-property-binding","status":"publish","type":"post","link":"https:\/\/springframework.guru\/immutable-property-binding\/","title":{"rendered":"Immutable Property Binding"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p>In this article, we will look at Spring Framework&#8217;s support of immutable property binding.<\/p>\n<p>We described Spring external configuration in this <a href=\"http:\/\/springframework.guru\/spring-external-configuration-data\/\" target=\"_blank\" rel=\"noopener noreferrer\">article<\/a> and also provided a more detailed <a href=\"http:\/\/springframework.guru\/java-bean-properties-binding\/\" target=\"_blank\" rel=\"noopener noreferrer\">article<\/a> about the Java bean properties binding. In this article, we will demonstrate constructor binding using the merchant account configuration in this <a href=\"http:\/\/springframework.guru\/spring-external-configuration-data\/\" target=\"_blank\" rel=\"noopener noreferrer\">article<\/a>.<\/p>\n<p>Constructor binding enables immutability of <span style=\"font-weight: 400;\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties<\/code><\/span> annotated classes. Immutable property binding is recent addition to the Spring Framework, and is considered a best practice, since the bound values cannot be changed.<\/p>\n<h2>Constructor Binding<\/h2>\n<p><span style=\"font-weight: 400;\">When we want our configuration properties to be bound without getting errors we must ensure that our <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">Java<\/code> bean has setters. These setters are used by Spring to set the values provided in the external property sources.\u00a0 This is a requirement if our Spring Boot version is before 2.2.0. <\/span><\/p>\n<p><span style=\"font-weight: 400;\">Constructor binding is not supported in Spring Boot versions older than version 2.2.0. <\/span><\/p>\n<p><span style=\"font-weight: 400;\">Our sample Spring Boot application uses a version above 2.2.0. It will be possible to demonstrate constructor binding.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">To enable constructor binding we use the annotation <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConstructorBinding<\/code> . This annotation tells Spring to bind our configuration properties using the provided constructor instead of using the setters.<\/span><\/p>\n<h3>Usage<\/h3>\n<p>This annotation can be applied at class level or directly on the constructor.<\/p>\n<h4>Class level<\/h4>\n<p>This annotation can be applied at class level id and only if there is an ambiguous constructor. If we switch to constructor binding our class will look like this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConstructorBinding\r\n@ConfigurationProperties(prefix = \"merchantaccount\")\r\npublic class MerchantAccount {\r\n   private final String name;\r\n   private final String username;\r\n   private final String code;\r\n   private final int number;\r\n   private final String currency;\r\n\r\n   public MerchantAccount(String name, String username, String code, int number, String currency) {\r\n       this.name = name;\r\n       this.username = username;\r\n       this.code = code;\r\n       this.number = number;\r\n       this.currency = currency;\r\n   }\r\n    \/\/getters\r\n}\r\n<\/pre>\n<p>Then our configuration file will look like this.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@SpringBootApplication\r\n@EnableConfigurationProperties({MerchantAccount.class})\r\npublic class MyApplication {\r\n   public static void main(String[] args) {\r\n       SpringApplication.run(MyApplication.class, args);\r\n   }\r\n}\r\n<\/pre>\n<h4>Constructor level<\/h4>\n<p><span style=\"font-weight: 400;\">If our Java Bean has more than one constructor, then we cannot annotate at class\/type level instead we must use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConstructorBinding<\/code> directly on the constructor that should be bound. In our case, we have defined more than one constructor. We want our properties to be bound using the second constructor.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@ConfigurationProperties(prefix = \"merchantaccount\")\r\npublic class MerchantAccount {\r\n   private String name;\r\n   private String username;\r\n   private String code;\r\n   private int number;\r\n   private String currency;\r\n\r\n   public MerchantAccount(String name, String username, String code, int number, String currency) {\r\n       this.name = name;\r\n       this.username = username;\r\n       this.code = code;\r\n       this.number = number;\r\n       this.currency = currency;\r\n   }\r\n\r\n   @ConstructorBinding\r\n   public MerchantAccount(String username, String code, int number, String currency) {\r\n       this.username = username;\r\n       this.code = code;\r\n       this.number = number;\r\n       this.currency = currency;\r\n   }\r\n\r\n  \/\/getters\r\n}\r\n<\/pre>\n<p><span style=\"font-weight: 400;\">Let us add an API key object to our Java Bean as a nested member. Spring bounds all the nested members through their constructors if constructor binding is used. Therefore we need to provide its constructor as well. Now our Java bean will look like this.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties(prefix = \"merchantaccount\")\r\npublic class MerchantAccount {\r\n   private final String name;\r\n   private final String username;\r\n   private final String code;\r\n   private final int number;\r\n   private final String currency;\r\n   Private final ApiKey apikey;\r\n\r\n   @ConstructorBinding\r\n   public MerchantAccount(String name, String username, String code, int number, String currency, ApiKey apikey) {\r\n       this.name = name;\r\n       this.username = username;\r\n       this.code = code;\r\n       this.number = number;\r\n       this.currency = currency;\r\n       this.apikey = apikey;\r\n   }\r\n\r\n   public static class ApiKey {\r\n       private  final String key;\r\n       private final String type;\r\n\r\n       public ApiKey(String key, String type) {\r\n           this.key = key;\r\n           this.type = type;\r\n       }\r\n   }\r\n    \/\/getters and setters\r\n}\r\n<\/pre>\n<h3>Enabling @ConstructorBinding<\/h3>\n<p><span style=\"font-weight: 400;\">To enable this annotation we must use either <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@EnableConfigurationProperties<\/code> <\/span><span style=\"font-weight: 400;\">or the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@EnableConfigurationPropertiesScan<\/code> . We cannot use it with other enablers such as <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@Bean<\/code> or <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@Component<\/code> or beans loaded with <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@Import<\/code>.<\/span><\/p>\n<h2>Conclusion<\/h2>\n<p>We have touched base about the immutability of property binding. If constructor binding is not used then the setters will be used. However, constructor binding ensures that all the property fields are final thus no need for providing setters.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In this article, we will look at Spring Framework&#8217;s support of immutable property binding. We described Spring external configuration in this article and also provided a more detailed article about the Java bean properties binding. In this article, we will demonstrate constructor binding using the merchant account configuration in this article. Constructor binding enables [&hellip;]<a href=\"https:\/\/springframework.guru\/immutable-property-binding\/\" class=\"df-link-excerpt\">Continue reading<\/a><\/p>\n","protected":false},"author":111,"featured_media":4655,"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":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","enabled":false},"version":2}},"categories":[20,21,104],"tags":[27,40,29,30],"class_list":["post-6429","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-java","category-spring","category-spring-boot","tag-java","tag-spring","tag-spring-boot","tag-spring-framework"],"jetpack_publicize_connections":[],"aioseo_notices":[],"modified_by":"jt","jetpack_sharing_enabled":true,"jetpack_featured_media_url":"https:\/\/springframework.guru\/wp-content\/uploads\/2017\/07\/NewBannerBOOTSWeb.jpg","jetpack_shortlink":"https:\/\/wp.me\/p5BZrZ-1FH","_links":{"self":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/6429"}],"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\/111"}],"replies":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/comments?post=6429"}],"version-history":[{"count":5,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/6429\/revisions"}],"predecessor-version":[{"id":6438,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/6429\/revisions\/6438"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/media\/4655"}],"wp:attachment":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/media?parent=6429"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/categories?post=6429"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/tags?post=6429"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}