Search code examples
javakotlinmicrometerspring-micrometer

Why does CloudWatchConfig interface expect a String of step duration


I am using Micrometer Cloudwatch 1.1.3, brought in with Gradle as compile 'io.micrometer:micrometer-registry-cloudwatch:1.1.3'

In Java, I can create a CloudWatchConfig by doing the following:

    CloudWatchConfig cloudWatchConfig = new CloudWatchConfig() {
        @Override
        public String get(String s) {
            return "my-service-metrics";
        }

        @Override
        public boolean enabled() {
            return true;
        }

        @Override
        public Duration step() {
            return Duration.ofSeconds(30);
        }

        @Override
        public int batchSize() {
            return CloudWatchConfig.MAX_BATCH_SIZE;
        }
    };

The equivalent in Kotlin, I think should be:

   val cloudWatchConfig = CloudWatchConfig {
        fun get(s:String) = "my-service-metrics"
        fun enabled() = true
        fun step() = Duration.ofSeconds(30)
        fun batchSize() = CloudWatchConfig.MAX_BATCH_SIZE
   }

The Koltin compiler fails this, pointing out the last line in the block: fun batchSize() = CloudWatchConfig.MAX_BATCH_SIZE saying that it expected a value of type String?

After much debugging, I was able to fix this by returning the toString of the step function. You can't just pass any String through as it will be parsed as if it is generated by Duration. My Kotlin code now works and looks like the following:

    val cloudWatchConfig = CloudWatchConfig {
        fun get(s:String) = "my-service-metrics"
        fun enabled() = true
        fun step() = Duration.ofSeconds(30)
        fun batchSize() = CloudWatchConfig.MAX_BATCH_SIZE
        step().toString()
    }

After looking through the CloudWatchConfig, StepRegisteryConfig and MeterRegistryConfig interfaces I can't work out why this is the case. Why does Koltin do this, and why is it expecting the toString of a Duration?


Solution

  • To create the equivalent of an anonymous class in Java, the syntax is a bit different. You need to use the object keyword, and also include the override keywords for the interface methods. e.g.

    val cloudWatchConfig = object : CloudWatchConfig {
        override fun get(key: String) = "my-service-metrics"
        override fun enabled() = true
        override fun step() = Duration.ofSeconds(30)
        override fun batchSize() = CloudWatchConfig.MAX_BATCH_SIZE
    }