Announcement Announcement Module
Collapse
No announcement yet.
twitter has already been registered error. Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • twitter has already been registered error.

    Failed properties: Property 'authenticationServices' threw exception; nested exception is java.lang.IllegalArgumentException: A ConnectionFactory for provider 'twitter' has already been registered

    Not sure why i am getting this. Twitter and Facebook are configured via annotations. This whole configuration is loaded via the ContextLoaderListener, just like the samples project.

    But for some reason it looks like the App context loaded by the DispatcherServlet might be trying to make them too.

    Here is my Java Config class

    Code:
    @Configuration
    @EnableJdbcConnectionRepository
    @EnableTwitter(appId="${twitter.consumerKey}", appSecret = "${twitter.consumerSecret}")
    @EnableFacebook(appId = "${facebook.clientId}", appSecret = "${facebook.clientSecret}")
    public class SocialWebConfig {
    
      @Autowired
      ConnectionFactoryLocator connectionFactoryLocator;
    
      @Autowired
      ConnectionRepository connectionRepository;
    
      @Autowired
      UsersConnectionRepository usersConnectionRepository;
    
      @Autowired
      private UserIdSource userIdSource;
    
      @Bean
      public ConnectController connectController() {
        ConnectController connectController = new ConnectController(connectionFactoryLocator, connectionRepository);
        return connectController;
      }
    
      @Bean
      public ProviderSignInController providerSignInController(RequestCache requestCache) {
        ProviderSignInController controller = new ProviderSignInController(connectionFactoryLocator, usersConnectionRepository, new SpringSecuritySignInAdapter(requestCache));
        controller.setSignUpUrl("/account/signup");
        return controller;
      }
    
      @Bean
      public SocialAuthenticationFilter socialAuthenticationFilter(AuthenticationManager authenticationManager, RememberMeServices rememberMeServices, SocialAuthenticationServiceLocator authenticationServiceLocator) {
        SocialAuthenticationFilter socialAuthenticationFilter = new SocialAuthenticationFilter(authenticationManager, userIdSource, usersConnectionRepository, authenticationServiceLocator);
        socialAuthenticationFilter.setFilterProcessesUrl("/auth");
        socialAuthenticationFilter.setSignupUrl("/account/signup"); // TODO: Fix filter to handle in-app paths
        socialAuthenticationFilter.setRememberMeServices(rememberMeServices);
        return socialAuthenticationFilter;
      }
    
      @Bean
      public AuthenticationProvider socialAuthenticationProvider(UserDetailsService userDetailsService, UsersConnectionRepository usersConnectionRepository) {
        return new SocialAuthenticationProvider(usersConnectionRepository, socialUsersDetailsService(userDetailsService));
      }
    
      @Bean
      public SocialUserDetailsService socialUsersDetailsService(UserDetailsService userDetailsService) {
        return new SimpleSocialUserDetailsService(userDetailsService);
      }
    
      @Bean
      public PasswordEncoder passwordEncoder() {
          return NoOpPasswordEncoder.getInstance();
      }
    
      @Bean
      public TextEncryptor textEncryptor() {
        return Encryptors.noOpText();
      }
    
      @Bean
      public UserIdSource userIdSource() {
        return new AuthenticationNameUserIdSource();
      }
    
    }
    Here is what I have in the applicationContext.xml

    Code:
        <context:property-placeholder location="classpath:META-INF/spring/social.properties"/>
        <context:component-scan base-package="com.hdpoker.social.config"/>
        <import resource="classpath*:META-INF/spring/applicationContext*.xml"/>
        <import resource="applicationContext-security-account.xml"/>
    Here is my spring-security xml file config

    Code:
        <security:global-method-security secured-annotations="enabled"/>
    
    	<!-- HTTP security configurations -->
        <security:http auto-config="true" use-expressions="true">
            <security:form-login login-page="/" authentication-failure-url="/?login_error=1" default-target-url="/index"/>
            <security:intercept-url pattern="/index/**" access="hasRole('Player')"/>
            <security:intercept-url pattern="/account/**" method="POST" access="permitAll"/>
    
            <!-- Configure these elements to secure URIs in your application -->
            <security:intercept-url pattern="/resources/**" access="permitAll"/>
            <security:intercept-url pattern="/auth/**" access="permitAll" />
            <security:intercept-url pattern="/signin/**" access="permitAll" />
            <security:intercept-url pattern="/signup/**" access="permitAll" />
            <security:intercept-url pattern="/" access="permitAll" />
    
            <!--  Spring Social Security authentication filter -->
            <security:custom-filter ref="socialAuthenticationFilter" before="PRE_AUTH_FILTER" />
        </security:http>
    
        <!--Make sure somewhere there is a component-scan to bring in the accountUserDetailsService-->
        <security:authentication-manager alias="authenticationManager">
            <security:authentication-provider user-service-ref="accountUserDetailsService">
                <!--security:password-encoder hash="md5">
                        <security:salt-source system-wide="wysiwyg"/>
                </security:password-encoder-->
            </security:authentication-provider>
            <security:authentication-provider ref="socialAuthenticationProvider"/>
        </security:authentication-manager>
    Any ideas what I am doing wrong.

    Thanks

    Mark

  • #2
    Can you confirm which version of Spring Social you are working with? I had this exact same problem at one time (about a week ago), but it turned out to be a copy-n-paste error that has since been fixed.

    For grins, try removing the Facebook provider and see if the error goes away.

    Comment


    • #3
      Another thing that might be going on is that you have a @Configuration-annotated class and then you're (probably...I can't tell for sure here) component-scanning the same package that the class is in from your XML. My guess is that SocialWebConfig is being used twice...once because it is annotated with @Configuration and again due to component-scanning.

      If this is the problem (and I can't be certain for lack of visibility into the rest of your code), the fix is to add an exclusion to the <context:component-scan> to not scan for any classes that are annotated with @Configuration. I hope you've also taken care to not have applicationContext.xml anywhere in a page that the import would pick it up again.

      Again...this is just a guess because I can't see enough of your project to give a real diagnosis (and again, it'd be handy if this stuff or a smaller facsimile of it were in GitHub so that I can help with the diagnosis).

      Comment


      • #4
        I really wish I could share the code. But we are building a Poker app that will be for actual gambling. I am working for a casino/gaming company in Las Vegas and there are so much legal stuff. So much that I don't know if I was even allowed to tell you what I am working on.

        I do have a component-scan for loading in the @Configuration. So are you saying that a component scan is already occurring automatically without any config to do so?

        I am using the yet to be announced M2 in the SpringSource Milestone repo that you deployed yesterday.

        Mark

        Comment


        • #5
          If I remove the component-scan then it doesn't pick up the Configuration class. So I get noBeanDefined error.

          And here is the component-scan in the xxx-servlet.xml file

          Code:
          <context:component-scan base-package="com.blah.controller" use-default-filters="false">
          	<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
          </context:component-scan>
          All the other xml files that are brought into via the <import> are for infrastructure database and services/repos stuff. One for Spring Data Neo4j. One for Spring Data JPA.

          Also have
          Code:
              <context:spring-configured/>
          
              <context:component-scan base-package="com.hdpoker" use-default-filters="false">
                  <context:include-filter type="annotation" expression="com.blah.annotations.AccountServerApp"/>
                  <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
              </context:component-scan>
          Mark
          Last edited by bytor99999; Feb 13th, 2013, 11:44 AM. Reason: more info

          Comment


          • #6
            I am now going to try using xml instead. I had posted a new thread on that topic, but can't find it. Maybe the same issue I had before with a post where it didn't show up for a day. No biggie.

            Thanks

            Mark

            Comment


            • #7
              OK, now I am back to just configuring Spring Social from @Configuration class. I have two component-scans. One for the middle tier, one for the web tier. Both exclude @Configuration. I have only one @Configuration class and I make it a bean by itself in xml with <bean>

              I even thought maybe Spring Data Neo4j was doing an internal scan that might have picked it up. But I set a base-package in that config too that would not go into the @Configuration classes package.

              I am still getting that duplicate twitter et al.

              Now in trying xml, there was a class in Spring Social Security that got me wondering if two locators were being created. The base one with @EnableTwitter and another in Social Security for SocialAuthenticationServiceLocator. When I was doing xml I would get that as a bean not found. But with @Configuration there isn't any place in the samples that define an @Bean for it, but it seems like that is then created automatically, because I would have a different failure if it wasn't.

              Thanks

              Mark

              Comment


              • #8
                OK. I am now back to being able to deploy my application. I still have some errors, but I got past the already registered provider error.

                And my last post was correct. If you are going to use the Spring Social Security Filter, you cannot also use the @EnableTwitter like annotations because you will end up with two locators. One that @EnableTwitter creates and a SocialAuthenticationServiceLocator which by the way extends ConnectionFactoryRegistry.

                So I removed the @Enable annotations, then for my FactoryRegistry I created an @Bean that returns a SocialAuthenticationServiceLocator. But that caused another error because some beans are looking for a bean named connectionFactoryRegistry. So I just made that the name of my @Bean method ConnectionFactoryRegistry() and now I am deploying.

                Now my current error is now very much in the realm of something that I can resolve because it is a NPE in my UserDetailsService.

                Of course a big contributor to the Spring Social Security, Yuan was where I found the answer on his post

                http://www.jiwhiz.com/post/2013/1/Cu...rk_For_MongoDB

                Looking at his @Configuration class

                Thanks

                Mark
                Last edited by bytor99999; Feb 13th, 2013, 06:41 PM. Reason: more info

                Comment


                • #9
                  Interesting. While what I said above is true, in that I couldn't use the @Enable because it created two ServiceLocators. I just noticed in ProviderConfigurationSupport class that it does check first to see if Spring Social Security is there and if so instantiate a SocialAuthenticationServiceLocator instead of ConnectionFactory.

                  So maybe there is a way to configure it to make it work, it is just that it is cleaner than it was before, and I think the samples don't reflect the new changes.

                  Just a hunch/guess.

                  Mark

                  Comment


                  • #10
                    Nope. Setting break points in ProviderConfigurationSupport shows that it does see that Spring Social Security is there and returns true. But it is still trying to register Twitter or Facebook twice.

                    Well, I can put it back to what I had. I am just not getting redirected to my signup page when there is a UserNotFoundException thrown from my UserDetailsService. Instead it gets a 401.

                    Thanks

                    Mark

                    Comment


                    • #11
                      Here is how you can exclude something from Config component 'scan' process and scan by using config XML, so there won't be duplicated instances for the same bean.

                      http://forum.springsource.org/showth...ST-mapping-why
                      Hope that will hep somehow.

                      Comment


                      • #12
                        Originally posted by blandger View Post
                        Here is how you can exclude something from Config component 'scan' process and scan by using config XML, so there won't be duplicated instances for the same bean.

                        http://forum.springsource.org/showth...ST-mapping-why
                        Hope that will hep somehow.
                        blandger, thanks for replying.

                        That's not what is causing the problem. I do not have an @ComponentScan anywhere. And I only have the one component-scan and it is very filtered already and only finds @Controller classes. Now, in the @Configuration class there is an @Bean for ProviderSignInController, and if you think that would cause two ConnectionFactoryLocator implementations to be created, then that would be the way that would be the cause.

                        Anyway, as I have said, I have gotten past the error by not using the @EnableTwitter annotations.

                        As far as my most recent issues, I have found that I was getting the 401 exception because my UserDetailsService throws UserNotFoundException, and Spring Social was only redirecting to your signup page if a BadCredentialsException is thrown. UserNotFoundException extends AuthenticationException, so not in the BadCredentialsException hierarchy.

                        So for a workaround, in SocialUserDetailsService, when I call my UserDetailsService, I catch UserNotFoundException and throw a new BadCredentialsException, and that is definitely a hack. I mean it is a UserNotFound problem because the user isn't in our database yet for Spring Security.

                        I don't know if the code that catches BadCredentialsException needs to be changed to catching AuthenticationException, but that might be too broad.

                        Thanks

                        Mark

                        Comment


                        • #13
                          Originally posted by blandger View Post
                          Here is how you can exclude something from Config component 'scan' process and scan by using config XML, so there won't be duplicated instances for the same bean.

                          http://forum.springsource.org/showth...ST-mapping-why
                          Hope that will hep somehow.
                          Sorry just to update what my current config looks like as opposed to those earlier in this thread

                          Code:
                          @Configuration
                          @EnableJdbcConnectionRepository
                          //@EnableTwitter(appId="${twitter.consumerKey}", appSecret = "${twitter.consumerSecret}")
                          //@EnableFacebook(appId = "${facebook.clientId}", appSecret = "${facebook.clientSecret}")
                          public class SocialConfig {
                          
                            //@Autowired
                            //SocialAuthenticationServiceLocator connectionFactoryLocator;
                          
                            @Autowired
                            ConnectionRepository connectionRepository;
                          
                            @Autowired
                            UsersConnectionRepository usersConnectionRepository;
                          
                            @Autowired
                            @Qualifier("socialProperties")
                           	private Properties environment;
                          
                            @Bean
                            public SocialAuthenticationServiceLocator connectionFactoryLocator() {
                              SocialAuthenticationServiceRegistry registry = new SocialAuthenticationServiceRegistry();
                          
                              //add twitter
                              OAuth1ConnectionFactory<Twitter> twitterConnectionFactory =
                                  new TwitterConnectionFactory(environment.getProperty("twitter.consumerKey"),
                                      environment.getProperty("twitter.consumerSecret"));
                              OAuth1AuthenticationService<Twitter> twitterAuthenticationService =
                                  new OAuth1AuthenticationService<Twitter>(twitterConnectionFactory);
                              registry.addAuthenticationService(twitterAuthenticationService);
                          
                              //add facebook
                              OAuth2ConnectionFactory<Facebook> facebookConnectionFactory =
                                  new FacebookConnectionFactory(environment.getProperty("facebook.clientId"),
                                      environment.getProperty("facebook.clientSecret"));
                              OAuth2AuthenticationService<Facebook> facebookAuthenticationService =
                                  new OAuth2AuthenticationService<Facebook>(facebookConnectionFactory);
                              facebookAuthenticationService.setScope("");
                              registry.addAuthenticationService(facebookAuthenticationService);
                          
                              return registry;
                            }
                          
                            @Bean
                            @Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
                            public Facebook facebook() {
                                Connection<Facebook> facebook = connectionRepository.findPrimaryConnection(Facebook.class);
                                return facebook != null ? facebook.getApi() : new FacebookTemplate();
                            }
                          
                            @Bean
                            @Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)
                            public Twitter twitter() {
                                Connection<Twitter> twitter = connectionRepository.findPrimaryConnection(Twitter.class);
                                return twitter != null ? twitter.getApi() : new TwitterTemplate();
                            }
                          
                          	/**
                          	 * The Spring MVC Controller that allows users to sign-in with their provider accounts.
                          	 */
                          	@Bean
                          	public ProviderSignInController providerSignInController(RequestCache requestCache) {
                               ProviderSignInController signInController = new ProviderSignInController(connectionFactoryLocator(), usersConnectionRepository,
                                   new SpringSecuritySignInAdapter(requestCache));
                               signInController.setSignUpUrl("account/signup");
                               return signInController;
                          	}
                          
                          
                            @Bean
                            public SocialAuthenticationFilter socialAuthenticationFilter(AuthenticationManager authenticationManager, RememberMeServices rememberMeServices) {
                              SocialAuthenticationFilter socialAuthenticationFilter = new SocialAuthenticationFilter(authenticationManager, userIdSource(), usersConnectionRepository, connectionFactoryLocator());
                              socialAuthenticationFilter.setFilterProcessesUrl("/auth");
                              socialAuthenticationFilter.setSignupUrl("/account/signup");
                              socialAuthenticationFilter.setRememberMeServices(rememberMeServices);
                              return socialAuthenticationFilter;
                            }
                          
                            @Bean
                            public AuthenticationProvider socialAuthenticationProvider(UserDetailsService userDetailsService, UsersConnectionRepository usersConnectionRepository) {
                              return new SocialAuthenticationProvider(usersConnectionRepository, socialUsersDetailsService(userDetailsService));
                            }
                          
                            @Bean
                            public SocialUserDetailsService socialUsersDetailsService(UserDetailsService userDetailsService) {
                              return new SimpleSocialUserDetailsService(userDetailsService);
                            }
                          
                            @Bean
                            public LoginUrlAuthenticationEntryPoint socialAuthenticationEntryPoint(){
                              return new LoginUrlAuthenticationEntryPoint("/");
                            }
                          
                            @Bean
                            public PasswordEncoder passwordEncoder() {
                                return NoOpPasswordEncoder.getInstance();
                            }
                          
                            @Bean
                            public TextEncryptor textEncryptor() {
                              return Encryptors.noOpText();
                            }
                          
                            @Bean
                            public UserIdSource userIdSource() {
                              return new AuthenticationNameUserIdSource();
                            }
                          and, I am combining my xml config files for brevity. And I do have two component-scans in xml, one for the middle tier and one for the web tier, but they already had exclusions for @Configuration. And therefore had to use <bean> tag to include the one @Configuration class.

                          Code:
                              <import resource="classpath*:META-INF/spring/applicationContext*.xml"/>
                              <import resource="applicationContext-security-account.xml"/>
                              <util:properties id="socialProperties" location="classpath:META-INF/spring/social.properties"/>
                              <bean class="com.hdpoker.social.config.SocialConfig"/>
                          
                              <security:global-method-security secured-annotations="enabled"/>
                          
                          	<!-- HTTP security configurations -->
                              <security:http auto-config="true" use-expressions="true">
                                  <security:remember-me user-service-ref="accountUserDetailsService"/>
                                  <security:form-login login-page="/" authentication-failure-url="/?login_error=1" default-target-url="/index"/>
                                  <security:intercept-url pattern="/index/**" access="hasRole('Player')"/>
                                  <security:intercept-url pattern="/account/**" method="POST" access="permitAll"/>
                          
                                  <!-- Configure these elements to secure URIs in your application -->
                                  <security:intercept-url pattern="/resources/**" access="permitAll"/>
                                  <security:intercept-url pattern="/auth/**" access="permitAll" />
                                  <security:intercept-url pattern="/signin/**" access="permitAll" />
                                  <security:intercept-url pattern="/signup/**" access="permitAll" />
                                  <security:intercept-url pattern="/" access="permitAll" />
                          
                                  <!--  Spring Social Security authentication filter -->
                                  <security:custom-filter ref="socialAuthenticationFilter" before="PRE_AUTH_FILTER" />
                              </security:http>
                          
                              <!--Make sure somewhere there is a component-scan to bring in the accountUserDetailsService-->
                              <security:authentication-manager alias="authenticationManager">
                                  <security:authentication-provider user-service-ref="accountUserDetailsService"/>
                                  <security:authentication-provider ref="socialAuthenticationProvider"/>
                              </security:authentication-manager>
                          
                          	<!-- The controllers are autodetected POJOs labeled with the @Controller annotation. -->
                          	<context:component-scan base-package="com.hdpoker.controller" use-default-filters="false">
                          		<context:include-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
                                  <context:exclude-filter type="annotation" expression="org.springframework.context.annotation.Configuration"/>
                          	</context:component-scan>
                          
                              <context:component-scan base-package="com.hdpoker" use-default-filters="false">
                                  <context:include-filter type="annotation" expression="com.hdpoker.annotations.AccountServerApp"/>
                                  <context:exclude-filter expression="org.springframework.stereotype.Controller" type="annotation"/>
                                  <context:exclude-filter type="annotation" expression="org.springframework.context.annotation.Configuration"/>
                              </context:component-scan>

                          Comment


                          • #14
                            But I also do want to make one point. We should never have to <exclude-filter> @Configuration everywhere, that right now is a hack too. When you do component-scan tags, it should more be based on base-package and sometimes the filter on other Stereotypes, like keeping @Controllers from your middle tier etc.

                            Mark

                            Comment


                            • #15
                              @Configuration is a stereotype annotation, just like @Controller, @Repository, @Service, etc. Here's how it's annotated:

                              Code:
                              @Target(ElementType.TYPE)
                              @Retention(RetentionPolicy.RUNTIME)
                              @Documented
                              @Component
                              public @interface Configuration {
                              ...
                              }
                              By virtue of the fact that it's annotated with @Component, it *will* be picked up by component-scanning. That's usually a good thing. However, there are times when it can be a hassle...especially if within your @Configuration class you have a @ComponentScan that scans the base package (and recursively whatever package the @Configuration class is found in).

                              (I'm not sure if any of that explanation helps you or not, but I thought I'd offer it anyway just to be clear on the fact that @Configuration classes are prone to be component-scanned.)

                              So, I'm a bit lost on where you stand now. Is it working or not? I see that you've commented out both @EnableTwitter and @EnableFacebook, so my guess is that it's not quite working yet.

                              Comment

                              Working...
                              X