Micronaut can convert String values defined as a number followed by (case-insensitive) KB/MB/GB
to a number value in certain cases. The conversion service in Micronaut supports the @ReadableBytes
annotation that we can apply to a method parameter. Micronaut will then parse the String value and convert it to a number. The value 1Kb
is converted to 1024
. We can use this for example in a configuration class or path variable in a controller.
In the following example we have a configuration class annotated with @ConfigurationProperties
with the property maxFileSize
. We use the @ReadableBytes
annotation to support setting the value with a String value:
package mrhaki; import io.micronaut.context.annotation.ConfigurationProperties; import io.micronaut.core.convert.format.ReadableBytes; @ConfigurationProperties(SampleConfig.SAMPLE_CONFIG_PREFIX) public class SampleConfig { public static final String SAMPLE_CONFIG_PREFIX = "sample.config"; private long maxFileSize; /** * Use @ReadableBytes for parameter {@code maxFileSize} * to convert a String value formatted as number followed * by "KB", "MB" or "GB" (case-insensitive). * * @param maxFileSize Maximum file size */ public void setMaxFileSize(@ReadableBytes long maxFileSize) { this.maxFileSize = maxFileSize; } public long getMaxFileSize() { return maxFileSize; } }
Let's write a Spock specification to test the conversion of String values to numbers:
package mrhaki import io.micronaut.context.ApplicationContext import spock.lang.Specification; class SampleConfigSpec extends Specification { void "set maxFileSize configuration property with KB/MB/GB format"() { given: final ApplicationContext context = ApplicationContext.run("sample.config.maxFileSize": maxFileSize) when: final SampleConfig sampleConfig = context.getBean(SampleConfig) then: sampleConfig.maxFileSize == result where: maxFileSize || result "20KB" || 20_480 "20kb" || 20 * 1024 "1MB" || 1_048_576 "1Mb" || 1 * 1024 * 1024 "3GB" || 3L * 1024 * 1024 * 1024 113 || 113 } }
In another example we use the conversion on a path variable parameter in a controller method:
package mrhaki; import io.micronaut.core.convert.format.ReadableBytes; import io.micronaut.http.annotation.Controller; import io.micronaut.http.annotation.Get; @Controller public class SampleController { @Get("/{size}") public long size(@ReadableBytes final long size) { return size; } }
And with the following test we can see if the conversion is done correctly:
package mrhaki import io.micronaut.context.ApplicationContext import io.micronaut.http.client.HttpClient import io.micronaut.runtime.server.EmbeddedServer import spock.lang.AutoCleanup import spock.lang.Shared import spock.lang.Specification class SampleControllerSpec extends Specification { @Shared @AutoCleanup private static EmbeddedServer server = ApplicationContext.run(EmbeddedServer) @Shared @AutoCleanup private static HttpClient httpClient = HttpClient.create(server.URL) void "return size converted from String value with unit KB/MB/GB"() { expect: httpClient.toBlocking().retrieve("/$size") == result where: size || result "20KB" || "20480" "20kb" || (20 * 1024).toString() "1MB" || 1_048_576.toString() "3GB" || (3L * 1024 * 1024 * 1024).toString() 113 || "113" } }
Written with Micronaut 1.0.4.