Fix bug [1966880] - Scheduled Processes only run in System client

https://sourceforge.net/tracker/index.php?func=detail&aid=1966880&group_id=176962&atid=879332
Fix bug [1926032] - Schedule incorrectly identified variables
https://sourceforge.net/tracker/index.php?func=detail&aid=1926032&group_id=176962&atid=879332
See additional documentation on http://www.adempiere.com/index.php/ManPageW_Scheduler#Contributions
This commit is contained in:
Carlos Ruiz 2010-03-14 00:39:16 +00:00
parent 976bee6dd0
commit a8d4ee3e05
3 changed files with 114 additions and 114 deletions

View File

@ -222,14 +222,15 @@ public class MScheduler extends X_AD_Scheduler
MUserRoles ur = urs[j]; MUserRoles ur = urs[j];
if (!ur.isActive()) if (!ur.isActive())
continue; continue;
list.add(ur.getAD_User_ID()); if (!list.contains(ur.getAD_User_ID()))
list.add(ur.getAD_User_ID());
} }
} }
} }
// Add Updater // Add Updater
if (list.size() == 0) if (list.size() == 0)
{ {
list.add(getUpdatedBy()); list.add(getCreatedBy());
} }
// //
return list.toArray(new Integer[list.size()]); return list.toArray(new Integer[list.size()]);

View File

