Affects: \<6.1.2> Reproducer: https://github.com/juliuskrah/graphql-demo/tree/spf-32487
Given this valid kotlin class:
class `20240318CreateProductTable` {
fun createProductTable() {
}
fun addProductData() {
}
}
and Bean class:
class ExampleBean {
lateinit var migrationClass: Class<*>
}
with a runtime bean definition:
@Configuration(proxyBeanMethods = false)
class MyConfig {
companion object {
@Bean
fun beanProcessor(): BeanFactoryPostProcessor {
return BeanFactoryPostProcessor {
if (it is DefaultListableBeanFactory) {
val beanDefinition = BeanDefinitionBuilder.rootBeanDefinition(ExampleBean::class.java)
.addPropertyValue("migrationClass", com.example.graph.migration.`20240318CreateProductTable`::class.java)
.beanDefinition
it.registerBeanDefinition("exampleBean", beanDefinition)
}
}
}
}
}
generates the following invalid java
class:
import com.example.graph.migration.20240318CreateProductTable;
import org.springframework.aot.generate.Generated;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.RootBeanDefinition;
@Generated
public class ExampleBean__BeanDefinitions {
/**
* Get the bean definition for 'exampleBean'.
*/
public static BeanDefinition getExampleBeanBeanDefinition() {
RootBeanDefinition beanDefinition = new RootBeanDefinition(ExampleBean.class);
beanDefinition.getPropertyValues().addPropertyValue("migrationClass", 20240318CreateProductTable.class);
beanDefinition.setInstanceSupplier(ExampleBean::new);
return beanDefinition;
}
}
that results in:
> Task :compileAotJava FAILED
/path/to/file/graphql-demo/build/generated/aotSources/com/example/graph/ExampleBean__BeanDefinitions.java:3: error: ';' expected
import com.example.graph.migration.20240318CreateProductTable;
^
/path/to/file/graphql-demo/build/generated/aotSources/com/example/graph/ExampleBean__BeanDefinitions.java:18: error: ')' or ',' expected
beanDefinition.getPropertyValues().addPropertyValue("migrationClass", 20240318CreateProductTable.class);
^
/path/to/file/graphql-demo/build/generated/aotSources/com/example/graph/ExampleBean__BeanDefinitions.java:18: error: not a statement
beanDefinition.getPropertyValues().addPropertyValue("migrationClass", 20240318CreateProductTable.class);
^
/path/to/file/graphql-demo/build/generated/aotSources/com/example/graph/ExampleBean__BeanDefinitions.java:18: error: ';' expected
beanDefinition.getPropertyValues().addPropertyValue("migrationClass", 20240318CreateProductTable.class);
^
4 errors
FAILURE: Build failed with an exception.
Expectation
Kotlin sources should generate Kotlin aotSources
Comment From: snicoll
Thanks for the report.
Kotlin sources should generate Kotlin aotSources
I can understand how, as a Kotlin user, you'd expect that but that would significantly increase the complexity of both the generation process and the tooling around it. There is no need to resort to that to fix this issue, Kotlin having different convention with class names is news to me, we'll just have to be more defensive about those.
Comment From: sdeleuze
As far as I can tell, Kotlin classes with backticks seems to be one of the rare cases where there is no workaround for Java interrop (@JvmName
can be applied to function or class generated in a Kotlin file, but not to customize an explicit Kotlin class name).
I am also not in favor of generating Kotlin code (far too involve) and not in favor throwing an exception because the regexp or algorithm designed to identify invalid class names could easily be wrong.
As a consequence, I turn this issue into a documentation one in order to document this limitation inherited from Kotlin own limitation in terms of Java interop.
Notice that backticks in class names, while technically possible, are not recommended in Kotlin coding conventions (usage of backticks is mainly for test methods).