My new SecureView superclass seems to be causing a ConditionalOnMissingBean error

I’ve gone a ways down the rabbit-hole of creating my own custom handling for Shiro authentication and authorization, and now I’m designing a view superclass to facilitate controlling page access, since this requires custom handling as well. This is my first time creating a superclass which implements BeforeEnterObserver, so I may be missing something.
I’m autowiring a service for getting general info from Shiro.

public ShiroSvc shiroSvc;

I’m overriding beforeEnter to check for the annotations the views might have.

public void beforeEnter(BeforeEnterEvent event) {
    // Check access to the view
    if (!isAccessAllowed(event.getNavigationTarget())) {
        if (event.getUI().getSession().getAttribute("user") == null) {
            event.rerouteTo(HelloView.class);
        } else {
            event.rerouteTo(ErrorView.class);
        }
    }
    
    otherBeforeEnter(event);
    
}

I’m checking whether access is allowed based on annotations and user roles.

protected boolean isAccessAllowed(Class<?> viewClass) {
    // Implement your Shiro access checks here
    // Example: check if the subject has roles/permissions
    Subject subject = shiroSvc.getSubject();
    if (viewClass.isAnnotationPresent(RolesAllowed.class)) {
        RolesAllowed rolesAnnotation = viewClass.getAnnotation(RolesAllowed.class);
        for (String role : rolesAnnotation.value()) {
            if (subject.hasRole(role)) {
                return true;
            }
        }
        return false;
    }
    // Handle other annotations similarly
    else if (viewClass.isAnnotationPresent(PermitAll.class)) {
        return subject.isAuthenticated();
    }
    else if (viewClass.isAnnotationPresent(DenyAll.class)) {
        return false;
    }
    else if (viewClass.isAnnotationPresent(AnonymousAllowed.class)) {
        return true;
    }
    return false;
}

…and I’m allowing the subclass views to run their own BeforeEnter processes in this overridable method.

protected void otherBeforeEnter(BeforeEnterEvent event) {
    //Main BeforeEnter calls this method to enable subclasses to run their own BeforeEnter processes.
    //By default this method does nothing.
}

Before I added this superclass, the application ran fine. Now with this superclass in place, the my views subclassed to it, I’m getting this error causing the run to abend:

ConditionalOnMissingBean did not specify a bean using type, name or annotation and the attempt to deduce the bean’s type failed.

Any ideas?

How do you autowire the bean?

It sounds like you’ve already noticed something I’m missing. Much of this is new to me, so I’m learning quite a lot.

There are several bean annotations in my ShiroConfig class, for a SecurityManager method, a MethodInvokingFactoryBean method, a MyCustomRealm method, which returns a custom subclass of AuthorizingRealm. Does this class need an annotation? There’s also a ShiroFilterChainDefinition method in my ShiroConfig class, and a ShiroFilterFactoryBean method, both of which are annotated as beans. My ShiroSVC class is annotated as a service, and all references to it are annotated as autowired, including the one in my SecureView superclass. Other than my ShiroSvc and my overridden beforeEnter event, nothing else in my SecureView superclass is annotated.

What specific bean are you suggesting I autowire?

It’s hard to answer if I don’t see the code. Could you share your project or at least the most important classes

Also share the full error message

This project is just a Vaadin-flavored fleshing out of the Apache Shiro sample Spring Boot project, so it’s ok to share. I’ve created a second, public repo for this project, which you should be able to access here. I’m pretty confident that the new SecureView superclass is the one that’s causing the error.

Here’s the full stack trace:

2024-05-09 11:13:19.729 ERROR 14220 — [ restartedMain] o.s.boot.SpringApplication : Application run failed