@ -1,5 +1,5 @@
/****************************************************************************** /******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution * * Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it * * This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published * * under the terms version 2 of the GNU General Public License as published *
@ -32,7 +32,6 @@ import org.compiere.model.MLdapProcessor;
import org.compiere.model.MRequestProcessor; import org.compiere.model.MRequestProcessor;
import org.compiere.model.MScheduler; import org.compiere.model.MScheduler;
import org.compiere.model.MSystem; import org.compiere.model.MSystem;
import org.compiere.model.X_R_RequestProcessor;
import org.compiere.util.CLogger; import org.compiere.util.CLogger;
import org.compiere.util.Env; import org.compiere.util.Env;
import org.compiere.util.TimeUtil; import org.compiere.util.TimeUtil;
@ -87,6 +86,9 @@ public abstract class AdempiereServer extends Thread
p_client = MClient.get(m_ctx); p_client = MClient.get(m_ctx);
Env.setContext(m_ctx, "#AD_Client_ID", p_client.getAD_Client_ID()); Env.setContext(m_ctx, "#AD_Client_ID", p_client.getAD_Client_ID());
m_initialNap = initialNap; m_initialNap = initialNap;
Timestamp dateNextRun = getDateNextRun(true);
if (dateNextRun != null)
m_nextWork = dateNextRun.getTime();
// log.info(model.getName() + " - " + getThreadGroup()); // log.info(model.getName() + " - " + getThreadGroup());
} // ServerBase } // ServerBase
@ -355,11 +357,11 @@ public abstract class AdempiereServer extends Thread
long typeSec = 600; // 10 minutes long typeSec = 600; // 10 minutes
if (frequencyType == null) if (frequencyType == null)
typeSec = 300; // 5 minutes typeSec = 300; // 5 minutes
else if (X_R_RequestProcessor.FREQUENCYTYPE_Minute.equals(frequencyType)) else if (MRequestProcessor.FREQUENCYTYPE_Minute.equals(frequencyType))
typeSec = 60; typeSec = 60;
else if (X_R_RequestProcessor.FREQUENCYTYPE_Hour.equals(frequencyType)) else if (MRequestProcessor.FREQUENCYTYPE_Hour.equals(frequencyType))
typeSec = 3600; typeSec = 3600;
else if (X_R_RequestProcessor.FREQUENCYTYPE_Day.equals(frequencyType)) else if (MRequestProcessor.FREQUENCYTYPE_Day.equals(frequencyType))
typeSec = 86400; typeSec = 86400;
// //
return typeSec * 1000 * frequency; // ms return typeSec * 1000 * frequency; // ms

View File

@ -1,5 +1,5 @@
/****************************************************************************** /******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution * * Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. * * Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* This program is free software; you can redistribute it and/or modify it * * This program is free software; you can redistribute it and/or modify it *
* under the terms version 2 of the GNU General Public License as published * * under the terms version 2 of the GNU General Public License as published *
@ -22,14 +22,18 @@ import it.sauronsoftware.cron4j.SchedulingPattern;
import java.io.File; import java.io.File;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.sql.Timestamp; import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Properties;
import java.util.logging.Level; import java.util.logging.Level;
import org.compiere.model.MAttachment; import org.compiere.model.MAttachment;
import org.compiere.model.MClient; import org.compiere.model.MClient;
import org.compiere.model.MNote; import org.compiere.model.MNote;
import org.compiere.model.MOrgInfo;
import org.compiere.model.MPInstance; import org.compiere.model.MPInstance;
import org.compiere.model.MPInstancePara; import org.compiere.model.MPInstancePara;
import org.compiere.model.MProcess; import org.compiere.model.MProcess;
import org.compiere.model.MRole;
import org.compiere.model.MScheduler; import org.compiere.model.MScheduler;
import org.compiere.model.MSchedulerLog; import org.compiere.model.MSchedulerLog;
import org.compiere.model.MSchedulerPara; import org.compiere.model.MSchedulerPara;
@ -72,6 +76,9 @@ public class Scheduler extends AdempiereServer
private it.sauronsoftware.cron4j.Scheduler cronScheduler; private it.sauronsoftware.cron4j.Scheduler cronScheduler;
private Predictor predictor; private Predictor predictor;
// ctx for the report/process
Properties m_schedulerctx = new Properties();
/** /**
* Work * Work
*/ */
@ -79,15 +86,36 @@ public class Scheduler extends AdempiereServer
{ {
m_summary = new StringBuffer(m_model.toString()) m_summary = new StringBuffer(m_model.toString())
.append(" - "); .append(" - ");
//
MProcess process = m_model.getProcess(); // Prepare a ctx for the report/process - BF [1966880]
m_schedulerctx.clear();
MClient schedclient = MClient.get(getCtx(), m_model.getAD_Client_ID());
Env.setContext(m_schedulerctx, "#AD_Client_ID", schedclient.getAD_Client_ID());
Env.setContext(m_schedulerctx, "#AD_Language", schedclient.getAD_Language());
Env.setContext(m_schedulerctx, "#AD_Org_ID", m_model.getAD_Org_ID());
if (m_model.getAD_Org_ID() != 0) {
MOrgInfo schedorg = MOrgInfo.get(getCtx(), m_model.getAD_Org_ID());
if (schedorg.getM_Warehouse_ID() > 0)
Env.setContext(m_schedulerctx, "#M_Warehouse_ID", schedorg.getM_Warehouse_ID());
}
Env.setContext(m_schedulerctx, "#AD_User_ID", getAD_User_ID());
Env.setContext(m_schedulerctx, "#SalesRep_ID", getAD_User_ID());
// TODO: It can be convenient to add AD_Scheduler.AD_Role_ID
MUser scheduser = MUser.get(getCtx(), getAD_User_ID());
MRole[] schedroles = scheduser.getRoles(m_model.getAD_Org_ID());
if (schedroles != null && schedroles.length > 0)
Env.setContext(m_schedulerctx, "#AD_Role_ID", schedroles[0].getAD_Role_ID()); // first role, ordered by AD_Role_ID
Timestamp ts = new Timestamp(System.currentTimeMillis());
SimpleDateFormat dateFormat4Timestamp = new SimpleDateFormat("yyyy-MM-dd");
Env.setContext(m_schedulerctx, "#Date", dateFormat4Timestamp.format(ts)+" 00:00:00" ); // JDBC format
Properties currentctx = Env.getCtx();
Env.setCtx(m_schedulerctx);
MProcess process = new MProcess(m_schedulerctx, m_model.getAD_Process_ID(), null);
try try
{ {
m_trx = Trx.get(Trx.createTrxName("Scheduler"), true); m_trx = Trx.get(Trx.createTrxName("Scheduler"), true);
if (process.isReport()) m_summary.append(runProcess(process));
m_summary.append(runReport(process));
else
m_summary.append(runProcess(process));
m_trx.commit(true); m_trx.commit(true);
} }
catch (Exception e) catch (Exception e)
@ -103,9 +131,12 @@ public class Scheduler extends AdempiereServer
m_trx.close(); m_trx.close();
} }
// Restore system context
Env.setCtx(currentctx);
// //
int no = m_model.deleteLog(); int no = m_model.deleteLog();
m_summary.append("Logs deleted=").append(no); m_summary.append(" Logs deleted=").append(no);
// //
MSchedulerLog pLog = new MSchedulerLog(m_model, m_summary.toString()); MSchedulerLog pLog = new MSchedulerLog(m_model, m_summary.toString());
pLog.setReference("#" + String.valueOf(p_runCount) pLog.setReference("#" + String.valueOf(p_runCount)
@ -114,76 +145,7 @@ public class Scheduler extends AdempiereServer
} // doWork } // doWork
/** /**
* Run Report * Run Process or Report
* @param process
* @return summary
* @throws Exception
*/
private String runReport(MProcess process) throws Exception
{ log.info(process.toString());
if (!process.isReport() || process.getAD_ReportView_ID() == 0)
return "Not a Report AD_Process_ID=" + process.getAD_Process_ID()
+ " - " + process.getName();
// Process
int AD_Table_ID = 0;
int Record_ID = 0;
//
MPInstance pInstance = new MPInstance(process, Record_ID);
fillParameter(pInstance);
//
ProcessInfo pi = new ProcessInfo (process.getName(), process.getAD_Process_ID(),
AD_Table_ID, Record_ID);
pi.setAD_User_ID(getAD_User_ID());
pi.setAD_Client_ID(m_model.getAD_Client_ID());
pi.setAD_PInstance_ID(pInstance.getAD_PInstance_ID());
if (!process.processIt(pi, m_trx) && pi.getClassName() != null)
return "Process failed: (" + pi.getClassName() + ") " + pi.getSummary();
// Report
ReportEngine re = ReportEngine.get(getCtx(), pi);
if (re == null)
return "Cannot create Report AD_Process_ID=" + process.getAD_Process_ID()
+ " - " + process.getName();
File report = re.getPDF();
// Notice
int AD_Message_ID = 884; // HARDCODED SchedulerResult
MUser from = new MUser(getCtx(), pi.getAD_User_ID(), null);
Integer[] userIDs = m_model.getRecipientAD_User_IDs();
for (int i = 0; i < userIDs.length; i++)
{
MUser user = new MUser(getCtx(), userIDs[i].intValue(), null);
boolean email = user.isNotificationEMail();
boolean notice = user.isNotificationNote();
if (notice)
{
MNote note = new MNote(getCtx(),
AD_Message_ID, userIDs[i].intValue(), m_trx.getTrxName());
note.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID());
note.setTextMsg(m_model.getName());
note.setDescription(m_model.getDescription());
note.setRecord(AD_Table_ID, Record_ID);
note.save();
// Attachment
MAttachment attachment = new MAttachment (getCtx(),
MNote.Table_ID, note.getAD_Note_ID(), m_trx.getTrxName());
attachment.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID());
attachment.addEntry(report);
attachment.setTextMsg(m_model.getName());
attachment.save();
}
if (email)
{
MClient client = MClient.get(m_model.getCtx(), m_model.getAD_Client_ID());
client.sendEMail(from, user, m_model.getName(), m_model.getDescription(), report);
}
}
//
return pi.getSummary();
} // runReport
/**
* Run Process
* @param process process * @param process process
* @return summary * @return summary
* @throws Exception * @throws Exception
@ -191,6 +153,9 @@ public class Scheduler extends AdempiereServer
private String runProcess(MProcess process) throws Exception private String runProcess(MProcess process) throws Exception
{ {
log.info(process.toString()); log.info(process.toString());
boolean isReport = (process.isReport() || process.getAD_ReportView_ID() > 0);
// Process (see also MWFActivity.performWork // Process (see also MWFActivity.performWork
int AD_Table_ID = 0; int AD_Table_ID = 0;
int Record_ID = 0; int Record_ID = 0;
@ -198,18 +163,15 @@ public class Scheduler extends AdempiereServer
MPInstance pInstance = new MPInstance(process, Record_ID); MPInstance pInstance = new MPInstance(process, Record_ID);
fillParameter(pInstance); fillParameter(pInstance);
// //
ProcessInfo pi = new ProcessInfo (process.getName(), process.getAD_Process_ID(), ProcessInfo pi = new ProcessInfo (process.getName(), process.getAD_Process_ID(), AD_Table_ID, Record_ID);
AD_Table_ID, Record_ID); pi.setAD_User_ID(getAD_User_ID());
int AD_User_ID = getAD_User_ID();
pi.setAD_User_ID(AD_User_ID);
pi.setAD_Client_ID(m_model.getAD_Client_ID()); pi.setAD_Client_ID(m_model.getAD_Client_ID());
pi.setAD_PInstance_ID(pInstance.getAD_PInstance_ID()); pi.setAD_PInstance_ID(pInstance.getAD_PInstance_ID());
MUser from = new MUser(getCtx(), pi.getAD_User_ID(), null); MUser from = new MUser(getCtx(), pi.getAD_User_ID(), null);
//notify supervisor if error if ( !process.processIt(pi, m_trx) ) // note, this call close the transaction, don't use m_trx below
if ( !process.processIt(pi, m_trx) )
{ {
// notify supervisor if error
int supervisor = m_model.getSupervisor_ID(); int supervisor = m_model.getSupervisor_ID();
if (supervisor > 0) if (supervisor > 0)
{ {
@ -226,9 +188,8 @@ public class Scheduler extends AdempiereServer
client.sendEMail(from, user, process.getName(), pi.getSummary() + " " + pi.getLogInfo(), null); client.sendEMail(from, user, process.getName(), pi.getSummary() + " " + pi.getLogInfo(), null);
} }
if (notice) { if (notice) {
int AD_Message_ID = 442; //ProcessRunError int AD_Message_ID = 442; // HARDCODED ProcessRunError
MNote note = new MNote(getCtx(), MNote note = new MNote(getCtx(), AD_Message_ID, supervisor, null);
AD_Message_ID, supervisor, null);
note.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID()); note.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID());
note.setTextMsg(pi.getSummary()); note.setTextMsg(pi.getSummary());
//note.setDescription(); //note.setDescription();
@ -239,6 +200,7 @@ public class Scheduler extends AdempiereServer
} }
else else
{ {
// notify recipients on success
Integer[] userIDs = m_model.getRecipientAD_User_IDs(); Integer[] userIDs = m_model.getRecipientAD_User_IDs();
if (userIDs.length > 0) if (userIDs.length > 0)
{ {
@ -246,24 +208,57 @@ public class Scheduler extends AdempiereServer
for (int i = 0; i < userIDs.length; i++) for (int i = 0; i < userIDs.length; i++)
{ {
MUser user = new MUser(getCtx(), userIDs[i].intValue(), null); MUser user = new MUser(getCtx(), userIDs[i].intValue(), null);
boolean email = user.isNotificationEMail(); boolean email = user.isNotificationEMail();
boolean notice = user.isNotificationNote(); boolean notice = user.isNotificationNote();
File report = null;
if (isReport) {
// Report
ReportEngine re = ReportEngine.get(m_schedulerctx, pi);
if (re == null)
return "Cannot create Report AD_Process_ID=" + process.getAD_Process_ID()
+ " - " + process.getName();
report = re.getPDF();
}
if (notice) {
int AD_Message_ID = 441; // ProcessOK
if (isReport)
AD_Message_ID = 884; // HARDCODED SchedulerResult
MNote note = new MNote(getCtx(), AD_Message_ID, userIDs[i].intValue(), null);
note.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID());
if (isReport) {
note.setTextMsg(m_model.getName());
note.setDescription(m_model.getDescription());
note.setRecord(AD_Table_ID, Record_ID);
} else {
note.setTextMsg(pi.getSummary());
// note.setDescription();
note.setRecord(MPInstance.Table_ID, pi.getAD_PInstance_ID());
}
if (note.save()) {
if (isReport) {
// Attachment
MAttachment attachment = new MAttachment (getCtx(), MNote.Table_ID, note.getAD_Note_ID(), null);
attachment.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID());
attachment.addEntry(report);
attachment.setTextMsg(m_model.getName());
attachment.save();
}
}
}
if (email) if (email)
{ {
MClient client = MClient.get(m_model.getCtx(), m_model.getAD_Client_ID()); MClient client = MClient.get(m_model.getCtx(), m_model.getAD_Client_ID());
client.sendEMail(from, user, process.getName(), pi.getSummary() + " " + pi.getLogInfo(), null); if (isReport) {
} client.sendEMail(from, user, m_model.getName(), m_model.getDescription(), report);
if (notice) { } else {
int AD_Message_ID = 441; //ProcessOK client.sendEMail(from, user, process.getName(), pi.getSummary() + " " + pi.getLogInfo(), null);
MNote note = new MNote(getCtx(), }
AD_Message_ID, userIDs[i].intValue(), null);
note.setClientOrg(m_model.getAD_Client_ID(), m_model.getAD_Org_ID());
note.setTextMsg(pi.getSummary());
//note.setDescription();
note.setRecord(MPInstance.Table_ID, pi.getAD_PInstance_ID());
note.save();
} }
} }
} }
} }
@ -274,10 +269,10 @@ public class Scheduler extends AdempiereServer
int AD_User_ID; int AD_User_ID;
if (m_model.getSupervisor_ID() > 0) if (m_model.getSupervisor_ID() > 0)
AD_User_ID = m_model.getSupervisor_ID(); AD_User_ID = m_model.getSupervisor_ID();
else if (m_model.getUpdatedBy() > 0)
AD_User_ID = m_model.getUpdatedBy();
else if (m_model.getCreatedBy() > 0) else if (m_model.getCreatedBy() > 0)
AD_User_ID = m_model.getCreatedBy(); AD_User_ID = m_model.getCreatedBy();
else if (m_model.getUpdatedBy() > 0)
AD_User_ID = m_model.getUpdatedBy();
else else
AD_User_ID = 100; //fall back to SuperUser AD_User_ID = 100; //fall back to SuperUser
return AD_User_ID; return AD_User_ID;
@ -306,7 +301,7 @@ public class Scheduler extends AdempiereServer
if (variable == null if (variable == null
|| (variable != null && variable.length() == 0)) || (variable != null && variable.length() == 0))
value = null; value = null;
else if (variable.indexOf('@') != -1) // we have a variable else if (variable.startsWith("@") && variable.endsWith("@")) // we have a variable / BF [1926032]
{ {
// Strip // Strip
int index = variable.indexOf('@'); int index = variable.indexOf('@');
@ -320,7 +315,9 @@ public class Scheduler extends AdempiereServer
} }
columnName = columnName.substring(0, index); columnName = columnName.substring(0, index);
// try Env // try Env
String env = Env.getContext(getCtx(), columnName); String env = Env.getContext(m_schedulerctx, columnName);
if (env == null || env.length() == 0)
env = Env.getContext(getCtx(), columnName);
if (env.length() == 0) if (env.length() == 0)
{ {
log.warning(sPara.getColumnName() log.warning(sPara.getColumnName()