title: Spring security OAuth2 "clientDetailsService" circular reference?
body: <p>I have below security config class (at the bottom), recently upgraded to;</p>
  <ul>
  <li>Spring Security (3.2.6.RELEASE)</li>
  <li>Spring Security OAuth2 (2.0.6.RELEASE from 2.0.3.RELEASE)</li>
  </ul>
  <p>and I started seeing this error messages, now all my integration tests fail with the same error;</p>
  <blockquote>
  <p>Caused by: org.springframework.beans.factory.BeanCreationException:
  Error creating bean with name 'securityConfig': Injection of autowired
  dependencies failed; nested exception is
  org.springframework.beans.factory.BeanCreationException: Could not
  autowire field: private
  org.springframework.security.oauth2.provider.ClientDetailsService
  com.xyz.package.config.SecurityConfig.clientDetailsService; nested
  exception is
  org.springframework.beans.factory.BeanCurrentlyInCreationException:
  Error creating bean with name 'clientDetailsService': Requested bean
  is currently in creation: Is there an unresolvable circular reference?</p>
  <p>..............</p>
  <p>..............</p>
  <p>Caused by:
  org.springframework.beans.factory.BeanCurrentlyInCreationException:
  Error creating bean with name 'clientDetailsService': Requested bean
  is currently in creation: Is there an unresolvable circular reference?</p>
  </blockquote>
  <p>This is definitely caused by upgrading to Spring Security OAuth2 (2.0.6.RELEASE), I didn't have this on 2.0.3.RELEASE.
  I appreciate if anyone can give me an insight on this one.</p>
  <p>Thanks in advance.</p>
  <pre><code>@Configuration 
  public class SecurityConfig {
  
  @Autowired
  private DataSource dataSource;
  
  @Autowired
  private ClientDetailsService clientDetailsService;
  
  @Autowired
  private RedisConnectionFactory redisConnectionFactory;
  
  @Bean
  public TokenStore tokenStore() {
      return new PipelinedRedisTokenStore(redisConnectionFactory);
  }
  
  @Bean
  public DefaultTokenServices tokenServices() throws Exception {
      DefaultTokenServices tokenServices = new DefaultTokenServices();
      tokenServices.setAccessTokenValiditySeconds(6000);
      tokenServices.setClientDetailsService(clientDetailsService);
      tokenServices.setTokenEnhancer(new MyTokenEnhancer());
      tokenServices.setSupportRefreshToken(true);
      tokenServices.setTokenStore(tokenStore());
      return tokenServices;
  }
  
  @Bean
  public UserApprovalHandler userApprovalHandler() throws Exception {
      UserApprovalHandler handler = new MyUserApprovalHandler();
      handler.setApprovalStore(approvalStore());
      handler.setClientDetailsService(clientDetailsService);
      handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
      handler.setUseApprovalStore(true);
      return handler;
  }
  
  @Bean
  public ApprovalStore approvalStore() {
      TokenApprovalStore store = new TokenApprovalStore();
      store.setTokenStore(tokenStore());
      return store;
  }
  
  @Bean
  public OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler() {
      return new OAuth2AccessDeniedHandler();
  }
  
  @Configuration
  @Priority(2000)
  @EnableWebSecurity
  protected static class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  
      @Value(&quot;${baseUrl}&quot;) 
      private String baseUrl;
  
      @Autowired
      private DataSource dataSource;
      
      @Resource
      private PasswordEncoder passwordEncoder;
  
      @Autowired
      private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;
  
      @Bean
      public ClientDetailsService clientDetailsService() throws Exception {
          ClientDetailsServiceConfiguration serviceConfig = new ClientDetailsServiceConfiguration();
              
          serviceConfig.clientDetailsServiceConfigurer().inMemory()
              .withClient(&quot;xxxx&quot;)
              .secret(&quot;some-secret&quot;)
              .authorizedGrantTypes(&quot;password&quot;, &quot;authorization_code&quot;, &quot;refresh_token&quot;, &quot;client_credentials&quot;)
              .authorities(&quot;ROLE_CLIENT&quot;, &quot;ROLE_TRUSTED_CLIENT&quot;)
              .scopes(&quot;play&quot;, &quot;trust&quot;);
  
          return serviceConfig.clientDetailsService();
      }
      
      @Bean
      UserDetailsService clientDetailsUserDetailsService() throws Exception {
          return new ClientDetailsUserDetailsService(clientDetailsService());
      }
      
      @Bean
      public ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter() throws Exception {
          ClientCredentialsTokenEndpointFilter filter = new ClientCredentialsTokenEndpointFilter();
          filter.setAuthenticationManager(authenticationManagerBean());
          filter.afterPropertiesSet();
          return filter;
      }
  
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
          
          JdbcUserDetailsManagerConfigurer&lt;AuthenticationManagerBuilder&gt; jdbcUserDetail = new JdbcUserDetailsManagerConfigurer&lt;AuthenticationManagerBuilder&gt;();
          jdbcUserDetail.dataSource(dataSource);
          jdbcUserDetail.passwordEncoder(passwordEncoder);
          jdbcUserDetail.authoritiesByUsernameQuery(&quot;select a.username, r.role_name from account a, role r, account_role ar where a.id = ar.account_id and r.id = ar.role_id and a.username = ?&quot;);
          jdbcUserDetail.usersByUsernameQuery(&quot;select a.username, a.password, a.enabled, a.email from account a where a.username = ?&quot;);
          auth.apply(jdbcUserDetail);
          
          auth.userDetailsService(clientDetailsUserDetailsService());
          
  
      }
      
      @Bean(name=&quot;authenticationManager&quot;)
      @Override
      public AuthenticationManager authenticationManagerBean() throws Exception {
          return super.authenticationManagerBean();
      }
      
      @Bean
      protected AuthenticationEntryPoint authenticationEntryPoint() {
          OAuth2AuthenticationEntryPoint entryPoint = new OAuth2AuthenticationEntryPoint();
          entryPoint.setTypeName(&quot;Basic&quot;);
          entryPoint.setRealmName(&quot;realm/client&quot;);
          return entryPoint;
      }
      
      @Override
      public void configure(WebSecurity webSecurity) throws Exception {
          webSecurity
              .ignoring()
              .antMatchers(&quot;/resources/**&quot;, &quot;/swagger/**&quot;, &quot;/copyright*&quot;, &quot;/api-docs/**&quot;)
              .antMatchers(HttpMethod.POST, &quot;/api/**/account&quot;)
          .and()
              .debug(false);
      }
      
      @Override
      protected void configure(HttpSecurity http) throws Exception {
          
          // @formatter:off
          http
              .anonymous().disable()
              .requiresChannel().anyRequest().requiresSecure();
  
          http
              .antMatcher(&quot;/oauth/token&quot;)
              .authorizeRequests().anyRequest().authenticated()
          .and()
              .httpBasic().authenticationEntryPoint(authenticationEntryPoint())
          .and()
              .csrf().requireCsrfProtectionMatcher(new AntPathRequestMatcher(&quot;/oauth/token&quot;)).disable()
              .exceptionHandling().accessDeniedHandler(oAuth2AccessDeniedHandler)
          .and()
              .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
          http
              .addFilterBefore(clientCredentialsTokenEndpointFilter(), BasicAuthenticationFilter.class);
          // @formatter:on
  
      }
      
  }
  
  @Configuration
  @EnableResourceServer
  protected static class ResourceServerConfig extends ResourceServerConfigurerAdapter {
      
      @Autowired
      private ResourceServerTokenServices tokenServices;
      
      @Autowired
      private OAuth2AccessDeniedHandler oAuth2AccessDeniedHandler;
      
      @Autowired
      ClientCredentialsTokenEndpointFilter clientCredentialsTokenEndpointFilter;
      
      @Override
      public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
          //resources.tokenServices(tokenServices);
          resources.resourceId(&quot;resource&quot;);
      }
      
      @Override
      public void configure(HttpSecurity http) throws Exception {
  
          // @formatter:off
          http
              .requiresChannel().anyRequest().requiresSecure();
  
          // API calls
          http
              .anonymous().disable()
              .authorizeRequests()
              .antMatchers(&quot;/api/**&quot;)
              .access(&quot;#oauth2.hasScope('trust') and #oauth2.hasScope('play') and (hasRole('ROLE_USER'))&quot;)
          .and()
              .addFilterBefore(clientCredentialsTokenEndpointFilter, BasicAuthenticationFilter.class)
              .sessionManagement()
              .sessionCreationPolicy(SessionCreationPolicy.NEVER)
          .and()
              .exceptionHandling()
              .accessDeniedHandler(oAuth2AccessDeniedHandler);
              
          // @formatter:on
      }
      
  }
  
  @Configuration
  @EnableAuthorizationServer
  protected static class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
      
      @Autowired
      private DataSource dataSource;
      
      @Autowired
      private AuthorizationServerTokenServices tokenServices;
      
      @Autowired
      private ClientDetailsService clientDetailsService;
  
      @Autowired
      private UserApprovalHandler userApprovalHandler;
      
      @Autowired
      private AuthenticationManager authenticationManager;
      
      @Autowired
      AuthenticationEntryPoint authenticationEntryPoint;
  
      @Override
      public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
          endpoints
          .tokenServices(tokenServices)
          .userApprovalHandler(userApprovalHandler)
          .authenticationManager(authenticationManager);
      }
  
      @Override
      public void configure(ClientDetailsServiceConfigurer clients)
              throws Exception {
          clients.withClientDetails(clientDetailsService);
      }
      
      @Override
      public void configure(AuthorizationServerSecurityConfigurer oauthServer)
              throws Exception {
          oauthServer.authenticationEntryPoint(authenticationEntryPoint)
                  .realm(&quot;realm/clients&quot;);
      }
      
  }
  
  }
  </code></pre>
  <p>** Update (3/17) **</p>
  <p>Created <a href="https://github.com/aug70/security-sample" rel="nofollow noreferrer">https://github.com/aug70/security-sample</a> for this question.
  Without changing the configuration seems like things that worked in previous release (2.0.3) is not working anymore. See project readme.</p>