Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Classes annotated with @Configuration could be implicitly subclassed and must not be final

Tags:

kotlin

I created a new project on Kotlin to generate a report. Knowing Kotlin can reduce number of lines of code and is safer than Java, I used Spring-jpa and Kotlin to get this done. All my @Configuration classes had an error:

Classes annotated with @Configuration could be implicitly subclassed and must not be final

FYI, I am using a maven project with Kotlin 1.3.50. From my knowledge, I knew that spring does subclass for injecting values.

How do I make spring happy but not keep writing open in each of my class where spring complains?

like image 576
NewUser Avatar asked Oct 20 '19 05:10

NewUser


People also ask

Can a @configuration class be final?

A class annotated with @Configuration cannot be final because Spring will use CGLIB to create a proxy for @Configuration class. CGLIB creates subclass for each class that is supposed to be proxied, however since the final class cannot have subclass CGLIB will fail.

Do we need @configuration in spring boot?

@Configuration is: not required, if you already pass the annotated class in the sources parameter when calling the SpringApplication. run() method; required, when you don't pass the annotated class explicitly, but it's in the package that's specified in the @ComponentScan annotation of your main configuration class.

Why are Kotlin classes final by default?

final: default The final modifier mark classes and methods as not allowed to be overridden. In Kotlin this is the default. This decision was made to avoid fragile base class problem. It happens when a small change in base classes (super classes) make subclasses to malfunction.

Can we Autowire a final class in spring?

Enabling @Autowired Annotations The Spring framework enables automatic dependency injection. In other words, by declaring all the bean dependencies in a Spring configuration file, Spring container can autowire relationships between collaborating beans. This is called Spring bean autowiring.


1 Answers

As you might already know, by default kotlin classes can not be extended. In order to support inheritance, you got to add open keyword. Also, we know for a fact that spring annotation processing needs classes marked as @Configuration can be subclassed.

The alternative of writing open in each of the classes is to add a plugin : kotlin-allopen

ex :

<plugin>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-maven-plugin</artifactId>
    <version>${kotlin.version}</version>
    <configuration>
        <compilerPlugins>
            <plugin>spring</plugin>
        </compilerPlugins>
    </configuration>
    <dependencies>
        <dependency>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-allopen</artifactId>
            <version>${kotlin.version}</version>
        </dependency>
    </dependencies>
    <executions>
        <execution>
            <id>compile</id>
            <phase>compile</phase>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>
        <execution>
            <id>test-compile</id>
            <phase>test-compile</phase>
            <goals>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>
</plugin>




<compilerPlugins>
    <plugin>spring</plugin>
</compilerPlugins>

The above does the trick of adding open to the following annotations: @Component, @Async, @Transactional, @Cacheable and @SpringBootTest. Thanks to meta-annotations support classes annotated with @Configuration, @Controller, @RestController, @Service or @Repository are automatically opened since these annotations are meta-annotated with @Component.

You can find the documentation here: https://kotlinlang.org/docs/reference/compiler-plugins.html

like image 87
NewUser Avatar answered Sep 28 '22 21:09

NewUser