IDEMPIERE-2756 Background threads losing context when user log out / integrate fix from hengsin for the server services
This commit is contained in:
parent
d726d9c75a
commit
ad6290e09c
|
@ -20,12 +20,14 @@ import java.sql.Timestamp;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
|
import org.adempiere.util.ServerContext;
|
||||||
import org.compiere.model.AdempiereProcessor;
|
import org.compiere.model.AdempiereProcessor;
|
||||||
import org.compiere.model.AdempiereProcessor2;
|
import org.compiere.model.AdempiereProcessor2;
|
||||||
import org.compiere.model.AdempiereProcessorLog;
|
import org.compiere.model.AdempiereProcessorLog;
|
||||||
import org.compiere.model.MClient;
|
import org.compiere.model.MClient;
|
||||||
import org.compiere.model.MSchedule;
|
import org.compiere.model.MSchedule;
|
||||||
import org.compiere.model.MSystem;
|
import org.compiere.model.MSystem;
|
||||||
|
import org.compiere.model.PO;
|
||||||
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;
|
||||||
|
@ -47,11 +49,9 @@ public abstract class AdempiereServer implements Runnable
|
||||||
protected AdempiereServer (AdempiereProcessor model, int initialNap)
|
protected AdempiereServer (AdempiereProcessor model, int initialNap)
|
||||||
{
|
{
|
||||||
p_model = model;
|
p_model = model;
|
||||||
m_ctx = new Properties(model.getCtx());
|
|
||||||
if (p_system == null)
|
if (p_system == null)
|
||||||
p_system = MSystem.get(m_ctx);
|
p_system = MSystem.get(model.getCtx());
|
||||||
p_client = MClient.get(m_ctx);
|
p_client = MClient.get(model.getCtx(), model.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);
|
Timestamp dateNextRun = getDateNextRun(true);
|
||||||
|
@ -89,8 +89,6 @@ public abstract class AdempiereServer implements Runnable
|
||||||
|
|
||||||
/** Logger */
|
/** Logger */
|
||||||
protected CLogger log = CLogger.getCLogger(getClass());
|
protected CLogger log = CLogger.getCLogger(getClass());
|
||||||
/** Context */
|
|
||||||
private Properties m_ctx = null;
|
|
||||||
/** System */
|
/** System */
|
||||||
protected volatile static MSystem p_system = null;
|
protected volatile static MSystem p_system = null;
|
||||||
/** Client */
|
/** Client */
|
||||||
|
@ -102,7 +100,7 @@ public abstract class AdempiereServer implements Runnable
|
||||||
*/
|
*/
|
||||||
public Properties getCtx()
|
public Properties getCtx()
|
||||||
{
|
{
|
||||||
return m_ctx;
|
return Env.getCtx();
|
||||||
} // getCtx
|
} // getCtx
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -118,12 +116,35 @@ public abstract class AdempiereServer implements Runnable
|
||||||
return m_initialNap;
|
return m_initialNap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void runNow()
|
||||||
|
{
|
||||||
|
Properties context = new Properties();
|
||||||
|
Env.setContext(context, "#AD_Client_ID", p_model.getAD_Client_ID());
|
||||||
|
if (p_model instanceof PO) {
|
||||||
|
PO po = (PO) p_model;
|
||||||
|
if (po.get_ColumnIndex("AD_Org_ID") >= 0)
|
||||||
|
Env.setContext(context, "#AD_Org_ID", po.get_ValueAsInt("AD_Org_ID"));
|
||||||
|
if (po.get_ColumnIndex("AD_User_ID") >= 0)
|
||||||
|
Env.setContext(context, "#AD_User_ID", po.get_ValueAsInt("AD_User_ID"));
|
||||||
|
}
|
||||||
|
|
||||||
|
Properties prevContext = ServerContext.getCurrentInstance();
|
||||||
|
try {
|
||||||
|
ServerContext.setCurrentInstance(context);
|
||||||
|
m_sleeping = false;
|
||||||
|
doRunNow();
|
||||||
|
} finally {
|
||||||
|
ServerContext.dispose();
|
||||||
|
ServerContext.setCurrentInstance(prevContext);
|
||||||
|
m_sleeping = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Run Now
|
* Run Now
|
||||||
*/
|
*/
|
||||||
public void runNow()
|
public void doRunNow()
|
||||||
{
|
{
|
||||||
m_sleeping = false;
|
|
||||||
p_startWork = System.currentTimeMillis();
|
p_startWork = System.currentTimeMillis();
|
||||||
doWork();
|
doWork();
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
@ -138,13 +159,9 @@ public abstract class AdempiereServer implements Runnable
|
||||||
//
|
//
|
||||||
if (log.isLoggable(Level.FINE))
|
if (log.isLoggable(Level.FINE))
|
||||||
log.fine(getStatistics());
|
log.fine(getStatistics());
|
||||||
m_sleeping = true;
|
|
||||||
} // runNow
|
} // runNow
|
||||||
|
|
||||||
/**************************************************************************
|
public void run()
|
||||||
* Run async
|
|
||||||
*/
|
|
||||||
public void run ()
|
|
||||||
{
|
{
|
||||||
final Thread currentThread = Thread.currentThread();
|
final Thread currentThread = Thread.currentThread();
|
||||||
final String oldThreadName = currentThread.getName();
|
final String oldThreadName = currentThread.getName();
|
||||||
|
@ -157,7 +174,35 @@ public abstract class AdempiereServer implements Runnable
|
||||||
} catch (SecurityException e) {}
|
} catch (SecurityException e) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Properties context = new Properties();
|
||||||
|
Env.setContext(context, "#AD_Client_ID", p_model.getAD_Client_ID());
|
||||||
|
if (p_model instanceof PO) {
|
||||||
|
PO po = (PO) p_model;
|
||||||
|
if (po.get_ColumnIndex("AD_Org_ID") >= 0)
|
||||||
|
Env.setContext(context, "#AD_Org_ID", po.get_ValueAsInt("AD_Org_ID"));
|
||||||
|
if (po.get_ColumnIndex("AD_User_ID") >= 0)
|
||||||
|
Env.setContext(context, "#AD_User_ID", po.get_ValueAsInt("AD_User_ID"));
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ServerContext.setCurrentInstance(context);
|
||||||
m_sleeping = false;
|
m_sleeping = false;
|
||||||
|
doRun();
|
||||||
|
} finally {
|
||||||
|
m_sleeping = true;
|
||||||
|
ServerContext.dispose();
|
||||||
|
if (renamed) {
|
||||||
|
// Revert the name back if the current thread was renamed.
|
||||||
|
// We do not check the exception here because we know it works.
|
||||||
|
currentThread.setName(oldThreadName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**************************************************************************
|
||||||
|
* Run async
|
||||||
|
*/
|
||||||
|
protected void doRun()
|
||||||
|
{
|
||||||
if (m_start == 0)
|
if (m_start == 0)
|
||||||
m_start = System.currentTimeMillis();
|
m_start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
@ -192,12 +237,6 @@ public abstract class AdempiereServer implements Runnable
|
||||||
p_model.setDateLastRun(lastRun);
|
p_model.setDateLastRun(lastRun);
|
||||||
p_model.setDateNextRun(new Timestamp(m_nextWork));
|
p_model.setDateNextRun(new Timestamp(m_nextWork));
|
||||||
p_model.saveEx();
|
p_model.saveEx();
|
||||||
m_sleeping = true;
|
|
||||||
if (renamed) {
|
|
||||||
// Revert the name back if the current thread was renamed.
|
|
||||||
// We do not check the exception here because we know it works.
|
|
||||||
currentThread.setName(oldThreadName);
|
|
||||||
}
|
|
||||||
} // run
|
} // run
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -27,10 +27,8 @@ import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
|
||||||
import java.util.logging.Level;
|
import java.util.logging.Level;
|
||||||
|
|
||||||
import org.adempiere.util.ServerContext;
|
|
||||||
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;
|
||||||
|
@ -83,9 +81,6 @@ public class Scheduler extends AdempiereServer
|
||||||
/** Transaction */
|
/** Transaction */
|
||||||
protected Trx m_trx = null;
|
protected Trx m_trx = null;
|
||||||
|
|
||||||
// ctx for the report/process
|
|
||||||
protected Properties m_schedulerctx = new Properties();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Work
|
* Work
|
||||||
*/
|
*/
|
||||||
|
@ -95,29 +90,27 @@ public class Scheduler extends AdempiereServer
|
||||||
.append(" - ");
|
.append(" - ");
|
||||||
|
|
||||||
// Prepare a ctx for the report/process - BF [1966880]
|
// Prepare a ctx for the report/process - BF [1966880]
|
||||||
m_schedulerctx.clear();
|
|
||||||
MClient schedclient = MClient.get(getCtx(), m_model.getAD_Client_ID());
|
MClient schedclient = MClient.get(getCtx(), m_model.getAD_Client_ID());
|
||||||
Env.setContext(m_schedulerctx, "#AD_Client_ID", schedclient.getAD_Client_ID());
|
Env.setContext(getCtx(), "#AD_Client_ID", schedclient.getAD_Client_ID());
|
||||||
Env.setContext(m_schedulerctx, "#AD_Language", schedclient.getAD_Language());
|
Env.setContext(getCtx(), "#AD_Language", schedclient.getAD_Language());
|
||||||
Env.setContext(m_schedulerctx, "#AD_Org_ID", m_model.getAD_Org_ID());
|
Env.setContext(getCtx(), "#AD_Org_ID", m_model.getAD_Org_ID());
|
||||||
if (m_model.getAD_Org_ID() != 0) {
|
if (m_model.getAD_Org_ID() != 0) {
|
||||||
MOrgInfo schedorg = MOrgInfo.get(getCtx(), m_model.getAD_Org_ID(), null);
|
MOrgInfo schedorg = MOrgInfo.get(getCtx(), m_model.getAD_Org_ID(), null);
|
||||||
if (schedorg.getM_Warehouse_ID() > 0)
|
if (schedorg.getM_Warehouse_ID() > 0)
|
||||||
Env.setContext(m_schedulerctx, "#M_Warehouse_ID", schedorg.getM_Warehouse_ID());
|
Env.setContext(getCtx(), "#M_Warehouse_ID", schedorg.getM_Warehouse_ID());
|
||||||
}
|
}
|
||||||
Env.setContext(m_schedulerctx, "#AD_User_ID", getAD_User_ID());
|
Env.setContext(getCtx(), "#AD_User_ID", getAD_User_ID());
|
||||||
Env.setContext(m_schedulerctx, "#SalesRep_ID", getAD_User_ID());
|
Env.setContext(getCtx(), "#SalesRep_ID", getAD_User_ID());
|
||||||
// TODO: It can be convenient to add AD_Scheduler.AD_Role_ID
|
// TODO: It can be convenient to add AD_Scheduler.AD_Role_ID
|
||||||
MUser scheduser = MUser.get(getCtx(), getAD_User_ID());
|
MUser scheduser = MUser.get(getCtx(), getAD_User_ID());
|
||||||
MRole[] schedroles = scheduser.getRoles(m_model.getAD_Org_ID());
|
MRole[] schedroles = scheduser.getRoles(m_model.getAD_Org_ID());
|
||||||
if (schedroles != null && schedroles.length > 0)
|
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
|
Env.setContext(getCtx(), "#AD_Role_ID", schedroles[0].getAD_Role_ID()); // first role, ordered by AD_Role_ID
|
||||||
Timestamp ts = new Timestamp(System.currentTimeMillis());
|
Timestamp ts = new Timestamp(System.currentTimeMillis());
|
||||||
SimpleDateFormat dateFormat4Timestamp = new SimpleDateFormat("yyyy-MM-dd");
|
SimpleDateFormat dateFormat4Timestamp = new SimpleDateFormat("yyyy-MM-dd");
|
||||||
Env.setContext(m_schedulerctx, "#Date", dateFormat4Timestamp.format(ts)+" 00:00:00" ); // JDBC format
|
Env.setContext(getCtx(), "#Date", dateFormat4Timestamp.format(ts)+" 00:00:00" ); // JDBC format
|
||||||
ServerContext.setCurrentInstance(m_schedulerctx);
|
|
||||||
|
|
||||||
MProcess process = new MProcess(m_schedulerctx, m_model.getAD_Process_ID(), null);
|
MProcess process = new MProcess(getCtx(), m_model.getAD_Process_ID(), null);
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
m_trx = Trx.get(Trx.createTrxName("Scheduler"), true);
|
m_trx = Trx.get(Trx.createTrxName("Scheduler"), true);
|
||||||
|
@ -137,9 +130,6 @@ public class Scheduler extends AdempiereServer
|
||||||
m_trx.close();
|
m_trx.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear thread local context
|
|
||||||
ServerContext.dispose();
|
|
||||||
|
|
||||||
//
|
//
|
||||||
int no = m_model.deleteLog();
|
int no = m_model.deleteLog();
|
||||||
m_summary.append(" Logs deleted=").append(no);
|
m_summary.append(" Logs deleted=").append(no);
|
||||||
|
@ -161,7 +151,7 @@ public class Scheduler extends AdempiereServer
|
||||||
if (log.isLoggable(Level.INFO)) log.info(process.toString());
|
if (log.isLoggable(Level.INFO)) log.info(process.toString());
|
||||||
|
|
||||||
boolean isReport = (process.isReport() || process.getAD_ReportView_ID() > 0 || process.getJasperReport() != null || process.getAD_PrintFormat_ID() > 0);
|
boolean isReport = (process.isReport() || process.getAD_ReportView_ID() > 0 || process.getJasperReport() != null || process.getAD_PrintFormat_ID() > 0);
|
||||||
String schedulerName = Env.parseContext(m_schedulerctx, -1, m_model.getName(), false, true);
|
String schedulerName = Env.parseContext(getCtx(), -1, m_model.getName(), false, true);
|
||||||
|
|
||||||
// Process (see also MWFActivity.performWork
|
// Process (see also MWFActivity.performWork
|
||||||
int AD_Table_ID = m_model.getAD_Table_ID();
|
int AD_Table_ID = m_model.getAD_Table_ID();
|
||||||
|
@ -449,7 +439,7 @@ public class Scheduler extends AdempiereServer
|
||||||
String sql = variable.substring(5); // w/o tag
|
String sql = variable.substring(5); // w/o tag
|
||||||
//sql = Env.parseContext(m_vo.ctx, m_vo.WindowNo, sql, false, true); // replace variables
|
//sql = Env.parseContext(m_vo.ctx, m_vo.WindowNo, sql, false, true); // replace variables
|
||||||
//hengsin, capture unparseable error to avoid subsequent sql exception
|
//hengsin, capture unparseable error to avoid subsequent sql exception
|
||||||
sql = Env.parseContext(m_schedulerctx, 0, sql, false, false); // replace variables
|
sql = Env.parseContext(getCtx(), 0, sql, false, false); // replace variables
|
||||||
if (sql.equals(""))
|
if (sql.equals(""))
|
||||||
log.log(Level.WARNING, "(" + sPara.getColumnName() + ") - Default SQL variable parse failed: " + variable);
|
log.log(Level.WARNING, "(" + sPara.getColumnName() + ") - Default SQL variable parse failed: " + variable);
|
||||||
else {
|
else {
|
||||||
|
@ -493,7 +483,7 @@ public class Scheduler extends AdempiereServer
|
||||||
String tail=index < (columnName.length()-1) ? columnName.substring(index+1) : null;
|
String tail=index < (columnName.length()-1) ? columnName.substring(index+1) : null;
|
||||||
columnName = columnName.substring(0, index);
|
columnName = columnName.substring(0, index);
|
||||||
// try Env
|
// try Env
|
||||||
String env = Env.getContext(m_schedulerctx, columnName);
|
String env = Env.getContext(getCtx(), columnName);
|
||||||
if (env == null || env.length() == 0)
|
if (env == null || env.length() == 0)
|
||||||
env = Env.getContext(getCtx(), columnName);
|
env = Env.getContext(getCtx(), columnName);
|
||||||
if (env.length() == 0)
|
if (env.length() == 0)
|
||||||
|
|
Loading…
Reference in New Issue