I have a service layer class having annotation @Controller and in service call I am spawning in thread and that is updating something in database. I have used @transaction annotation in thread's method. But I am getting hibernate exception "No session found". Do I need to add any annotation to Thread?
org.hibernate.HibernateException: No Session found for current thread at org.springframework.orm.hibernate4.SpringSessionContext.currentSession(SpringSessionContext.java:97) at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:978) at com.mediaiq.commons.persistence.BaseRepository.getCurrentSession(BaseRepository.java:30) at com.mediaiq.cms.persistence.AgencyRepository.getById(AgencyRepository.java:20) at com.mediaiq.mail.client.AgencyLookupReportByDayClient.emailAgencyLookupConfirmation(AgencyLookupReportByDayClient.java:84) at com.mediaiq.mail.client.AgencyLookupReportByDayClient.sendemailreport(AgencyLookupReportByDayClient.java:67) at com.mediaiq.mail.client.BaseMailClient.run(BaseMailClient.java:222) at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:471) at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:334) at java.util.concurrent.FutureTask.run(FutureTask.java:166) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) at java.lang.Thread.run(Thread.java:722)
@Repository
public class BaseMailClient implements Runnable {
public BaseMailClient() {
}
public BaseMailClient(PlacementsRepository placementsRepository, SessionFactory sessionFactory, String sessionID) {
this.placementsRepository = placementsRepository;
this.sessionFactory = sessionFactory;
this.sessionID = sessionID;
}
public BaseMailClient(AgencyRepository agencyRepository, SessionFactory sessionFactory, String sessionID) {
this.agencyRepository = agencyRepository;
this.sessionFactory = sessionFactory;
this.sessionID = sessionID;
}
private String sessionID = null;
@Autowired
private SessionFactory sessionFactory;
@Autowired
private PlacementsRepository placementsRepository;
@Autowired
private AgencyRepository agencyRepository;
final static Logger logger =LoggerFactory.getLogger(BaseMailClient.class);
@Override
public void run()
{
sendemailreport();
}
@Transactional
public void sendemailreport()
{
checkSessionID();
try {
emailAgencyLookupConfirmation();
emailAgencyLookup();
}
catch (IOException | FailedToCreateTempFile e) {
logger.info("Failed To mail due to exception :" + e.getMessage());
}
catch (Throwable e) {
logger.info("Failed To mail due to exception :" + e.getMessage());
}
}
}
Service Class:
@Transactional
@Controller
@RequestMapping(URLEndPoints.EMAIL)
public class SendMailService {
@Autowired
PlacementsRepository placementsRepository;
@Autowired
AgencyRepository agencyRepository;
/**
*
*/
@Autowired
private SessionFactory sessionFactory;
@Autowired
private ThreadPoolTaskExecutor mailJobExecutor;
final static Logger logger = LoggerFactory.getLogger(SendMailService.class);
@RequestMapping(method = RequestMethod.POST, value = URLEndPoints.EMAIL_AGENCY_LOOKUP_BY_DAY, produces = "application/json")
@ResponseBody
public String emailAgencyLookupByDay(ServletRequest request,@PathVariable("agencyID") Integer agencyID,
@PathVariable("startDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date startDate,
@PathVariable("endDate") @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) Date endDate )
{
logger.debug("POST:SendEmail:AgencyLookup");
String sessionId = getSessionIDFromCookie(request);
BaseClient mailServiceClient = new BaseClient(getAgencyRepository(), getSessionFactory(), sessionId);
logger.debug("Getting Executor Instance");
mailJobExecutor.submit(mailServiceClient);
logger.debug("Submitted to Executor");
return "SUCCESS";
}
}
@Asyncand@Transactionalhad a bug before Spring-3.0.3. See SPR-7147 - Markus Malkusch@Async. - Markus Malkusch