christopher
christopher

Reputation: 27346

Multithreaded Hibernate Session

I've got an issue involving scheduled tasks and Hibernate. I'm trying to use the java Timer object to schedule a task to run once a second. That tasks involves querying a database via hibernate. Now, as far as I understand it, Hibernate getCurrentSession() method will return a session bound to the current context.

Firstly, I am using this code to schedule the task:

  timer = new Timer();
  task = new UpdateTask();
  // Schedule the task for future runs.
  timer.scheduleAtFixedRate(task, 1000, 1000);

The code for the task is as follows:

 public void run() {
    FilterMeetingDao fmService = new FilterMeetingDao();
    Set<String> codes = new HashSet<String>();

    String date = new SimpleDateFormat(Constants.DATE_FORMAT).format(new Date());
    try {
        List<Meeting> meetings = new MeetingDao().getMeetings(date);

        for(Meeting m : meetings)
        {
             if(RawMeetingFilter.isDefaultMeeting(m)) {
                  // Is a default meeting. Insert into the database.
                  codes.add(m.getCode());
             }
        }
        fmService.add(codes, date);
    } catch (ParseException e) {
        e.printStackTrace();
    }
}

Finally, here is the code is the DAO object that is retrieving the information:

public List<Meeting> getMeetings(String date) throws ParseException{                        
    SimpleDateFormat sdf = new SimpleDateFormat(Constants.DATE_FORMAT);         
    Date startDate = sdf.parse(date);

    Query query = getSession().createQuery("from Meeting m where m.startDate = :startDate and source not like 'TTV' order by countrycode, categorycode, description");
    query.setParameter("startDate", startDate);     
    return query.list();
}

And the getSession method is the origin of the NPE, which is as follows:

public Session getSession(){
    return sessionFactory.getCurrentSession();
}

The line return sessionFactory.getCurrentSession(); is the origin of the error. Now, this obviously means the sessionFactory is null. However, in my code, the exact same database request is made in the previous line. This tells me that the sessionFactory isn't null because the previous request is successful.

Here is a stack trace of the NullPointerException:

Exception in thread "Timer-0" java.lang.NullPointerException
at com.sis.rawfilter.dao.impl.BaseDao.getSession(BaseDao.java:13)
at com.sis.rawfilter.dao.impl.MeetingDao.getMeetings(MeetingDao.java:21)
at com.sis.rawfilter.domain.UpdateTask.run(UpdateTask.java:32)
at java.util.TimerThread.mainLoop(Timer.java:555)
at java.util.TimerThread.run(Timer.java:505)

Just for reference..

meetings = meetingService.getMeetings(date);
// meetingService is the wrapper for the DAO object. this is the successful request.

And this is how I start my request:

 us.startTimer();

Which starts off the call chain, with the timer code at the top.

Edits I've made to try and fix it

So I added in a new bean tag into the applicationContext.xml file. That looks like this:

 <bean id="updateTask" class="com.sis.rawfilter.domain.UpdateTask"/>

And I've added in the Autowired tag into the class for the fields:

@Autowired
private IMeetingService meetingService;

@Autowired
private IFilterMeetingService filterMeetingService;

These types are declared in the applicationContext file as:

<bean id="meetingService" class="com.sis.rawfilter.service.impl.MeetingService"/>
<bean id="filterMeetingService" class="com.sis.rawfilter.service.impl.FilterMeetingService"/>

Sample Service Class

@Transactional
public class FilterMeetingService implements IFilterMeetingService {

@Autowired
private IFilterMeetingDao filterMeetingDao;

public List<FilterMeeting> getFilterMeetings(String date) throws ParseException{
    return filterMeetingDao.getFilterMeetings(date);
}

public void save(Set<String> selectedMeetings, Set<String> excludedMeetings, String date) throws ParseException{    

    if(excludedMeetings.size() > 0){
        filterMeetingDao.remove(excludedMeetings, date);
    }

    if(selectedMeetings.size() > 0){
        filterMeetingDao.add(selectedMeetings, date);
    }
}

public void setFilterMeetingDao(IFilterMeetingDao filterMeetingDao) {
    this.filterMeetingDao = filterMeetingDao;
}

}

Sample Dao Class

public class FilterMeetingDao extends BaseDao implements IFilterMeetingDao {

@SuppressWarnings("unchecked")
public List<FilterMeeting> getFilterMeetings(String date) throws ParseException{    

    SimpleDateFormat sdf = new SimpleDateFormat(Constants.DATE_FORMAT);         
    Date startDate = sdf.parse(date);

    Query query = getSession().createQuery("from FilterMeeting fm where fm.startDate = :startDate");
    query.setParameter("startDate", startDate);

    return query.list();        
}


public void remove(Set<String> codes, String date){

    Query query = getSession().createSQLQuery("delete from tbl where d = :date and c in :codes ");
    query.setParameter("date", date);
    query.setParameterList("codes", codes);
    query.executeUpdate();
}

public void add(Set<String> codes, String date) throws ParseException{
    SimpleDateFormat sdf = new SimpleDateFormat(Constants.DATE_FORMAT); 

    for(String code : codes){
        FilterMeeting filterMeeting = new FilterMeeting(code,   sdf.parse(date), Config.getInstance().getQueue());
        getSession().save(filterMeeting);   
    }
}

}

Upvotes: 0

Views: 1972

Answers (1)

commit
commit

Reputation: 4807

You are creating new object of meeting dao

new MeetingDao().getMeetings(date);

so sessionFactory object will not initialize and obviously you will get nullPointerException, you should Autowired dao.

Upvotes: 1

Related Questions