I have an application that is currently secured with Spring Security and using the Spring Security login form, but I wanted to switch to using the new to Vaadin 13+ login addon. I’m running into an odd error during setup.
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'com.company.inventoryapp.LoginView': Instantiation of bean failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.company.inventoryapp.LoginView]
: Constructor threw exception; nested exception is java.lang.StackOverflowError
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1287)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1181)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:305)
at com.vaadin.flow.spring.SpringInstantiator.getOrCreate(SpringInstantiator.java:88)
at com.vaadin.flow.di.Instantiator.createRouteTarget(Instantiator.java:158)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.lambda$getRouteTarget$1(AbstractNavigationStateRenderer.java:121)
at java.util.Optional.orElseGet(Optional.java:267)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.getRouteTarget(AbstractNavigationStateRenderer.java:120)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:178)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.reroute(AbstractNavigationStateRenderer.java:385)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:218)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.reroute(AbstractNavigationStateRenderer.java:385)
... the AbstractNavigationStateRenderer line repeats for a while...
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.elavon.inventoryapp.LoginView]
: Constructor threw exception; nested exception is java.lang.StackOverflowError
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:184)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1279)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1181)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:305)
at com.vaadin.flow.spring.SpringInstantiator.getOrCreate(SpringInstantiator.java:88)
at com.vaadin.flow.di.Instantiator.createRouteTarget(Instantiator.java:158)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.lambda$getRouteTarget$1(AbstractNavigationStateRenderer.java:121)
at java.util.Optional.orElseGet(Optional.java:267)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.getRouteTarget(AbstractNavigationStateRenderer.java:120)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:178)
... 1011 more
Caused by: java.lang.StackOverflowError
at java.lang.reflect.InvocationTargetException.<init>(InvocationTargetException.java:72)
at sun.reflect.GeneratedConstructorAccessor52.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.security.Provider$Service.newInstance(Provider.java:1595)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:236)
at sun.security.jca.GetInstance.getInstance(GetInstance.java:164)
at java.security.Security.getImpl(Security.java:730)
at java.security.MessageDigest.getInstance(MessageDigest.java:167)
at com.vaadin.flow.internal.MessageDigestUtil.getSha256(MessageDigestUtil.java:49)
at com.vaadin.flow.internal.MessageDigestUtil.sha256(MessageDigestUtil.java:44)
at com.vaadin.flow.internal.ConstantPoolKey.calculateHash(ConstantPoolKey.java:94)
at com.vaadin.flow.internal.ConstantPoolKey.<init>(ConstantPoolKey.java:55)
at com.vaadin.flow.internal.nodefeature.ElementListenerMap.updateEventSettings(ElementListenerMap.java:362)
at com.vaadin.flow.internal.nodefeature.ElementListenerMap.add(ElementListenerMap.java:291)
at com.vaadin.flow.dom.impl.BasicElementStateProvider.addEventListener(BasicElementStateProvider.java:237)
at com.vaadin.flow.dom.Element.addEventListener(Element.java:513)
at com.vaadin.flow.component.ComponentEventBus.addDomTrigger(ComponentEventBus.java:262)
at com.vaadin.flow.component.ComponentEventBus.lambda$addDomTriggerIfNeeded$1(ComponentEventBus.java:226)
at java.util.Optional.map(Optional.java:215)
at com.vaadin.flow.component.ComponentEventBus.addDomTriggerIfNeeded(ComponentEventBus.java:225)
at com.vaadin.flow.component.ComponentEventBus.addListenerInternal(ComponentEventBus.java:143)
at com.vaadin.flow.component.ComponentEventBus.addListener(ComponentEventBus.java:101)
at com.vaadin.flow.component.Component.addListener(Component.java:331)
at com.vaadin.flow.component.ComponentUtil.addListener(ComponentUtil.java:338)
at com.vaadin.flow.component.login.AbstractLogin.addLoginListener(AbstractLogin.java:161)
at com.vaadin.flow.component.login.AbstractLogin.<init>(AbstractLogin.java:63)
at com.vaadin.flow.component.login.LoginForm.<init>(LoginForm.java:35)
at com.elavon.inventoryapp.LoginView.<init>(LoginView.java:34)
at sun.reflect.GeneratedConstructorAccessor57.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:172)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:87)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateBean(AbstractAutowireCapableBeanFactory.java:1279)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1181)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:305)
at com.vaadin.flow.spring.SpringInstantiator.getOrCreate(SpringInstantiator.java:88)
at com.vaadin.flow.di.Instantiator.createRouteTarget(Instantiator.java:158)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.lambda$getRouteTarget$1(AbstractNavigationStateRenderer.java:121)
at java.util.Optional.orElseGet(Optional.java:267)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.getRouteTarget(AbstractNavigationStateRenderer.java:120)
at com.vaadin.flow.router.internal.AbstractNavigationStateRenderer.handle(AbstractNavigationStateRenderer.java:178)
... 979 more
My SecurityConfig
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private static final String LOGIN_PROCESSING_URL = "/login";
private static final String LOGIN_FAILURE_URL = "/login";
private static final String LOGIN_URL = "/login";
private static final String LOGOUT_SUCCESS_URL = "/";
@Override
protected void configure(HttpSecurity http) throws Exception {
/**
* Not using Spring CSRF here to be able to use plain HTML for the login page, Vaadin has its own CSRF protection
*/
http.csrf().disable()
// Register our CustomRequestCache, that saves unauthorized access attempts, so
// the user is redirected after login.
.requestCache().requestCache(new CustomRequestCache())
.and()
.authorizeRequests()
// Allow all flow internal requests.
.requestMatchers(SecurityUtils::isFrameworkInternalRequest).permitAll()
// Allow all requests by logged in users.
.anyRequest().authenticated()
.and()
// Sets up login page
.formLogin().loginPage(LOGIN_URL).permitAll().loginProcessingUrl(LOGIN_PROCESSING_URL)
.failureUrl(LOGIN_FAILURE_URL)
// Register the success handler that redirects users to the page they last tried to access
.successHandler(new SavedRequestAwareAuthenticationSuccessHandler())
.and()
// Configure logout
.logout().logoutSuccessUrl(LOGOUT_SUCCESS_URL).permitAll()
.and()
// Limits users to a single session
.sessionManagement().maximumSessions(1)
;
}
// ? Consider allowing for login from a created user, not just an LDAP authenticated user
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.ldapAuthentication()
.userDnPatterns("uid={0},ou=people")
.groupSearchBase("ou=groups")
.contextSource()
.url("ldap://localhost:8389/dc=springframework,dc=org")
.and()
.passwordCompare()
// ! Deprecated as insecure (see import), should only be needed during dev for test data
.passwordEncoder(new LdapShaPasswordEncoder())
.passwordAttribute("userPassword")
.and()
.ldapAuthoritiesPopulator(authPopulator())
;
}
@Bean(name = "ldapAuthoritiesPopulator")
public CustomLdapAuthoritiesPopulator authPopulator() {
CustomLdapAuthoritiesPopulator populator = new CustomLdapAuthoritiesPopulator();
return populator;
}
/**
* Allows access to static resources, bypassing Spring security.
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers(
// Vaadin Flow static resources //
"/VAADIN/**",
// the standard favicon URI
"/favicon.ico",
// the robots exclusion standard
"/robots.txt",
// web application manifest //
"/manifest.webmanifest",
"/sw.js",
"/offline-page.html",
// (development mode) static resources //
"/frontend/**",
// (development mode) webjars //
"/webjars/**",
// (production mode) static resources //
"/frontend-es5/**", "/frontend-es6/**");
}
}
and my LoginView
@Route(value = "login")
@PageTitle("Login")
public class LoginView extends VerticalLayout {
private LoginForm login = new LoginForm(); //
public LoginView(){
login.setAction("login"); //
getElement().appendChild(login.getElement()); //
}
}
I’m fairly certain it has something to do with how I have the LDAP authentication set up, but I can’t figure out what to change. The Spring login form works perfectly.