'Error in PreAuthorize annotation with hasRole('ROLE_ADMIN')

The controller in my application is mentioned below and I get the error when I try to start the Application:

@RestController
@CrossOrigin
@RequestMapping("/api/admin")
@PreAuthorize("hasRole('ROLE_ADMIN')")
class AdminController (private val userRepository: UserRepository, private val roleRepository: RoleRepository) {

    @GetMapping("/getUsers")
    fun getUsers(): List<UserResponseAdmin> {
        return userRepository.findAll().stream().map { user: User ->
            UserResponseAdmin(user)
        }.collect(Collectors.toList())
    }
}
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'adminController' defined in file [E:\_dev\appspring\target\classes\de\totwart\appspring\controller\AdminController.class]: Initialization of bean failed; nested exception is org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class de.totwart.appspring.controller.AdminController: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class de.totwart.appspring.controller.AdminController
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:628)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:542)
    at ...
Caused by: org.springframework.aop.framework.AopConfigException: Could not generate CGLIB subclass of class de.totwart.apppongspring.controller.AdminController: Common causes of this problem include using a final class or a non-visible class; nested exception is java.lang.IllegalArgumentException: Cannot subclass final class de.totwart.apppongspring.controller.AdminController
    at org.springframework.aop.framework.CglibAopProxy.getProxy(CglibAopProxy.java:209)
    at org.springframework.aop.framework.ProxyFactory.getProxy(ProxyFactory.java:110)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.createProxy(AbstractAutoProxyCreator.java:478)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.wrapIfNecessary(AbstractAutoProxyCreator.java:342)
    at org.springframework.aop.framework.autoproxy.AbstractAutoProxyCreator.postProcessAfterInitialization(AbstractAutoProxyCreator.java:291)
    at 

When I remove the annotation, everything is working fine. I don't understand the issue. Why its saying that I am using a final class, when I don't.

Any Ideas, what I can try?

PS: found the solution. @PreAuthorize maybe extends the AdminController, so AdminController must be "open"

open class AdminController



Solution 1:[1]

Unlike Java, all classes in Kotlin are by default closed or final.

Why does this matter when you add the @PreAuthorize ? - well, what Spring does is inject some behaviour around the method to enforce the check. That is implemented by subclassing your original class, hence the need for your class to be open. Many other parts of the Spring framework use this same subclassing technique, so it is a very common requirement to need to open all your Controller and similar classes.

As you found yourself, adding the open keyword fixes this but you can make a project-wide change if you simply include a special dependency called Kotlin-Allopen. Find out more here: https://www.baeldung.com/kotlin/allopen-spring

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AndrewL