8

I spend a few hours trying to get Twitter integration to work with Spring Social using the XML configuration approach. All the examples I could find on the web (and on stackoverflow) always use the @Config approach as shown in the samples

For whatever reason the bean definition to get an instance to the twitter API throws an AOP exception:

Caused by: java.lang.IllegalStateException: Cannot create scoped proxy for bean 'scopedTarget.twitter': Target type could not be determined at the time of proxy creation.

Here's the complete config file I have:

    <?xml version="1.0" encoding="UTF-8"?>
    <beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:jaxrs="http://cxf.apache.org/jaxrs"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:util="http://www.springframework.org/schema/util" 
    xmlns:cxf="http://cxf.apache.org/core"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:mvc="http://www.springframework.org/schema/mvc" 
    xmlns:jdbc="http://www.springframework.org/schema/jdbc"  
    xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
       http://cxf.apache.org/jaxrs http://cxf.apache.org/schemas/jaxrs.xsd
       http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd 
       http://www.springframework.org/schema/util http://www.springframework.org/schema/util/spring-util-3.1.xsd
       http://cxf.apache.org/core http://cxf.apache.org/schemas/core.xsd
       http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
       http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.1.xsd
       http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
       http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.1.xsd">

    <import resource="classpath:META-INF/cxf/cxf.xml" />
    <import resource="classpath:META-INF/cxf/cxf-servlet.xml" />

    <jee:jndi-lookup id="dataSource" jndi-name="java:comp/env/jdbc/DefaultDB" />

    <!-- initialize DB required to store user auth tokens -->
    <jdbc:initialize-database data-source="dataSource" ignore-failures="ALL">
      <jdbc:script location="classpath:/org/springframework/social/connect/jdbc/JdbcUsersConnectionRepository.sql"/>
    </jdbc:initialize-database>

    <bean id="connectionFactoryLocator"
        class="org.springframework.social.connect.support.ConnectionFactoryRegistry">
        <property name="connectionFactories">
            <list>
                <ref bean="twitterConnectFactory" />
            </list>
        </property>
    </bean>

    <bean id="twitterConnectFactory" class="org.springframework.social.twitter.connect.TwitterConnectionFactory">
        <constructor-arg value="xyz" />
        <constructor-arg value="xzy" />
    </bean>

    <bean id="usersConnectionRepository"
        class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository">
        <constructor-arg ref="dataSource" />
        <constructor-arg ref="connectionFactoryLocator" />
        <constructor-arg ref="textEncryptor" />
    </bean>

    <bean id="connectionRepository" factory-method="createConnectionRepository"
        factory-bean="usersConnectionRepository" scope="request">
        <constructor-arg value="#{request.userPrincipal.name}" />
        <aop:scoped-proxy proxy-target-class="false" />
    </bean>

    <bean id="twitter" factory-method="findPrimaryConnection"
        factory-bean="connectionRepository" scope="request" depends-on="connectionRepository">
        <constructor-arg value="org.springframework.social.twitter.api.Twitter" />
        <aop:scoped-proxy proxy-target-class="false" />
    </bean>


    <bean id="textEncryptor" class="org.springframework.security.crypto.encrypt.Encryptors"
        factory-method="noOpText" />

    <bean id="connectController" class="org.springframework.social.connect.web.ConnectController">
        <constructor-arg ref="connectionFactoryLocator"/>
        <constructor-arg ref="connectionRepository"/>
        <property name="applicationUrl" value="https://socialscn.int.netweaver.ondemand.com/socialspringdemo" />
    </bean>

    <bean id="signInAdapter" class="com.sap.netweaver.cloud.demo.social.SimpleSignInAdapter" />

</beans>

What puzzles me is that the connectionRepositoryinstantiation works perfectly fine (I commented-out the twitter bean and tested the code!) ?!? It uses the same features: request scope and interface AOP proxy and works, but the twitter bean instantiation fails ?!?

The spring social config code looks as follows (I can not see any differences, can you?):

@Configuration
public class SocialConfig {

    @Inject
    private Environment environment;

    @Inject
    private DataSource dataSource;

    @Bean
    @Scope(value="singleton", proxyMode=ScopedProxyMode.INTERFACES) 
    public ConnectionFactoryLocator connectionFactoryLocator() {
        ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
        registry.addConnectionFactory(new TwitterConnectionFactory(environment.getProperty("twitter.consumerKey"),
                environment.getProperty("twitter.consumerSecret")));
        return registry;
    }

