private boolean validateImportJob(final ImportNotification notification) { importJobStatusHandler.reportImportJobState( notification.getProcessId(), ImportJobState.VALIDATING); List<ImportBadRow> importBadRows = Collections.emptyList(); try { importBadRows = processValidation(notification); } catch (Exception exc) { LOG.error("Validation failed.", exc); importJobStatusHandler.reportImportJobState( notification.getProcessId(), ImportJobState.VALIDATION_FAILED); return false; } if (CollectionUtils.isNotEmpty(importBadRows)) { importJobStatusHandler.reportBadRows( notification.getProcessId(), importBadRows.toArray(new ImportBadRow[importBadRows.size()])); importJobStatusHandler.reportImportJobState( notification.getProcessId(), ImportJobState.VALIDATION_FAILED); return false; } importJobStatusHandler.reportImportJobState( notification.getProcessId(), ImportJobState.QUEUED_FOR_IMPORT); return true; }
/** * Sets the notification in processed state. * * @param notification the notification */ protected void unlock(final ImportNotification notification) { notification.setState(ImportNotificationState.PROCESSED); importNotificationDao.update(notification); if (LOG.isDebugEnabled()) { LOG.debug( "Import notification has been processed. Process ID: " + notification.getProcessId()); } }
/** * Validates one import job in case there is a notification for that. * * <p>Note: Only one job at a time will be processed. It is not clear what the consequences will * be in a clustered environment running different import jobs. All submitted import jobs are * executed in sequence ordered by the date of submission. */ public void launchImportJob() { final long startTime = System.currentTimeMillis(); LOG.info("Start import job quartz job at: " + new Date(startTime)); if (hasRunningImportJob()) { LOG.info("Import Job. Another processor is running at the moment. Quiting operation."); return; } List<ImportNotification> notifications = importNotificationDao.findByActionAndState( ImportAction.LAUNCH_IMPORT, ImportNotificationState.NEW, 1); if (CollectionUtils.isEmpty(notifications)) { LOG.info("Import Job. No notifications found. Quiting operation."); return; } // grab the first notification. there should be only one. ImportNotification notification = notifications.iterator().next(); if (!lock(notification)) { LOG.info( "Import Job. Could not lock notification. Likely locked by another processor. " + notification); return; } try { if (isCancelled(notification.getProcessId())) { LOG.info("Import Job cancelled. Process ID: " + notification.getProcessId()); return; } if (validateImportJob(notification)) { if (isCancelled(notification.getProcessId())) { LOG.info("Import Job cancelled. Process ID: " + notification.getProcessId()); return; } ImportJobStatus importStatus = null; try { importStatus = executeImport(notification); } catch (Exception exc) { LOG.error("Import job failure.", exc); importJobStatusHandler.reportImportJobState( notification.getProcessId(), ImportJobState.FAILED); return; } sendEmail(importStatus, notification.getInitiator(), notification.getReportingLocale()); LOG.info( "Import job quartz job completed in (ms): " + (System.currentTimeMillis() - startTime)); } } finally { unlock(notification); } }
/** * Executes an import by getting the parameters from the notification. * * @param notification the notification * @return the status of the import */ protected ImportJobStatus executeImport(final ImportNotification notification) { ImportJob importJob = notification.getImportJob(); // update the CSV file path with the local file path notification.setImportSource(getRemoteCsvFileName(notification.getImportSource())); // Validate again final ImportDataType importDataType = importService.findImportDataType(importJob.getImportDataTypeName()); if (importDataType == null) { throw new EpSystemException( "ImportJob specifies unknown importDataType " + importJob.getImportDataTypeName()); } ImportJobRunner importJobRunner = getImportJobRunner(importDataType.getImportJobRunnerBeanName()); importJobRunner.init(notification, notification.getProcessId()); updateTotalRowsNumber(importJobRunner.getTotalRows(), notification.getProcessId()); importJobStatusHandler.reportImportJobState( notification.getProcessId(), ImportJobState.RUNNING); // Start the runner. LOG.info("Launch import job runner: " + importJobRunner); importJobRunner.run(); return importJobStatusHandler.getImportJobStatus(notification.getProcessId()); }
/** * Tries to lock the notification by setting it into in_process state. * * @param notification the notification to lock * @return true if the lock has been gained successfully */ protected boolean lock(final ImportNotification notification) { if (ObjectUtils.equals(ImportNotificationState.IN_PROCESS, notification.getState())) { return false; } // set in process on notification so that no other parties should take it over notification.setState(ImportNotificationState.IN_PROCESS); try { // update the notification which makes sure that no other participants will take it for // processing // could throw OptimisticLockException wrapped in EpPersistenceException when some other party // has updated the same object which means that it was already locked importNotificationDao.update(notification); } catch (EpPersistenceException exc) { LOG.debug("Cannot gain lock over notification: " + notification, exc); return false; } return true; }
/** * Process the validation by using the import job runner. * * @param notification the notification * @return a list of bad rows */ protected List<ImportBadRow> processValidation(final ImportNotification notification) { ImportJob importJob = notification.getImportJob(); // update the CSV file path with the local file path notification.setImportSource(getRemoteCsvFileName(notification.getImportSource())); // Validate again final ImportDataType importDataType = importService.findImportDataType(importJob.getImportDataTypeName()); if (importDataType == null) { throw new EpSystemException( "ImportJob specifies unknown importDataType " + importJob.getImportDataTypeName()); } ImportJobRunner importJobRunner = getImportJobRunner(importDataType.getImportJobRunnerBeanName()); importJobRunner.init(notification, notification.getProcessId()); return importJobRunner.validate(notification.getReportingLocale()); }