首页 > 解决方案 > Spring Batch - 未关闭 - 由于静态方法调用

问题描述

我在 Spring Boot + CommandLineRunner 中完成了一个 spring 批处理(独立 Jar)。但是JVM在完成后没有关闭。在最初做了一些研究之后,我认为它没有因为以下原因而关闭。

1. 我没有在命令行运行器的末尾关闭 spring 应用程序上下文。
2. Executor 服务未正确关闭,这可能导致 JVM 关闭。

我不想调用 system.exit 这是一个强制关闭。

我尝试关闭应用程序上下文,并且还使用 isShutdown 方法验证了执行程序服务已关闭(返回 true)。

然后我找到了根本原因,这是因为我正在调用一个静态方法,这是罪魁祸首。当我评论静态方法调用时,即使我没有明确关闭应用程序上下文,作业也会正常关闭。

我不确定为什么会出现这种行为,我是否需要将所有内容都转换为对象,或者我在这里还缺少其他东西。有人可以请放一些光。

主班

    @SpringBootApplication
@ComponentScan(basePackages = "com.acn.abp.printbatch")
@EnableTransactionManagement
@ImportResource({ "ABPBatchInfrastructure.xml", "financeBillPayAppConfig.xml" })
public class financeBillPayFileUploadApplication extends PrintBatchConstants implements CommandLineRunner {

    @Autowired
    private NotifyConfig notify;

    @Autowired
    private ApplicationContext ctx;

    static final Logger logger = LoggerFactory.getLogger(financeBillPayFileUploadApplication.class);

    public static void main(String[] args) {
        SpringApplication application = new SpringApplication(financeBillPayFileUploadApplication.class);

        application.setBannerMode(Banner.Mode.OFF);
        application.run(args);

    }

    @Override
    public void run(String... args) throws Exception {

        logger.info(notify.getEnvironment());

        JobLauncher jobLauncher = ctx.getBean(JobLauncher.class);
        Job job = ctx.getBean(Job.class);

        jobLauncher.run(job,
                new JobParametersBuilder()
                .addString(batchDocumentClass, "InvoiceStatementDocumentation")
                .addString(batchType, "2020-06-04")
                .addString(batchEmailID, notify.getSupportEmailId())
                .addString(batchEnvironment, notify.getEnvironment())
                .toJobParameters());
        
System.out.println("Here cxf");

((ConfigurableApplicationContext)ctx).close();


    }

}

低于导致问题的类。如果我在下面的代码中注释掉,那么一切都会完美运行。

          populateItemDocuments(job, printConfig.geteCMObjectStore(), printConfig.geteCMUserId());

调用此方法的类文件

@Component
public class DuplexWorker implements Callable {

    static final Logger logger = LoggerFactory.getLogger(DuplexWorker.class);
    @Autowired
    private ManageFormService formgmtClient;
    @Autowired
    private PostScriptService postScriptService;
    @Autowired
    private BarcodeService barcodeService;

    private static CfBatchPrintConfiguration printConfig;
    
    private static CfPersistenceUtil dbUtilService;
    private static FilenetDocumentRetrieval docmgmtClient;

       @Autowired
       public DuplexWorker(CfPersistenceUtil dbUtilService,CfBatchPrintConfiguration printConfig,FilenetDocumentRetrieval docmgmtClient) {
           DuplexWorker.dbUtilService = dbUtilService;
           DuplexWorker.printConfig = printConfig;
           DuplexWorker.docmgmtClient=docmgmtClient;
       }

    
    private MailUtil mailUtil;
    
    private NotifyConfig notify;
    
    private List<PrintJobItem> printJobItems;
    