    @Bean
    @Scope(value="singleton", proxyMode=ScopedProxyMode.INTERFACES) 
    public UsersConnectionRepository usersConnectionRepository() {
        return new JdbcUsersConnectionRepository(dataSource, connectionFactoryLocator(), Encryptors.noOpText());
    }

    @Bean
    @Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)   
    public ConnectionRepository connectionRepository() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        if (authentication == null) {
            throw new IllegalStateException("Unable to get a ConnectionRepository: no user signed in");
        }
        return usersConnectionRepository().createConnectionRepository(authentication.getName());
    }

    @Bean
    @Scope(value="request", proxyMode=ScopedProxyMode.INTERFACES)   
    public Twitter twitter() {
        Connection<Twitter> twitter = connectionRepository().findPrimaryConnection(Twitter.class);
        return twitter != null ? twitter.getApi() : new TwitterTemplate();
    }

    @Bean
    public ConnectController connectController() {
        ConnectController connectController = new ConnectController(connectionFactoryLocator(), connectionRepository());
        connectController.addInterceptor(new PostToWallAfterConnectInterceptor());
        connectController.addInterceptor(new TweetAfterConnectInterceptor());
        return connectController;
    }

    @Bean
    public ProviderSignInController providerSignInController(RequestCache requestCache) {
        return new ProviderSignInController(connectionFactoryLocator(), usersConnectionRepository(), new SimpleSignInAdapter(requestCache));
    }
}

Any help/pointers would be appreciated!!!

John Conde
  • 217,595
  • 99
  • 455
  • 496

2 Answers2

5

I have a configuration that worked for Spring Social Facebook integration. (I have twitter configuration in it, But I haven't tested the twitter part in it)

<bean class="org.springframework.social.connect.web.ProviderSignInController">
<!-- relies on by-type autowiring for the constructor-args -->    
<constructor-arg ref="signInAdapter" /> 
</bean>

<bean id="connectionFactoryLocator" 
  class="org.springframework.social.connect.support.ConnectionFactoryRegistry">
<property name="connectionFactories">
    <list>
        <bean class="org.springframework.social.twitter.connect.TwitterConnectionFactory">
            <constructor-arg value="${twitter.consumerKey}" />
            <constructor-arg value="${twitter.consumerSecret}" />               
        </bean>
        <bean class="org.springframework.social.facebook.connect.FacebookConnectionFactory">
            <constructor-arg value="${facebook.clientId}" />
            <constructor-arg value="${facebook.clientSecret}" />                
        </bean>
    </list>
</property>
</bean>

<bean id="connectionRepository" factory-method="createConnectionRepository" 
  factory-bean="usersConnectionRepository" scope="request">
<constructor-arg value="#{request.userPrincipal.name}" />
<aop:scoped-proxy proxy-target-class="false" />
</bean>

<bean id="signInAdapter" class="com.test.social.SimpleSignInAdapter"/>

<bean id="usersConnectionRepository" 
  class="org.springframework.social.connect.jdbc.JdbcUsersConnectionRepository">
<constructor-arg ref="dataSource" />
<constructor-arg ref="connectionFactoryLocator" />
<constructor-arg ref="textEncryptor" />
</bean>

<bean id="textEncryptor" class="org.springframework.security.crypto.encrypt.Encryptors" 
        factory-method="noOpText" />

I have primarily referred the documentation which is small enough to read and a tutorial which had more to do with integration with spring security. I hope this helps in some way.

shazinltc
  • 3,616
  • 7
  • 34
  • 49
  • Well, as I said... the official documentation does not include the missing part my question was related to. The spring-social-showcase app uses the @Config annotation-based config. Your example doesn't include the missing part - bean definition of "twitter" - as well, but thanks for trying nonetheless! Cheers! – Matthias Steiner Oct 04 '12 at 13:53
0

I have a working xml spring-mvc/spring-social configuration for tomcat7 in this question I posted.

This question was posted a long time ago but maybe the configuration in my post will save some people some time. It took me quite some time to set up with XML configuration and latest spring 4.2.4 MVC including spring-social(1.1.4) and spring-social-twitter(1.1.2) twitter connection. I write versions here, because there are quite a few things different between spring versions.

Community
  • 1
  • 1