{"id":6425,"date":"2020-09-10T08:10:25","date_gmt":"2020-09-10T12:10:25","guid":{"rendered":"http:\/\/springframework.guru\/?p=6425"},"modified":"2024-10-21T06:43:37","modified_gmt":"2024-10-21T10:43:37","slug":"java-bean-properties-binding","status":"publish","type":"post","link":"https:\/\/springframework.guru\/java-bean-properties-binding\/","title":{"rendered":"Properties Binding with Spring: Simplify Configuration with @ConfigurationProperties"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p style=\"text-align: left;\"><span style=\"font-weight: 400;\">In this <\/span><span style=\"font-weight: 400;\"><a href=\"http:\/\/springframework.guru\/spring-external-configuration-data\/\" target=\"_blank\" rel=\"noopener noreferrer\">article<\/a>,<\/span><span style=\"font-weight: 400;\"> we explained why we should externalise our application configuration data. We also provided configuration examples that use various methods supported by Spring Boot. Within these methods was the Java bean properties binding but it was less detailed. Therefore in this article, we are going to give more details about using the payment service in the previous <\/span><a href=\"http:\/\/springframework.guru\/spring-external-configuration-data\/\" target=\"_blank\" rel=\"noopener noreferrer\"><span style=\"font-weight: 400;\">article<\/span><\/a><span style=\"font-weight: 400;\">.\u00a0<\/span><\/p>\n<p style=\"text-align: left;\">Our payment service requires merchant information which consists of many fields. We are not going to use <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Value<\/code> annotation because it will be cumbersome work. Using <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Value<\/code> requires us to annotate each and every property with <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Value<\/code>. Our code will look untidy if we do so. A workaround is to group the merchant details together in a POJO class. This POJO class is the one referred to as Java Bean. Its properties will be bound to the configuration file data when annotated with <span style=\"font-weight: 400;\"><code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties<\/code>.It will be easier for us to maintain these properties because they are at a single place and our code will be cleaner. Let us take a look at the comparison between <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Value<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties<\/code> annotations.<\/span><\/p>\n<h2>Features<\/h2>\n<p><span style=\"font-weight: 400;\">The table below shows the features supported by each of the configuration methods provided by the annotations,\u00a0 <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Value<\/code> and <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties<\/code>.<\/span><\/p>\n<table style=\"border-collapse: collapse; width: 100%; height: 110px;\">\n<tbody>\n<tr style=\"height: 22px;\">\n<td style=\"width: 33.3333%; height: 22px;\"><strong>Feature<\/strong><\/td>\n<td style=\"width: 33.3333%; height: 22px;\"><strong>@ConfigurationProperties<\/strong><\/td>\n<td style=\"width: 33.3333%; height: 22px;\"><strong>@Value<\/strong><\/td>\n<\/tr>\n<tr style=\"height: 22px;\">\n<td style=\"width: 33.3333%; height: 22px;\">Type-safety<\/td>\n<td style=\"width: 33.3333%; height: 22px;\">YES<\/td>\n<td style=\"width: 33.3333%; height: 22px;\">NO<\/td>\n<\/tr>\n<tr style=\"height: 22px;\">\n<td style=\"width: 33.3333%; height: 22px;\">Relaxed-binding<\/td>\n<td style=\"width: 33.3333%; height: 22px;\">YES<\/td>\n<td style=\"width: 33.3333%; height: 22px;\">NO<\/td>\n<\/tr>\n<tr style=\"height: 22px;\">\n<td style=\"width: 33.3333%; height: 22px;\">Meta-data support<\/td>\n<td style=\"width: 33.3333%; height: 22px;\">YES<\/td>\n<td style=\"width: 33.3333%; height: 22px;\">NO<\/td>\n<\/tr>\n<tr style=\"height: 22px;\">\n<td style=\"width: 33.3333%; height: 22px;\">SpEL Evaluation<\/td>\n<td style=\"width: 33.3333%; height: 22px;\">NO<\/td>\n<td style=\"width: 33.3333%; height: 22px;\">YES<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">This comparison shows that the<code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties<\/code> ticks more boxes compared to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Value<\/code>. It is a better option for our use-case that involves many configuration properties.<\/span><\/p>\n<h2>Properties Binding<\/h2>\n<p><span style=\"font-weight: 400;\">In order for us to understand how the Java Bean Properties binding works and how it is configured. We will use a step by step guide using the payments service from the previous <a href=\"http:\/\/springframework.guru\/spring-external-configuration-data\/\" target=\"_blank\" rel=\"noopener noreferrer\">article<\/a><\/span><span style=\"font-weight: 400;\">. <\/span><span style=\"font-weight: 400;\">The payment service shall be receiving payments made by customers for vendor services provided. This implies that we will be dealing with more than one vendor each with a unique merchant account. We must be able to identify the merchant account for each transaction request received.<\/span><\/p>\n<h3>Properties Names<\/h3>\n<p><span style=\"font-weight: 400;\">Let us first list the individual properties of the merchant account. Let us indicate the data type of each so that it becomes easy for us to set up its configuration in a Spring Application using a POJO class and the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties<\/code> annotation.<\/span><\/p>\n<table style=\"border-collapse: collapse; width: 100%; height: 154px;\">\n<tbody>\n<tr style=\"height: 22px;\">\n<td style=\"width: 25%; height: 22px;\"><strong>Configuration\/Setting<\/strong><\/td>\n<td style=\"width: 25%; height: 22px;\"><strong>Name of property<\/strong><\/td>\n<td style=\"width: 25%; height: 22px;\"><strong>Data type of property value<\/strong><\/td>\n<td style=\"width: 25%; height: 22px;\"><strong>Property type<\/strong><\/td>\n<\/tr>\n<tr style=\"height: 22px;\">\n<td style=\"width: 25%; height: 22px;\">Merchant Account<\/td>\n<td style=\"width: 25%; height: 22px;\">merchantaccount<\/td>\n<td style=\"width: 25%; height: 22px;\">key\/value(Map)<\/td>\n<td style=\"width: 25%; height: 22px;\">Object<\/td>\n<\/tr>\n<tr style=\"height: 22px;\">\n<td style=\"width: 25%; height: 22px;\"><\/td>\n<td style=\"width: 25%; height: 22px;\">name<\/td>\n<td style=\"width: 25%; height: 22px;\">String<\/td>\n<td style=\"width: 25%; height: 22px;\"><\/td>\n<\/tr>\n<tr style=\"height: 22px;\">\n<td style=\"width: 25%; height: 22px;\"><\/td>\n<td style=\"width: 25%; height: 22px;\">username<\/td>\n<td style=\"width: 25%; height: 22px;\">String<\/td>\n<td style=\"width: 25%; height: 22px;\"><\/td>\n<\/tr>\n<tr style=\"height: 22px;\">\n<td style=\"width: 25%; height: 22px;\"><\/td>\n<td style=\"width: 25%; height: 22px;\">code<\/td>\n<td style=\"width: 25%; height: 22px;\">String<\/td>\n<td style=\"width: 25%; height: 22px;\"><\/td>\n<\/tr>\n<tr style=\"height: 22px;\">\n<td style=\"width: 25%; height: 22px;\"><\/td>\n<td style=\"width: 25%; height: 22px;\">number<\/td>\n<td style=\"width: 25%; height: 22px;\">Number<\/td>\n<td style=\"width: 25%; height: 22px;\"><\/td>\n<\/tr>\n<tr style=\"height: 22px;\">\n<td style=\"width: 25%; height: 22px;\"><\/td>\n<td style=\"width: 25%; height: 22px;\">currency<\/td>\n<td style=\"width: 25%; height: 22px;\">String<\/td>\n<td style=\"width: 25%; height: 22px;\"><\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p><span style=\"font-weight: 400;\">We have identified the properties that we will use to get configuration values. Now let us create our properties file. In our case, we will use the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">YAML<\/code> <\/span><span style=\"font-weight: 400;\">format.<\/span><\/p>\n<p><em>application.yml<\/em><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">name: Maureen Sindiso Mpofu\nusername: momoe\ncode: MCA1230\nnumber: 771222279\ncurrency: ZWL<\/pre>\n<h3>Properties Grouping<\/h3>\n<p><span style=\"font-weight: 400;\">We now have our properties file, the next step is to bind them. To do this, first of all, we will create a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">Java<\/code><\/span><span style=\"font-weight: 400;\">class as indicated below.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">public class MerchantAccount {\n private String name;\n private String username;\n private String code;\n private int number;\n private String currency;\n\n public String getName() {\n  return name;\n }\n\n public void setName(String name) {\n  this.name = name;\n }\n\n public String getUsername() {\n  return username;\n }\n\n public void setUsername(String username) {\n  this.username = username;\n }\n \n public String getCode() {\n  return code;\n }\n\n public void setCode(String code) {\n  this.code = code;\n }\n\n public int getNumber() {\n  return number;\n }\n\n public void setNumber(int number) {\n  this.number = number;\n }\n\n public String getCurrency() {\n  return currency;\n }\n\n public void setCurrency(String currency) {\n  this.currency = currency;\n }\n}<\/pre>\n<h3>Enabling Java Bean Properties Binding<\/h3>\n<p><span style=\"font-weight: 400;\">There are many ways of binding our properties defined in our configuration file to our <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">Java<\/code> <\/span><span style=\"font-weight: 400;\">class we created in the previous section<\/span><span style=\"font-weight: 400;\">. We will annotate our <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">Java<\/code> class with <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties<\/code>. Inside this annotation, we will also specify the prefix of our properties so that Spring will be able to identify them in the properties file. In our case, the prefix is &#8220;merchantacccount&#8221;. The following are ways we can use to enable properties binding.<\/span><\/p>\n<h4>Annotating the Java bean class with @Component<\/h4>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Component\n@ConfigurationProperties(prefix = \"merchantaccount\")\npublic class MerchantAccount {\n   private String name;\n   private String userName;\n   private String code;\n   private int number;\n   private String currency;\n\n   \/\/getters and setters\n\n}\n<\/pre>\n<h3>Declaring it as a bean in the Spring configuration class<\/h3>\n<p><span style=\"font-weight: 400;\">This method is commonly used in scenarios where we want to bind the properties to third-party components.\u00a0 This is because most of the time we have no control of these third-party components. In the example below the merchant account class can be considered as a third-party component.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Configuration\npublic class PropertyConfigurations {\n    \n   @Bean\n   @ConfigurationProperties(prefix = \"merchantaccount\")\n   public MerchantAccount merchantAccount(){ \n      return new MerchantAccount();\n   }\n    \/\/other beans\n\n}\n<\/pre>\n<h3>Using @EnableConfigurationproperties annotation<\/h3>\n<p>When using this method, we must also specify the configuration classes as indicated below. Let us say we had another configuration class for connection settings then we can include it as well in this same annotation as indicated below.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@SpringBootApplication \n@EnableConfigurationProperties({MerchantAccount.class, ConnectionSettings.class})\npublic class MyApplication {\n   \n}\n<\/pre>\n<h3>Using @EnableConfigurationpropertiesScan annotation<\/h3>\n<p>This method will scan the package passed in the annotation. Any classes annotated with <span style=\"font-weight: 400;\"> <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties<\/code><\/span> found in this package will be bound automatically.<\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@SpringBootApplication \n@EnableConfigurationPropertiesScan(\u201ccom.springframeworkguru\u201d)\npublic class MyApplication {\n}<\/pre>\n<h2>Relaxed Binding<\/h2>\n<p><span style=\"font-weight: 400;\">In our example, the property name \u201cusername\u201d in our <code class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">Java<\/code> class matches the one defined in our configuration file. However, it is also possible to have different forms of property names in the configuration file for instance \u201cusername\u201d can also be represented as below. This is known as relaxed binding.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">merchantaccount:\n username: momoe        \/\/exact match\n userName: momoe        \/\/standard camel case\n user-name: momoe       \/\/kebab case recommended for use in .properties or .yml files\n user_name: momoe       \/\/underscore notation an alternative to kebab notation\n USER_NAME: momoe   \/\/uppercase format recommended when using system environment variables\n\n<\/pre>\n<h2>Constructor Binding<\/h2>\n<p>Take a look at this <a href=\"http:\/\/springframework.guru\/immutable-property-binding\/\" target=\"_blank\" rel=\"noopener noreferrer\">article<\/a> for more details.<\/p>\n<h2>Properties Conversion<\/h2>\n<p><span style=\"font-weight: 400;\">When binding external properties to the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@ConfigurationProperty<\/code> annotated Java Beans, Spring Boot attempts to match them to the target type. However, it is also possible to provide a custom type converter. There are various ways of providing a custom converter. Let us look at them in the following sections.<\/span><\/p>\n<h3>@ConfigurationPropertiesBinding annotation<\/h3>\n<p>First of all, we need to specify a property to our Java bean that has no default converter. Let us add a<span style=\"font-weight: 400;\"> property of type LocalDateTime.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties(prefix = \"merchantaccount\")\npublic class MerchantAccount {\n   private String name;\n   private String username;\n   private String code;\n   private int number;\n   private String currency;\n   private final LocalDateTime localDateTime;\n   \n   public LocalDateTime getLocalDateTime() {\n     return localDateTime;\n    }\n   public void setLocalDateTime(LocalDateTime localDateTime) {\n    this.localDateTime = localDateTime;\n    }\n\/\/other getters and setters\n}\n<\/pre>\n<p>Then configure <span style=\"font-weight: 400;\">its value in our external configuration file.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">merchantaccount:\n name: Maureen Sindiso Mpofu\n username: momoe\n code: MCA1230\n number: 771222279\n currency: ZWL\n localDateTime: 2011-12-03T10:15:30\n<\/pre>\n<p><span style=\"font-weight: 400;\">We must provide a custom converter so that we do not get a binding exception during application startup. We will use the annotation <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@ConfigurationPropertiesBinding<\/code> <\/span><span style=\"font-weight: 400;\">as shown below. This custom converter will convert the String input type in our configuration file to a <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">LocalDateTime<\/code> . Take note that we must register this converter as a bean indicated by <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@Component<\/code> annotation.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Component\n@ConfigurationPropertiesBinding\npublic class LocalDateTimeConverter implements Converter&lt;String,LocalDateTime&gt; {\n\n   @Override\n   public LocalDateTime convert(String s) {\n       return LocalDateTime.parse(s, DateTimeFormatter.ISO_LOCAL_DATE_TIME);\n   }\n}\n<\/pre>\n<h3>Conversion Service bean<\/h3>\n<p><span style=\"font-weight: 400;\">We can use the ConversionService bean instead of the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@ConfigurationPropertiesBinding<\/code> annotation. Spring picks up a ConversionService and uses it whenever type conversion needs to be performed. This conversion service is like any other bean thus can be injected into other beans and invoked directly. The default <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">ConversionService<\/code> can convert between strings, numbers, enums, collections, maps, and other common types.<\/span><\/p>\n<p><span style=\"font-weight: 400;\">However, there are other converters that are not provided by default for instance conversion to <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">LocalDateTime<\/code>. We can supplement the default converter with our own custom converter by defining a conversion service bean as indicated below. We only added our custom converter through the factory bean.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Bean\npublic  ConversionServiceFactoryBean conversionService(){\n  ConversionServiceFactoryBean conversionServiceFactoryBean= new ConversionServiceFactoryBean();\n  Set&lt;Converter&gt; converters = new HashSet&lt;&gt;();\n  converters.add(new CustomLocalDateTimeConverter());\n   conversionServiceFactoryBean.setConverters(converters);\n  return conversionServiceFactoryBean;\n}\n<\/pre>\n<p><span style=\"font-weight: 400;\">After we have defined our conversion service bean, Spring will be able to bind the value of <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">LocalDateTime<\/code> provided in our properties configuration file.<\/span><\/p>\n<h3>CustomEditorConfigurer<\/h3>\n<p><span style=\"font-weight: 400;\">If we had declared a field of type java.util.Date then we must tell Spring how it will bind the Date value specified in the property configuration file to this type. We can do this by\u00a0 configuring Spring\u2019s built-in\u00a0 <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">CustomDateEditor<\/code>\u00a0class as indicated below.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">public class CustomLocalDateTimeEditorRegistrar implements PropertyEditorRegistrar {\n   @Override\n   public void registerCustomEditors(PropertyEditorRegistry propertyEditorRegistry) {\n       propertyEditorRegistry.registerCustomEditor(Date.class,\n               new CustomDateEditor(new SimpleDateFormat(\"yyyy-MM-dd\"),false));\n   }\n}\n<\/pre>\n<p><span style=\"font-weight: 400;\">We then register it through the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">CustomeditorConfigurer<\/code>\u00a0 bean factory class as indicated below.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Bean\npublic CustomEditorConfigurer customEditorConfigurer(){\n   CustomEditorConfigurer customEditorConfigurer = new CustomEditorConfigurer();\n   PropertyEditorRegistrar[] registrars = {new CustomLocalDateTimeEditorRegistrar()};\n   customEditorConfigurer.setPropertyEditorRegistrars(registrars);\n   return customEditorConfigurer;\n}\n<\/pre>\n<h3>Duration Conversion<\/h3>\n<p><span style=\"font-weight: 400;\">Spring supports duration expressions. Let us add two more properties to our Java-bean class that are of type <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">java.time.Duration<\/code>\u00a0 i.e session timeout and read timeout.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties(prefix = \"merchantaccount\")\npublic class MerchantAccount {\n    private final Duration sessionTimeout;\n    private final Duration readTimeout;\n    \/\/other properties\n    public Duration getSessionTimeout() {\n      return sessionTimeout;\n    }\n   public void setSessionTimeout(Duration sessionTimeout) {\n     this.sessionTimeout = sessionTimeout;\n   }\n   public Duration getReadTimeout() {\n   return readTimeout;\n  }\n  public void setReadTimeout(Duration readTimeout) {\n   this.readTimeout = readTimeout;\n  } \n   \/\/ setters and getters of other fields\n}\n<\/pre>\n<p><span style=\"font-weight: 400;\">Then in our properties file let us specify their values as indicated below.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">merchantaccount:\n    sessionTimeout: 15\n    readTimeout: 10<\/pre>\n<p><span style=\"font-weight: 400;\">When we execute our application, the default unit for both session timeout and read timeout in milliseconds. This default unit can be overridden using either of the methods defined below.<\/span><\/p>\n<h4>@DurationUnit annotation<\/h4>\n<p><span style=\"font-weight: 400;\">We can use the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@DurationUnit<\/code>\u00a0 annotation directly on the field. We noticed that in some Spring boot versions this annotation does not work with constructor binding,\u00a0 the default unit takes precedence. A workaround is to use setters.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties(prefix = \"merchantaccount\")\npublic class MerchantAccount {\n    @DurationUnit(ChronoUnit.SECONDS)\n    private Duration readTimeout;\n    \/\/other fields\n}\n<\/pre>\n<h4>Coupling value and unit<\/h4>\n<p><span style=\"font-weight: 400;\">This is more readable. In the properties file, we can append the unit symbols to the value. Let us reset our read timeout and session timeout values to seconds. We do this by appending &#8216;s&#8217; to their values in our configuration file as indicated below.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">merchantaccount:\n    sessionTimeout: 15s\n    readTimeout: 10s<\/pre>\n<p><span style=\"font-weight: 400;\">The supported units are:<\/span><\/p>\n<ul>\n<li><em>ns<\/em>\u00a0<span style=\"font-weight: 400;\">for nanoseconds<\/span><\/li>\n<li style=\"font-weight: 400;\"><em><span style=\"font-weight: 400;\">us<\/span><\/em><span style=\"font-weight: 400;\"> for microseconds<\/span><\/li>\n<li style=\"font-weight: 400;\"><em><span style=\"font-weight: 400;\">ms<\/span><\/em><span style=\"font-weight: 400;\"> for milliseconds<\/span><\/li>\n<li style=\"font-weight: 400;\"><em><span style=\"font-weight: 400;\">s<\/span><\/em><span style=\"font-weight: 400;\"> for seconds<\/span><\/li>\n<li style=\"font-weight: 400;\"><em><span style=\"font-weight: 400;\">m<\/span><\/em><span style=\"font-weight: 400;\"> for minutes<\/span><\/li>\n<li style=\"font-weight: 400;\"><em><span style=\"font-weight: 400;\">h<\/span><\/em><span style=\"font-weight: 400;\"> for hours<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><em>d<\/em> for days<\/span><\/li>\n<\/ul>\n<h3>Data size Conversion<\/h3>\n<p><span style=\"font-weight: 400;\">Spring also supports DataSize property binding. The default unit type of byte. However, we can override this default as we did in the duration data type by using either <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@DataSizeUnit<\/code>\u00a0or couple the value and its unit on the configuration file. Let us define data size properties as indicated below.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties(prefix = \"merchantaccount\")\npublic class MerchantAccount {\n  private  DataSize bufferSize;\n  private DataSize threshold;\n   \n  public DataSize getBufferSize() {\n   return bufferSize;\n  }\n\n  public void setBufferSize(DataSize bufferSize) {\n   this.bufferSize = bufferSize;\n  }\n\n  public DataSize getThreshold() {\n   return threshold;\n  }\n\n  public void setThreshold(DataSize threshold) {\n   this.threshold = threshold;\n  }\n   \/\/  setters and getter of other fields\n}\n<\/pre>\n<p><span style=\"font-weight: 400;\">We then specify the values in the configuration file.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">merchantaccount:\n  bufferSize: 1\n threshold: 200\n<\/pre>\n<p><span style=\"font-weight: 400;\">When our application is executed, the buffer size and threshold size will be 1 byte and 200 bytes respectively. Now lets us override this default unit type and ensure that the buffer size is set to 1 gigabyte.<\/span><\/p>\n<h4>@DataSizeUnit annotation<\/h4>\n<p><span style=\"font-weight: 400;\">We apply this annotation directly to the property field as indicated below.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@ConfigurationProperties(prefix = \"merchantaccount\")\npublic class MerchantAccount {\n\n   @DataSizeUnit(DataUnit.GIGABYTES)\n    private  DataSize bufferSize;\n  \n    \/\/getters and setters\n}\n<\/pre>\n<p><span style=\"font-weight: 400;\">Now our buffer size will be set to 1 Gigabyte (1GB).<\/span><\/p>\n<h4>Coupling value and unit<\/h4>\n<p><span style=\"font-weight: 400;\">We can append the unit type on the value specified in our configuration file. The unit types supported include:<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><em>B<\/em> for bytes<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><em>KB<\/em> for kilobytes<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><em>MB<\/em> for megabytes<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><em>GB<\/em> for gigabytes<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\"><em>TB<\/em> for terabytes<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">In our configuration file let us append the unit type GB so that the buffer size becomes 1GB.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">merchantaccount:\n  bufferSize: 1GB\n  threshold: 200\n<\/pre>\n<h2>Properties Validation<\/h2>\n<p><span style=\"font-weight: 400;\">Spring validates the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@Configuration<\/code> classes when annotated with JSR-303 <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">javax.validation<\/code>\u00a0 constraint annotations. To ensure that this validation works we must add a JSR-303 implementation on our classpath. We then add the constraint annotations to our fields as indicated below.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties(prefix = \"merchantaccount\")\n@Validated   \npublic class MerchantAccount {\n\n   @NotNull\n   private final String name;\n   \/\/other property fields\n   \/\/getters and setters\n\n}\n<\/pre>\n<p><span style=\"font-weight: 400;\">The <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@Validated<\/code> annotation is mandatory. Below are options we can choose from to enable validation using this annotation.<\/span><\/p>\n<ul>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">At the class level on the annotated <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@ConfigurationProperties<\/code> class.<\/span><\/li>\n<li style=\"font-weight: 400;\"><span style=\"font-weight: 400;\">On the bean method that instantiates the configuration properties class.<\/span><\/li>\n<\/ul>\n<p><span style=\"font-weight: 400;\">We can apply this validation if some of our configuration properties need to be verified and validated before using them. Our application will fail at start-up if we do not declare the merchant name in our configuration file.<\/span><\/p>\n<h3>Nested Properties<\/h3>\n<p><span style=\"font-weight: 400;\">Our nested properties are also validated. It is recommended and also a good practice to also annotate them with <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@Valid<\/code>. This will trigger the validation even if there are no nested properties found.\u00a0<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@ConfigurationProperties(prefix = \"merchantaccount\")\n@Validated   \npublic class MerchantAccount {\n   @NotNull\n   private String name;\n   @Valid\n   private ApiKey apiKey;\n   public static class ApiKey{\n      @NotEmpty\n      public String name;\n   }\n   \/\/getters and setters\n}\n<\/pre>\n<h2>Usage of the Java Bean<\/h2>\n<p><span style=\"font-weight: 400;\">To work with <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@ConfigurationProperties<\/code><\/span><span style=\"font-weight: 400;\"> beans, you just need to inject them the same way as any other bean. See the example below.<\/span><\/p>\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"java\" data-enlighter-theme=\"git\">@Component\n@Slf4j\npublic class PaymentServiceImpl implements PaymentService {\n\n   private final MerchantAccount merchantAccount;\n\n   public PaymentServiceImpl(MerchantAccount merchantAccount) {\n       this.merchantAccount = merchantAccount;\n   }\n}<\/pre>\n<h2>Management<\/h2>\n<p><span style=\"font-weight: 400;\">In our application, we can include the spring-boot-actuator dependency in order to view all our @ConfigurationProperties beans. The spring-boot-actuator has an endpoint that exposes these beans and its URL path is \u2018\/actuator\/configprops\u2019.<\/span><\/p>\n<h2>Conclusion<\/h2>\n<p><span style=\"font-weight: 400;\">It recommended to externalise our configuration and if there are many configuration properties. We can group them into a simple <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">Java<\/code> class and use the <code class=\"EnlighterJSRAW\" data-enlighter-language=\"null\">@ConfigurationProperties<\/code> annotation to structure our configuration and make it type-safe. <\/span><\/p>\n<p><span style=\"font-weight: 400;\">However, the biggest challenge with externalising configuration is on the part of ensuring that the deployed application runs with the correct configuration. It is important to be careful when setting up an application that uses different property sources for different environments. The sample codes provided in this article are found<\/span><a href=\"https:\/\/github.com\/spring-framework-guru\/sfg-blog-posts\" target=\"_blank\" rel=\"noopener noreferrer\"> <span style=\"font-weight: 400;\">here<\/span><\/a><span style=\"font-weight: 400;\">.<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction In this article, we explained why we should externalise our application configuration data. We also provided configuration examples that use various methods supported by Spring Boot. Within these methods was the Java bean properties binding but it was less detailed. Therefore in this article, we are going to give more details about using the [&hellip;]<a href=\"https:\/\/springframework.guru\/java-bean-properties-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-6425","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-1FD","_links":{"self":[{"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/6425"}],"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=6425"}],"version-history":[{"count":6,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/6425\/revisions"}],"predecessor-version":[{"id":8236,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/posts\/6425\/revisions\/8236"}],"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=6425"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/categories?post=6425"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/springframework.guru\/wp-json\/wp\/v2\/tags?post=6425"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}