    private List<String> groupIds;
    
    
    private ArrayList duplexJobs;
    private String groupId;
    private CountDownLatch latch;

    
    public DuplexWorker(ArrayList duplexJobs, String groupId,CountDownLatch latch) {
        super();
        this.latch=latch;
        this.duplexJobs = duplexJobs;
        this.groupId = groupId;
    }
    public DuplexWorker(CountDownLatch latch, MailUtil mailUtil,NotifyConfig notify,List<PrintJobItem> findByPrintStatusEquals,List<String>groupIds) {
        this.latch=latch;
        this.mailUtil=mailUtil;
        this.notify=notify;
        this.printJobItems=findByPrintStatusEquals;
        this.groupIds=groupIds;

    }
    @Override
    public Object call() throws Exception {
        
        try {
        
        if ((duplexJobs != null) && (!duplexJobs.isEmpty())) {
            
              String prevJobId = null;
              int docCount = 0;
              CvPrintJob consolidatedPrintJob = (CvPrintJob)duplexJobs.get(0);

            
              ArrayList printItems = new ArrayList();
              
              if (consolidatedPrintJob != null)
              { 
                  
                  ArrayList items = consolidatedPrintJob.getPrintJobItems();
                  int numPages = 0;
                  if ((items != null) && (!items.isEmpty()))
                  {

                      CvPrintJobItem firstItem = (CvPrintJobItem)items.get(0);
                      
                      numPages = CfBatchPrintUtil.getItemTotalPages(firstItem);
                      logger.info("Item Total Pages == " + numPages);
                      logger.info("Job Item Page Limit == " + 
                        printConfig.getJobItemPageLimit());
                      consolidatedPrintJob.setSequence(firstItem.getSequence());

                  
                }
                  if (numPages <= printConfig.getJobItemPageLimit())
                  {
                    consolidatedPrintJob.setHasLargeItems(false);
                    logger.info("Item setHasLargeItems == false");
                  }
                  else
                  {
                    consolidatedPrintJob.setHasLargeItems(true);
                    logger.info("Item setHasLargeItems == true");
                  }

              }
              
              ArrayList startBannerDataList = new ArrayList();
              ArrayList barcodeList = new ArrayList();
              ArrayList barcodeCorresPageCount = new ArrayList();
              ArrayList statementNumberList = new ArrayList();
              for (int i = 0; i < duplexJobs.size(); i++)
              {
                CvPrintJob job = (CvPrintJob)duplexJobs.get(i);
                if ((prevJobId == null) || 
                  (!prevJobId.equalsIgnoreCase(job.getJobId()))) {
                  docCount = 0;
                }
                
                  populateItemDocuments(job, printConfig.geteCMObjectStore(), printConfig.geteCMUserId());
              }
              
              consolidatedPrintJob.setPrintJobItems(printItems);
              
   }
            else
            {
              logger.info("====================================================================");
              
              logger.info("=================>> No DUPLEX jobs to process <<===================");
              
              logger.info("====================================================================");
            }
            duplexJobs = null;
          
             
            this.latch.countDown();
            System.gc();
                return null;
                
        }catch(Exception e) {
            e.printStackTrace();
            return null;
        }
        
    }
    
      public static void populateItemDocuments(CvPrintJob job, String objectStore, String userid)
                throws CfException
              {
                
                logger.info("Enters populateItemDocuments");
                try
                {
                  ArrayList items = job.getPrintJobItems();
                  job.setIsProcess(true);
                  ArrayList modelDocList = null;
                  logger.info("Items size::::::" + items.size());
                  for (int i = 0; i < items.size(); i++)
                  {
                    modelDocList = new ArrayList();
                    CvPrintJobItem x = (CvPrintJobItem)items.get(i);
                    ArrayList guidList = x.getGuidList();
                    if ((guidList != null) && (!guidList.isEmpty())) {
                      modelDocList.addAll(guidList);
                    }
                    logger.info("guidList size::::::" + guidList.size());
                    
                    CvRenderPayloadRequest cvRenderPayloadRequest = null;
                    if ((modelDocList != null) && (!modelDocList.isEmpty()))
                    {
                      cvRenderPayloadRequest = new CvRenderPayloadRequest();
                      logger.info("Before creating CvRenderPayloadRequest");
                      logger.info("Document Class::: " + 
                        x.getDocumentClass());
                      cvRenderPayloadRequest.setDocumentClass(
                        x.getDocumentClass());
                      cvRenderPayloadRequest.setGuid(modelDocList);
                      cvRenderPayloadRequest.setUserId(userid);
                      logger.info("After creating the CvRenderPayloadRequest");
                      try
                      {
                        if (cvRenderPayloadRequest != null)
                        {
                          List pdfContents = docmgmtClient.retrieveDocument(cvRenderPayloadRequest.getGuid());
                          if ((pdfContents != null) && 
                            (!pdfContents.isEmpty()))
                          {
                            logger.info(
                              "PDF contents sizenew::::::::::::::" + pdfContents.size());
                            Iterator pdfItr = pdfContents.iterator();
                            while (pdfItr.hasNext())
                            {
                              byte[] contents = (byte[])pdfItr.next();
                              
                              CvPrintJobItem item = (CvPrintJobItem)items.get(i);
                              item.addDocumentList(contents);
                              
                              int filenetpagecount = 100;
                              item.setPageCountFromFileNet(filenetpagecount);
                              

                              logger.info("PageCOunt from Filenet " + filenetpagecount);
                            }
                          }
                        }
                      }
                      catch (Exception e)
                      {
                        e.printStackTrace();
                        throw new CfException(" Error populating documents" + e);
                      }
                    }
                  }
                }
                catch (Exception e)
                {
                  e.printStackTrace();
                  throw new CfException(" Error populating documents" + e);
                }
                logger.info("Exits populateItemDocuments");
              }
              

标签: javaspringspring-bootspring-batchexecutorservice

解决方案


首先,您使用的是运行应用程序的 Tomcat 服务器。如果你想制作独立的 spring 应用程序,你可以像下面这样配置

@Configuration
public class ApplicationMain {

    @Bean
    public Stackoverflow stackoverflow() {
        return new Stackoverflow ();
    }

    public static void main(String[] args) {
        ConfigurableApplicationContext configurableApplicationContext = new AnnotationConfigApplicationContext(ApplicationMain.class);
        System.out.println(configurableApplicationContext.getBean("stackoverflow"));
    }
}

'JVM 在完成后没有关闭。' 这是 Tomcat 服务器的正常行为,因为它等待处理请求。

你可以像下面这样给出基本包

new AnnotationConfigApplicationContext("com.example");

它会为你扫描包裹


推荐阅读