Micronaut Mastery: Parse String Value With Kb/Mb/Gb To Number
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.