Spring Boot Quartz - LazyInitializationException

时间:2015-09-01 16:00:55

标签: spring jpa spring-boot quartz-scheduler

我正在尝试使用Quartz在Spring启动时安排一项工作。以下是我在下面使用的代码是我的配置...

问题:调用作业时,org.hibernate.LazyInitializationException:无法懒惰地初始化角色集合:

HCSchedulerFactoryBean:

 @Autowired
  HCJobFactory jobFactory;

  @Autowired
  DataSource dataSource;

  @Autowired
  PlatformTransactionManager transactionManager;

  @Override
  public void afterPropertiesSet() throws Exception
  {
    setJobFactory( jobFactory.getJobFactory() );
    setDataSource( dataSource );
    //setTransactionManager( transactionManager );
    super.afterPropertiesSet();
  }

//工作工厂:

@Component
  public class HCJobFactory
  {
    @Autowired
    ApplicationContext applicationContext;

    public JobFactory getJobFactory()
    {
      HCSpringBeanJobFactory jobFactory = new HCSpringBeanJobFactory();
      jobFactory.setApplicationContext( applicationContext );
      return jobFactory;
    }
  }

// SpringBeanJobFactory

public final class HCSpringBeanJobFactory extends SpringBeanJobFactory implements ApplicationContextAware
{

  private transient AutowireCapableBeanFactory beanFactory;

  @Override
  public void setApplicationContext( final ApplicationContext context )
  {
    beanFactory = context.getAutowireCapableBeanFactory();
  }

  @Override
  protected Object createJobInstance( final TriggerFiredBundle bundle ) throws Exception
  {
    final Object job = super.createJobInstance( bundle );
    beanFactory.autowireBean( job );
    return job;
  }
}

//在Quartz中安排的调度程序作业

@SuppressWarnings( { "unchecked", "rawtypes" } )
  public Mailing saveAndScheduleMailing( Mailing mailing, Long runByUserId )
  {

    try
    {
      mailing = mailingDAO.saveMailing( mailing );

      // schedule job
      LinkedHashMap parameterValueMap = new LinkedHashMap();
      parameterValueMap.put( "mailingId", mailing.getId() );

      ProcessSchedule processSchedule = new ProcessSchedule();
      processSchedule.setStartDate( new Date() );
      processSchedule.setTimeOfDayMillis( new Long( 0 ) );

      processSchedule.setSchedulerFrequency( ScheduleFrequencyEnum.ONE_TIME_ONLY.getScheduleFrequency() );

      scheduleProcess( mailing, processSchedule, parameterValueMap, runByUserId );

      return mailing;
    }
    catch( Exception e )
    {
      logger.error( "An error occured method saveAndScheduleMailing." + "For mailingId: " + mailing.getId() );
      e.printStackTrace();
      return null;
    }

  }

  @SuppressWarnings( "rawtypes" )
  private void scheduleProcess( Mailing mailing, ProcessSchedule processSchedule, LinkedHashMap parameterValueMap, Long runByUserId )
  {
    try
    {
      JobKey jobKey = buildJobKey( mailing.getId() );
      JobDataMap triggerJobDataMap = new JobDataMap();
      triggerJobDataMap.put( RUN_BY_USER_ID_PARAM_NAME, runByUserId.toString() );
      triggerJobDataMap.put( MAILING_ID, mailing.getId() );
      JobDetail job = JobBuilder.newJob( QuartzEmailProcess.class ).withIdentity( jobKey ).storeDurably().setJobData( triggerJobDataMap ).build();

      // Define Trigger Instance
      String triggerGroupName = buildTriggerGroupName( mailing.getId() );
      String triggerName = buildTriggerName(mailing.getId());

      Trigger trigger = QuartzProcessUtil.buildTrigger( processSchedule, job, triggerName, triggerGroupName );
      Scheduler scheduler = factoryBean.getScheduler();
      scheduler.addJob( job, true );
      scheduler.scheduleJob( trigger );
    }
    catch( SchedulerException e )
    {
      e.printStackTrace();
    }
  }

//从Scheduler调用的实际服务:

@Service
@Transactional
public class QuartzEmailProcess extends QuartzJobBean
{
  @Autowired
  EmailService emailService;
  private static final Logger logger = LoggerFactory.getLogger( QuartzEmailProcess.class );
  protected void executeInternal( JobExecutionContext context ) throws JobExecutionException
  {
    try
    {
      Scheduler scheduler = context.getScheduler();
      JobDetail jobDetail = context.getJobDetail();
      Long mailingId = Long.valueOf( jobDetail.getJobDataMap().get( "MailingId" ).toString() );
      emailService.sendMessage( mailingId );
    }
    catch( SchedulerException e )
    {
      e.printStackTrace();
    }
  }

与数据库交互的电子邮件服务类:所有类文件也在同一个项目和相同的包中。

  public void sendMessage( Long mailingId )
  {
    Mailing mailing = mailingDao.getByMailingId( mailingId ); --> Getting Mailing object from DB
    EmailHeaderRequest header = buildEmailHeaderFromMailingId( mailing );

    for ( MailingRecipient recipient : mailing.getMailingRecipient() )
    {
      if ( recipient.getMailingRecipientType().equalsIgnoreCase( TO_VALUE ) && !StringUtils.isEmpty( recipient.getRecipient().getParticipant().getPrimaryEmailId() ) )
      {
        header.getRecipientEmails().clear();
        header.getRecipientEmails().put( recipient.getUserId(), recipient.getRecipient().getParticipant().getPrimaryEmailId() );
        EmailBodyRequest body = buildEmailBody( mailing.getTextCmKey(), recipient, true );
        processEmail( header, body );
      }
    }
    updateMailingStatus(mailing);
  }

    private String getUserEmailAddress( Long sender )
    {
      ApplicationUser user = userDao.findById( sender ); --> Getting user Object from DB
      Iterator<UserRole> roleIterator = user.getUserRoles().iterator(); ---------------> GETTING LAZY INITIALIZATION EXCEPTION HERE ERROR
      String emailAddress = null;

      while(roleIterator.hasNext())
      {
        UserRole role = roleIterator.next();
        if ( role.getRole().getRoleCode().equalsIgnoreCase( HCCoreConstants.PAX_VALUE ) )
        {
          emailAddress = user.getParticipant().getPrimaryEmailId();
          break;
        }
        else if ( role.getRole().getRoleCode().equalsIgnoreCase( HCCoreConstants.ADMIN_VALUE ) )
        {
          emailAddress = ldapQueryService.getByUserName( user.getUserName() ).iterator().next();
          break;
        }
      }

      return emailAddress;
  }  

但我还是得到了这个问题。我尝试将事务管理器添加到调度程序,但没有解决问题

任何人都可以帮助我

更新1 - StackTrace

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.domain.ApplicationUser.userRoles, could not initialize proxy - no Session
    at org.hibernate.collection.internal.AbstractPersistentCollection.throwLazyInitializationException(AbstractPersistentCollection.java:575)
    at org.hibernate.collection.internal.AbstractPersistentCollection.withTemporarySessionIfNeeded(AbstractPersistentCollection.java:214)
    at org.hibernate.collection.internal.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:554)
    at org.hibernate.collection.internal.AbstractPersistentCollection.read(AbstractPersistentCollection.java:142)
    at org.hibernate.collection.internal.PersistentSet.iterator(PersistentSet.java:180)
    at com.email.EmailService.getUserEmailAddress(EmailService.java:152)
    at com.email.EmailService.buildEmailHeaderFromMailingId(EmailService.java:207)
    at com.email.EmailService.sendMessage(EmailService.java:78)
    at com.email.EmailService$$FastClassBySpringCGLIB$$66ae4112.invoke(<generated>)
    at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:649)
    at com.EmailService$$EnhancerBySpringCGLIB$$ed23dcaf.sendMessage(<generated>)
    at com.process.QuartzEmailProcess.executeInternal(QuartzEmailProcess.java:48)
    at org.springframework.scheduling.quartz.QuartzJobBean.execute(QuartzJobBean.java:75)
    at org.quartz.core.JobRunShell.run(JobRunShell.java:202)
    at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:573)

1 个答案:

答案 0 :(得分:1)

我能够通过更改SchedulerFactoryBean来解决问题

@Autowired
  HCJobFactory jobFactory;

  @Autowired
  DataSource dataSource;

  @Autowired
  ApplicationContext applicationContext;


  @Override
  public void afterPropertiesSet() throws Exception
  {
    setJobFactory( jobFactory.getJobFactory() );
    setApplicationContext(applicationContext);
    setDataSource( dataSource );
    //setTransactionManager( transactionManager );
    super.afterPropertiesSet();
  }