3

I am practising on spring-social and it seems that the userConnectionRepository is not properly autowired in the following code when I do a "Run as Junit Test" in Eclipse. I get a Null pointer exception on the usersConnectionRepository when creating a new FacebookOffLine although breakpoints put in the @Bean java creation code shows that they seem to be properly created. Thanks in advance,

public class FacebookOffline {

    private Facebook fb;

    @Autowired
    private UsersConnectionRepository usersConnectionRepository;

    public FacebookOffline(User user) {
        super();

        ConnectionRepository cr = usersConnectionRepository.createConnectionRepository(user.getId());
        fb = cr.getPrimaryConnection(Facebook.class).getApi();
    }

}

Here is the test code :

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = {
        org.springframework.social.quickstart.config.MainConfig.class,
        org.springframework.social.quickstart.config.SocialConfig.class })
public class FacebookOfflineTest {

    @Test
    public void test1() {
        FacebookOffline essai = new FacebookOffline(new User("yves"));

And the Spring configuration classes adapted from Keith Donald Quick Start Sample :

@Configuration
@ComponentScan(basePackages = "org.springframework.social.quickstart", excludeFilters = { @Filter(Configuration.class) })
@PropertySource("classpath:org/springframework/social/quickstart/config/application.properties")
public class MainConfig {

    @Bean
    public DataSource datasource() {
        DriverManagerDataSource toReturn = new DriverManagerDataSource("jdbc:mysql://localhost:3306/spring_social");
        toReturn.setDriverClassName("com.mysql.jdbc.Driver");
        toReturn.setUsername("spring");
        toReturn.setPassword("spring");
        return toReturn;

    }
}

@Configuration
public class SocialConfig {

    @Inject
    private Environment environment;

    @Inject
    private DataSource dataSource;

    @Bean
    public ConnectionFactoryLocator connectionFactoryLocator() {
        ConnectionFactoryRegistry registry = new ConnectionFactoryRegistry();
        registry.addConnectionFactory(new FacebookConnectionFactory(environment
                .getProperty("facebook.clientId"), environment
                .getProperty("facebook.clientSecret")));
        return registry;
    }

@Bean
    public UsersConnectionRepository usersConnectionRepository() {
        JdbcUsersConnectionRepository repository = new JdbcUsersConnectionRepository(
                dataSource, connectionFactoryLocator(), Encryptors.noOpText());
        return repository;
    }

}
4

3 回答 3

8

Actually there are 2 problems here.

  1. Spring cannot autowire beans it doesn't control (i.e. created with new)
  2. Dependencies aren't available in the constructor (an object instance is needed before it can be injected)

The first one can be mitigated by letting spring manage an instance of FacebookOffline (or if you need multiple instances make the bean request or session scoped).

The second is a bit harder but can probaly solved by using a method annotated with @PostConstruct (or by implementing InitializingBean from spring).

于 2013-09-18T06:56:16.980 回答
2

You did

FacebookOffline essai = new FacebookOffline(new User("yves"));

That means, Spring isn't managing this essai instance and thus spring can't autowire any variables in the essai.

You'll have to create bean of FacebookOffline in SocialConfig.

Then you can have

/* ... */
public class FacebookOfflineTest {

@Autowired
ApplicationContext context;

@Test
public void test1() {
    FacebookOffline essai = context.getBean(FacebookOffline.class);

OR

 /* ... */
public class FacebookOfflineTest {

@Autowired
FacebookOffline essai;

@Test
public void test1() {
    // You can use essai now

Also, you'll need to update FacebookOffline as Dependencies ain't available in constructor.

public class FacebookOffline {

private Facebook fb;

@Autowired
private UsersConnectionRepository usersConnectionRepository;

public FacebookOffline(User user) {
    super();  
}

@PostConstruct
void loadFacebook() {
    ConnectionRepository cr =       usersConnectionRepository.createConnectionRepository(user.getId());
     fb = cr.getPrimaryConnection(Facebook.class).getApi();
   }
}
于 2013-09-18T06:20:10.803 回答
0

Spring can't autowire fields on an instance you create via new since it doesn't know about it. Declare a bean of type FacebookOffline instead.

于 2013-09-18T06:14:21.340 回答