use of org.pentaho.platform.api.scheduler2.IBackgroundExecutionStreamProvider in project pentaho-platform by pentaho.
the class LocalActionInvokerTest method getStreamProviderWithInputAndOutputFileTest.
@Test
public void getStreamProviderWithInputAndOutputFileTest() throws IOException {
Map<String, Serializable> paramMap = new HashMap<>();
RepositoryFileStreamProvider repositoryFileStreamProvider = new RepositoryFileStreamProvider();
File inputFile = new File("example.txt");
BufferedWriter output = new BufferedWriter(new FileWriter(inputFile));
output.write("TEST TEXT");
paramMap.put(ActionUtil.INVOKER_STREAMPROVIDER, repositoryFileStreamProvider);
paramMap.put(ActionUtil.INVOKER_STREAMPROVIDER_INPUT_FILE, inputFile);
paramMap.put(ActionUtil.INVOKER_STREAMPROVIDER_OUTPUT_FILE_PATTERN, inputFile);
paramMap.put(ActionUtil.INVOKER_STREAMPROVIDER_UNIQUE_FILE_NAME, true);
IBackgroundExecutionStreamProvider iBackgroundExecutionStreamProvider = defaultActionInvoker.getStreamProvider(paramMap);
Assert.assertEquals(iBackgroundExecutionStreamProvider, repositoryFileStreamProvider);
}
use of org.pentaho.platform.api.scheduler2.IBackgroundExecutionStreamProvider in project pentaho-platform by pentaho.
the class ActionAdapterQuartzJob method invokeAction.
/**
* Invokes the {@link IAction} bean that is created from the provided {@code actionClassName} and {@code actionId} as
* the provided {@code actionUser}. If the {@code IAction} execution fails as-is, the scheduler attempts to re-create
* the job that will try to invoke the {@link IAction} again.
*
* @param actionClassName The class name of the {@link IAction} bean; used as a backup, if the {@code actionId} is not
* available or vald
* @param actionId The bean id of the {@link IAction} requested to be invoked.
* @param actionUser The user invoking the {@link IAction}
* @param context the {@code JobExecutionContext}
* @param params the {@link Map} or parameters needed to invoke the {@link IAction}
* @throws Exception when the {@code IAction} cannot be invoked for some reason.
*/
protected void invokeAction(final String actionClassName, final String actionId, final String actionUser, final JobExecutionContext context, final Map<String, Serializable> params) throws Exception {
final String workItemUid = ActionUtil.extractUid(params);
WorkItemLifecycleEventUtil.publish(workItemUid, params, WorkItemLifecyclePhase.SUBMITTED);
// creates an instance of IActionInvoker, which knows how to invoke this IAction - if the IActionInvoker bean is
// not defined through spring, fall back on the default action invoker
final IActionInvoker actionInvoker = Optional.ofNullable(PentahoSystem.get(IActionInvoker.class)).orElse(getActionInvoker());
// Instantiate the requested IAction bean
final IAction actionBean = (IAction) ActionUtil.createActionBean(actionClassName, actionId);
if (actionInvoker == null || actionBean == null) {
final String failureMessage = Messages.getInstance().getErrorString(// $NON-NLS-1$
"ActionAdapterQuartzJob.ERROR_0002_FAILED_TO_CREATE_ACTION", getActionIdentifier(null, actionClassName, actionId), StringUtil.getMapAsPrettyString(params));
WorkItemLifecycleEventUtil.publish(workItemUid, params, WorkItemLifecyclePhase.FAILED, failureMessage);
throw new LoggingJobExecutionException(failureMessage);
}
if (actionBean instanceof BlockoutAction) {
params.put(IBlockoutManager.SCHEDULED_FIRE_TIME, context.getScheduledFireTime());
}
// Invoke the action and get the status of the invocation
final IActionInvokeStatus status = actionInvoker.invokeAction(actionBean, actionUser, getSerializableMap(params));
// Status may not be available for remote execution, which is expected
if (status == null) {
if (log.isWarnEnabled()) {
log.warn(Messages.getInstance().getErrorString(// $NON-NLS-1$
"ActionAdapterQuartzJob.WARN_0002_NO_STATUS", getActionIdentifier(actionBean, actionClassName, actionId), StringUtil.getMapAsPrettyString(params)));
}
return;
}
// exception
if (!status.isExecutionSuccessful()) {
// throw job exception
throw new JobExecutionException(Messages.getInstance().getActionFailedToExecute(// $NON-NLS-1$
actionBean.getClass().getName()));
}
final boolean requiresUpdate = status.requiresUpdate();
final Throwable throwable = status.getThrowable();
Object objsp = status.getStreamProvider();
IBackgroundExecutionStreamProvider sp = null;
if (objsp != null && IBackgroundExecutionStreamProvider.class.isAssignableFrom(objsp.getClass())) {
sp = (IBackgroundExecutionStreamProvider) objsp;
}
final IBackgroundExecutionStreamProvider streamProvider = sp;
// shallow copy
final Map<String, Serializable> jobParams = new HashMap<String, Serializable>(params);
final IScheduler scheduler = PentahoSystem.getObjectFactory().get(IScheduler.class, "IScheduler2", null);
if (throwable != null) {
Object restartFlag = jobParams.get(QuartzScheduler.RESERVEDMAPKEY_RESTART_FLAG);
if (restartFlag == null) {
final SimpleJobTrigger trigger = new SimpleJobTrigger(new Date(), null, 0, 0);
final Class<IAction> iaction = (Class<IAction>) actionBean.getClass();
// recreate the job in the context of the original creator
SecurityHelper.getInstance().runAsUser(actionUser, new Callable<Void>() {
@Override
public Void call() throws Exception {
if (streamProvider != null) {
// remove generated content
streamProvider.setStreamingAction(null);
}
QuartzJobKey jobKey = QuartzJobKey.parse(context.getJobDetail().getName());
String jobName = jobKey.getJobName();
jobParams.put(QuartzScheduler.RESERVEDMAPKEY_RESTART_FLAG, Boolean.TRUE);
WorkItemLifecycleEventUtil.publish(workItemUid, params, WorkItemLifecyclePhase.RESTARTED);
scheduler.createJob(jobName, iaction, jobParams, trigger, streamProvider);
log.warn("New RunOnce job created for " + jobName + " -> possible startup synchronization error");
return null;
}
});
} else {
log.warn("RunOnce already created, skipping");
}
throw new JobExecutionException(throwable);
}
scheduler.fireJobCompleted(actionBean, actionUser, params, streamProvider);
if (requiresUpdate) {
log.warn("Output path for job: " + context.getJobDetail().getName() + " has changed. Job requires update");
try {
final IJobTrigger trigger = scheduler.getJob(context.getJobDetail().getName()).getJobTrigger();
final Class<IAction> iaction = (Class<IAction>) actionBean.getClass();
// remove job with outdated/invalid output path
scheduler.removeJob(context.getJobDetail().getName());
// recreate the job in the context of the original creator
SecurityHelper.getInstance().runAsUser(actionUser, new Callable<Void>() {
@Override
public Void call() throws Exception {
// remove generated content
streamProvider.setStreamingAction(null);
QuartzJobKey jobKey = QuartzJobKey.parse(context.getJobDetail().getName());
String jobName = jobKey.getJobName();
WorkItemLifecycleEventUtil.publish(workItemUid, params, WorkItemLifecyclePhase.RESTARTED);
org.pentaho.platform.api.scheduler2.Job j = scheduler.createJob(jobName, iaction, jobParams, trigger, streamProvider);
log.warn("New Job: " + j.getJobId() + " created");
return null;
}
});
} catch (Exception e) {
log.error(e.getMessage(), e);
}
}
if (log.isDebugEnabled()) {
log.debug(MessageFormat.format("Scheduling system successfully invoked action {0} as user {1} with params [ {2} ]", // $NON-NLS-1$
actionBean.getClass().getName(), actionUser, QuartzScheduler.prettyPrintMap(params)));
}
}
use of org.pentaho.platform.api.scheduler2.IBackgroundExecutionStreamProvider in project pentaho-platform by pentaho.
the class ActionRunnerTest method testCallThrowsException.
@Test
public void testCallThrowsException() throws Exception {
Map<String, Serializable> paramsMap = createMapWithUserLocale();
IAction actionBeanSpy = Mockito.spy(new TestAction());
IBackgroundExecutionStreamProvider mockStreamProvider = Mockito.mock(IBackgroundExecutionStreamProvider.class);
when(mockStreamProvider.getInputStream()).thenThrow(new Exception("something went wrong"));
ActionRunner actionRunner = new ActionRunner(actionBeanSpy, "actionUser", paramsMap, mockStreamProvider);
exception.expect(ActionInvocationException.class);
actionRunner.call();
}
use of org.pentaho.platform.api.scheduler2.IBackgroundExecutionStreamProvider in project pentaho-platform by pentaho.
the class QuartzScheduler method createJob.
/**
* {@inheritDoc}
*/
protected Job createJob(String jobName, Map<String, Serializable> jobParams, IJobTrigger trigger, IBackgroundExecutionStreamProvider outputStreamProvider) throws SchedulerException {
String curUser = getCurrentUser();
// determine if the job params tell us who owns the job
Serializable jobOwner = jobParams.get(RESERVEDMAPKEY_ACTIONUSER);
if (jobOwner != null && jobOwner.toString().length() > 0) {
curUser = jobOwner.toString();
}
QuartzJobKey jobId = new QuartzJobKey(jobName, curUser);
Trigger quartzTrigger = createQuartzTrigger(trigger, jobId);
if (trigger.getEndTime() != null) {
quartzTrigger.setEndTime(trigger.getEndTime());
}
Calendar triggerCalendar = quartzTrigger instanceof CronTrigger ? createQuartzCalendar((ComplexJobTrigger) trigger) : null;
if (outputStreamProvider != null) {
jobParams.put(RESERVEDMAPKEY_STREAMPROVIDER, outputStreamProvider);
}
if (trigger.getUiPassParam() != null) {
jobParams.put(RESERVEDMAPKEY_UIPASSPARAM, trigger.getUiPassParam());
}
if (!jobParams.containsKey(RESERVEDMAPKEY_LINEAGE_ID)) {
String uuid = UUID.randomUUID().toString();
jobParams.put(RESERVEDMAPKEY_LINEAGE_ID, uuid);
}
JobDetail jobDetail = createJobDetails(jobId, jobParams);
try {
Scheduler scheduler = getQuartzScheduler();
if (triggerCalendar != null) {
scheduler.addCalendar(jobId.toString(), triggerCalendar, false, false);
quartzTrigger.setCalendarName(jobId.toString());
}
logger.debug(MessageFormat.format("Scheduling job {0} with trigger {1} and job parameters [ {2} ]", jobId.toString(), trigger, // $NON-NLS-1$
prettyPrintMap(jobParams)));
scheduler.scheduleJob(jobDetail, quartzTrigger);
} catch (org.quartz.SchedulerException e) {
throw new SchedulerException(Messages.getInstance().getString("QuartzScheduler.ERROR_0001_FAILED_TO_SCHEDULE_JOB", jobName), // $NON-NLS-1$
e);
}
Job job = new Job();
job.setJobParams(jobParams);
job.setJobTrigger((JobTrigger) trigger);
job.setNextRun(quartzTrigger.getNextFireTime());
job.setLastRun(quartzTrigger.getPreviousFireTime());
job.setJobId(jobId.toString());
job.setJobName(jobName);
job.setUserName(curUser);
job.setState(JobState.NORMAL);
return job;
}
use of org.pentaho.platform.api.scheduler2.IBackgroundExecutionStreamProvider in project pentaho-platform by pentaho.
the class LocalActionInvoker method getStreamProvider.
/**
* Gets the stream provider from the {@code INVOKER_STREAMPROVIDER} key within the {@code params} {@link Map} or
* builds it from the input file and output dir {@link Map} values. Returns {@code null} if information needed to
* build the stream provider is not present in the {@code map}, which is perfectly ok for some
* {@link org.pentaho.platform.api.action.IAction} types.
*
* @param params the {@link Map} or parameters needed to invoke the {@link org.pentaho.platform.api.action.IAction}
* @return a {@link IBackgroundExecutionStreamProvider} represented in the {@code params} {@link Map}
*/
@Override
protected IBackgroundExecutionStreamProvider getStreamProvider(final Map<String, Serializable> params) {
if (params == null) {
logger.warn(Messages.getInstance().getMapNullCantReturnSp());
return null;
}
IBackgroundExecutionStreamProvider streamProvider = null;
final Object objsp = params.get(ActionUtil.INVOKER_STREAMPROVIDER);
if (objsp != null && IBackgroundExecutionStreamProvider.class.isAssignableFrom(objsp.getClass())) {
streamProvider = (IBackgroundExecutionStreamProvider) objsp;
if (streamProvider instanceof RepositoryFileStreamProvider) {
params.put(ActionUtil.INVOKER_STREAMPROVIDER_INPUT_FILE, ((RepositoryFileStreamProvider) streamProvider).getInputFilePath());
params.put(ActionUtil.INVOKER_STREAMPROVIDER_OUTPUT_FILE_PATTERN, ((RepositoryFileStreamProvider) streamProvider).getOutputFilePath());
params.put(ActionUtil.INVOKER_STREAMPROVIDER_UNIQUE_FILE_NAME, ((RepositoryFileStreamProvider) streamProvider).autoCreateUniqueFilename());
}
} else {
final String inputFile = params.get(ActionUtil.INVOKER_STREAMPROVIDER_INPUT_FILE) == null ? null : params.get(ActionUtil.INVOKER_STREAMPROVIDER_INPUT_FILE).toString();
final String outputFilePattern = params.get(ActionUtil.INVOKER_STREAMPROVIDER_OUTPUT_FILE_PATTERN) == null ? null : params.get(ActionUtil.INVOKER_STREAMPROVIDER_OUTPUT_FILE_PATTERN).toString();
boolean hasInputFile = !StringUtils.isEmpty(inputFile);
boolean hasOutputPattern = !StringUtils.isEmpty(outputFilePattern);
if (hasInputFile && hasOutputPattern) {
boolean autoCreateUniqueFilename = params.get(ActionUtil.INVOKER_STREAMPROVIDER_UNIQUE_FILE_NAME) == null || params.get(ActionUtil.INVOKER_STREAMPROVIDER_UNIQUE_FILE_NAME).toString().equalsIgnoreCase("true");
streamProvider = new RepositoryFileStreamProvider(inputFile, outputFilePattern, autoCreateUniqueFilename);
// put in the map for future lookup
params.put(ActionUtil.INVOKER_STREAMPROVIDER, streamProvider);
} else {
if (logger.isWarnEnabled()) {
logger.warn(Messages.getInstance().getMissingParamsCantReturnSp(String.format("%s, %s", ActionUtil.INVOKER_STREAMPROVIDER_INPUT_FILE, ActionUtil.INVOKER_STREAMPROVIDER_OUTPUT_FILE_PATTERN), // $NON-NLS-1$
params));
}
}
}
return streamProvider;
}
Aggregations