Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate Lazy init exception in spring scheduled job

I have a spring scheduled job (@Scheduled) that sends emails from my system according to a list of recipients in the DB.

This method is annotated with the @Scheduled annotation and it invokes a method from another interface, the method in the interface is annotated with the @Transactional annotation.

Now, when i invoke the scheduled method manually, it works perfectly. But when the method is invoked by spring scheduler i get the LazyInitFailed exception in the method implementing the said interface.

What am I doing wrong?

code:

The scheduled method:

@Component
public class ScheduledReportsSender {

    public static final int MAX_RETIRES = 3;
    public static final long HALF_HOUR = 1000 * 60 * 30; 

    @Autowired
    IScheduledReportDAO scheduledReportDAO;

    @Autowired
    IDataService dataService;

    @Autowired
    IErrorService errorService;

    @Scheduled(cron = "0 0 3 ? * *") // every day at 2:10AM
    public void runDailyReports() {
        // get all daily reports
        List<ScheduledReport> scheduledReports = scheduledReportDAO.getDaily();
        sendScheduledReports(scheduledReports);
    }

    private void sendScheduledReports(List<ScheduledReport> scheduledReports) {
        if(scheduledReports.size()<1) {
            return;
        }
        //check if data flow ended its process by checking the report_last_updated table in dwh
        int reportTimeId = scheduledReportDAO.getReportTimeId();
        String todayTimeId = DateUtils.getTimeid(DateUtils.getTodayDate());
        int yesterdayTimeId = Integer.parseInt(DateUtils.addDaysSafe(todayTimeId, -1));
        int counter = 0;

        //wait for time id to update from the daily flow
        while (reportTimeId != yesterdayTimeId && counter < MAX_RETIRES) {
            errorService.logException("Daily report sender, data not ready. Will try again in one hour.", null, null, null);
            try {
                Thread.sleep(HALF_HOUR);
            } catch (InterruptedException ignore) {}
            reportTimeId = scheduledReportDAO.getReportTimeId();
            counter++;
        }

        if (counter == MAX_RETIRES) {
            MarketplaceServiceException mse = new MarketplaceServiceException();
            mse.setMessage("Data flow not done for today, reports are not sent.");
            throw mse;
        }

        // get updated timeid
        updateTimeId();

        for (ScheduledReport scheduledReport : scheduledReports) {
            dataService.generateScheduledReport(scheduledReport);
        }
    }

}

The Invoked interface:

public interface IDataService {

    @Transactional
    public void generateScheduledReport(ScheduledReport scheduledReport);
}

The implementation (up to the line of the exception):

@Service
public class DataService implements IDataService {

public void generateScheduledReport(ScheduledReport scheduledReport) {

        // if no recipients or no export type - return
        if(scheduledReport.getRecipients()==null || scheduledReport.getRecipients().size()==0 || scheduledReport.getExportType() == null) {
            return;
        }
}
}

Stack trace:

ERROR: 2012-09-01 03:30:00,365 [Scheduler-15] LazyInitializationException.<init>(42) | failed to lazily initialize a collection of role: com.x.model.scheduledReports.ScheduledReport.recipients, no session or session was closed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.x.model.scheduledReports.ScheduledReport.recipients, no session or session was closed
        at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
        at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
        at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:122)
        at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
        at com.x.service.DataService.generateScheduledReport(DataService.java:219)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
        at $Proxy208.generateScheduledReport(Unknown Source)
        at com.x.scheduledJobs.ScheduledReportsSender.sendScheduledReports(ScheduledReportsSender.java:85)
        at com.x.scheduledJobs.ScheduledReportsSender.runDailyReports(ScheduledReportsSender.java:38)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
        at org.springframework.scheduling.support.MethodInvokingRunnable.run(MethodInvokingRunnable.java:65)
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:51)
        at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
        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.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:165)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:636)
ERROR: 2012-09-01 03:30:00,366 [Scheduler-15] MethodInvokingRunnable.run(68) | Invocation of method 'runDailyReports' on target class [class com.x.scheduledJobs.ScheduledReportsSender] failed
org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.x.model.scheduledReports.ScheduledReport.recipients, no session or session was closed
        at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:383)
        at org.hibernate.collection.AbstractPersistentCollection.throwLazyInitializationExceptionIfNotConnected(AbstractPersistentCollection.java:375)
        at org.hibernate.collection.AbstractPersistentCollection.readSize(AbstractPersistentCollection.java:122)
        at org.hibernate.collection.PersistentBag.size(PersistentBag.java:248)
        at com.x.service.DataService.generateScheduledReport(DataService.java:219)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
        at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
        at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
        at $Proxy208.generateScheduledReport(Unknown Source)
        at com.x.scheduledJobs.ScheduledReportsSender.sendScheduledReports(ScheduledReportsSender.java:85)
        at com.x.scheduledJobs.ScheduledReportsSender.runDailyReports(ScheduledReportsSender.java:38)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:616)
        at org.springframework.util.MethodInvoker.invoke(MethodInvoker.java:273)
        at org.springframework.scheduling.support.MethodInvokingRunnable.run(MethodInvokingRunnable.java:65)
        at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:51)
        at org.springframework.scheduling.concurrent.ReschedulingRunnable.run(ReschedulingRunnable.java:81)
        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.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$101(ScheduledThreadPoolExecutor.java:165)
        at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:266)
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
        at java.lang.Thread.run(Thread.java:636)

getReportTimeid implementation:

@Override
    public int getReportTimeId() {
        Query query = super.entityManager.createNativeQuery("select timeid from lgdwh.report_last_updated order by timeid desc limit 1");
        return (Integer) query.getSingleResult();
    }
like image 956
Noam Nevo Avatar asked Sep 01 '12 08:09

Noam Nevo


People also ask

How do I fix lazy initialization exception?

The right way to fix a LazyInitializationException is to fetch all required associations within your service layer. The best option for that is to load the entity with all required associations in one query.

What is lazy initialization in hibernate?

LazyInitializer is a Hibernate component that helps to generate proxy objects for Entities and can also be used to fetch the underlying entities of these proxy objects.


1 Answers

The problem was that I was extracting an object from the DB in the scheduled class and passing it to a class that does work on the object, my solution was to initialize the object in the scheduled class before passing it to the class that does the work.

like image 103
Noam Nevo Avatar answered Oct 27 '22 01:10

Noam Nevo