java.lang.IllegalStateException: Error processing condition on com.vaadin.flow.spring.security.VaadinAwareSecurityContextHolderStrategyConfiguration.securityContextHolderStrategy
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:60) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
at org.springframework.context.annotation.ConditionEvaluator.shouldSkip(ConditionEvaluator.java:108) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForBeanMethod(ConfigurationClassBeanDefinitionReader.java:193) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitionsForConfigurationClass(ConfigurationClassBeanDefinitionReader.java:153) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.annotation.ConfigurationClassBeanDefinitionReader.loadBeanDefinitions(ConfigurationClassBeanDefinitionReader.java:129) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.processConfigBeanDefinitions(ConfigurationClassPostProcessor.java:343) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.annotation.ConfigurationClassPostProcessor.postProcessBeanDefinitionRegistry(ConfigurationClassPostProcessor.java:247) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanDefinitionRegistryPostProcessors(PostProcessorRegistrationDelegate.java:311) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.support.PostProcessorRegistrationDelegate.invokeBeanFactoryPostProcessors(PostProcessorRegistrationDelegate.java:112) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.support.AbstractApplicationContext.invokeBeanFactoryPostProcessors(AbstractApplicationContext.java:756) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:572) ~[spring-context-5.3.31.jar:5.3.31]
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:147) ~[spring-boot-2.7.18.jar:2.7.18]
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:732) ~[spring-boot-2.7.18.jar:2.7.18]
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:409) ~[spring-boot-2.7.18.jar:2.7.18]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:308) ~[spring-boot-2.7.18.jar:2.7.18]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.7.18.jar:2.7.18]
at org.springframework.boot.SpringApplication.run(SpringApplication.java:1289) ~[spring-boot-2.7.18.jar:2.7.18]
at org.vaadin.example.Application.main(Application.java:47) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:na]
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
at java.base/java.lang.reflect.Method.invoke(Method.java:566) ~[na:na]
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:50) ~[spring-boot-devtools-2.7.18.jar:2.7.18]
Caused by: java.lang.IllegalStateException: @ConditionalOnMissingBean did not specify a bean using type, name or annotation and the attempt to deduce the bean’s type failed
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$Spec.validate(OnBeanCondition.java:490) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$Spec.(OnBeanCondition.java:439) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition.getMatchOutcome(OnBeanCondition.java:155) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
at org.springframework.boot.autoconfigure.condition.SpringBootCondition.matches(SpringBootCondition.java:47) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
… 22 common frames omitted
Caused by: org.springframework.boot.autoconfigure.condition.OnBeanCondition$BeanTypeDeductionException: Failed to deduce bean type for com.vaadin.flow.spring.security.VaadinAwareSecurityContextHolderStrategyConfiguration.securityContextHolderStrategy
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$Spec.deducedBeanTypeForBeanMethod(OnBeanCondition.java:520) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$Spec.deducedBeanType(OnBeanCondition.java:509) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$Spec.(OnBeanCondition.java:432) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
… 24 common frames omitted
Caused by: java.lang.NoClassDefFoundError: org/springframework/security/core/context/SecurityContextHolderStrategy
at java.base/java.lang.ClassLoader.defineClass1(Native Method) ~[na:na]
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016) ~[na:na]
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:174) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.defineClass(BuiltinClassLoader.java:800) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.findClassOnClassPathOrNull(BuiltinClassLoader.java:698) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClassOrNull(BuiltinClassLoader.java:621) ~[na:na]
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:579) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
at java.base/java.lang.Class.forName0(Native Method) ~[na:na]
at java.base/java.lang.Class.forName(Class.java:398) ~[na:na]
at org.springframework.boot.devtools.restart.classloader.RestartClassLoader.loadClass(RestartClassLoader.java:145) ~[spring-boot-devtools-2.7.18.jar:2.7.18]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
at java.base/java.lang.Class.forName0(Native Method) ~[na:na]
at java.base/java.lang.Class.forName(Class.java:398) ~[na:na]
at org.springframework.boot.autoconfigure.condition.FilteringSpringBootCondition.resolve(FilteringSpringBootCondition.java:108) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$Spec.getReturnType(OnBeanCondition.java:528) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
at org.springframework.boot.autoconfigure.condition.OnBeanCondition$Spec.deducedBeanTypeForBeanMethod(OnBeanCondition.java:516) ~[spring-boot-autoconfigure-2.7.18.jar:2.7.18]
… 26 common frames omitted
Caused by: java.lang.ClassNotFoundException: org.springframework.security.core.context.SecurityContextHolderStrategy
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:581) ~[na:na]
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178) ~[na:na]
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ~[na:na]
… 44 common frames omitted

That’s weird because the cause is

java.lang.ClassNotFoundException: org.springframework.security.core.context.SecurityContextHolderStrategy

Did you update the dependencies?

I’ve updated the repo with the fix to the weird error. It was:

public class ShiroConfig extends VaadinWebSecurity {

Removing the “extends” part resolved the issue. I must have seen that “extends” part somewhere and thought it seemed like a good idea to add, while I was adding that SecureView superclass.

Thanks for your help!!

1 Like

I’m happy to solved the issue

1 Like