Monday, April 28, 2014

Resolved : Spring Initialize a bean which depends on another bean: Use JdbcTemplate when initializing a bean.

Removed
I was working on a web project using spring. I needed in the project to initialize a cache by doing a call to the database. So in order to do so, I was putting the database call in the default class constructor.
So in my Configuration class I do

@Bean("usersCache")
@DependsOn("myJdbcTemplate")
public UsersCache userCache{
    return new UsersCache(); 
}

And in the UserCache constructor I do :

@ManagedResource
public class UsersCache {
@Autowired
JdbcTemplate jdbcTemplate;

@PostConstruct
public UsersCache(){

@SuppressWarnings({ "unchecked", "rawtypes" })
List<LatestRecordPerUser> latestRecordByDevice = jdbcTemplate.query(populateCache, new BeanPropertyRowMapper(LatestRecordPerUser.class));
for(LatestRecordPerUser record:latestRecordByDevice ){
// And Here I insert into my cache
}
}


But even using this code I get a NullPointerException as the JdbcTemplate bean is not injected:

Caused by: org.springframework.beans.BeanInstantiationException: Could not instantiate bean class [main.java.org.beans.UsersCache ]: Constructor threw exception; nested exception is java.lang.NullPointerException

I have later understand that as the UsersCache is not yet initialized, nothing will be injected to it. So only after initialization, spring will inject the jdbcTemplate and thus we can execute the request.

So the fix the problem, there is no need to use @dependsOn . We need just to populate the cache after the bean (or repository) initialisation, So this can be done thanks to @PostConstruct. So the code is now :

@Repository
@Scope("singleton")
public class UsersCache {
@Autowired
JdbcTemplate jdbcTemplate;

private final Map userCache = new ConcurrentHashMap();

@PostConstruct
public void init(){

@SuppressWarnings({ "unchecked", "rawtypes" })
List<LatestRecordPerUser> latestRecordByDevice = jdbcTemplate.query(populateCache, new BeanPropertyRowMapper(LatestRecordPerUser.class));

for(LatestRecordPerUser record:latestRecordByDevice ){
// And Here I insert into my cache
}
}

Thant's it :D

No comments :

Post a Comment

Articles les plus consultés