IDEMPIERE-2756 Background threads losing context when user log out / integrate fix from hengsin for the server services

This commit is contained in:
Carlos Ruiz 2015-08-07 10:03:50 -05:00
parent d726d9c75a
commit ad6290e09c
2 changed files with 200 additions and 171 deletions

View File

@ -1,8 +1,8 @@
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* 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 *
/******************************************************************************
* Product: Adempiere ERP & CRM Smart Business Solution *
* Copyright (C) 1999-2006 ComPiere, Inc. All Rights Reserved. *
* 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 *
* by the Free Software Foundation. This program is distributed in the hope *
* that it will be useful, but WITHOUT ANY WARRANTY; without even the implied *
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. *
@ -16,62 +16,62 @@
*****************************************************************************/
package org.compiere.server;
import java.sql.Timestamp;
import java.util.Properties;
import java.util.logging.Level;
import org.compiere.model.AdempiereProcessor;
import org.compiere.model.AdempiereProcessor2;
import org.compiere.model.AdempiereProcessorLog;
import org.compiere.model.MClient;
import org.compiere.model.MSchedule;
import org.compiere.model.MSystem;
import org.compiere.util.CLogger;
import org.compiere.util.Env;
import org.compiere.util.TimeUtil;
/**
* Adempiere Server Base
*
* @author Jorg Janke
* @version $Id: AdempiereServer.java,v 1.3 2006/10/09 00:23:26 jjanke Exp $
*/
public abstract class AdempiereServer implements Runnable
{
import java.sql.Timestamp;
import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.util.ServerContext;
import org.compiere.model.AdempiereProcessor;
import org.compiere.model.AdempiereProcessor2;
import org.compiere.model.AdempiereProcessorLog;
import org.compiere.model.MClient;
import org.compiere.model.MSchedule;
import org.compiere.model.MSystem;
import org.compiere.model.PO;
import org.compiere.util.CLogger;
import org.compiere.util.Env;
import org.compiere.util.TimeUtil;
/**
* Adempiere Server Base
*
* @author Jorg Janke
* @version $Id: AdempiereServer.java,v 1.3 2006/10/09 00:23:26 jjanke Exp $
*/
public abstract class AdempiereServer implements Runnable
{
/**************************************************************************
* Server Base Class
* @param model model
* @param initialNap delay time running in sec
*/
protected AdempiereServer (AdempiereProcessor model, int initialNap)
{
p_model = model;
m_ctx = new Properties(model.getCtx());
if (p_system == null)
p_system = MSystem.get(m_ctx);
p_client = MClient.get(m_ctx);
Env.setContext(m_ctx, "#AD_Client_ID", p_client.getAD_Client_ID());
m_initialNap = initialNap;
Timestamp dateNextRun = getDateNextRun(true);
if (dateNextRun != null)
m_nextWork = dateNextRun.getTime();
long now = System.currentTimeMillis();
if (m_nextWork > now)
{
m_sleepMS = m_nextWork - now;
* @param model model
* @param initialNap delay time running in sec
*/
protected AdempiereServer (AdempiereProcessor model, int initialNap)
{
p_model = model;
if (p_system == null)
p_system = MSystem.get(model.getCtx());
p_client = MClient.get(model.getCtx(), model.getAD_Client_ID());
m_initialNap = initialNap;
Timestamp dateNextRun = getDateNextRun(true);
if (dateNextRun != null)
m_nextWork = dateNextRun.getTime();
long now = System.currentTimeMillis();
if (m_nextWork > now)
{
m_sleepMS = m_nextWork - now;
}
} // ServerBase
/** The Processor Model */
protected volatile AdempiereProcessor p_model;
/** Initial nap is seconds */
private int m_initialNap = 0;
/** Milliseconds to sleep - 0 Sec default */
protected long m_sleepMS = 0;
} // ServerBase
/** The Processor Model */
protected volatile AdempiereProcessor p_model;
/** Initial nap is seconds */
private int m_initialNap = 0;
/** Milliseconds to sleep - 0 Sec default */
protected long m_sleepMS = 0;
/** Sleeping */
private volatile boolean m_sleeping = true;
/** Server start time */
@ -89,8 +89,6 @@ public abstract class AdempiereServer implements Runnable
/** Logger */
protected CLogger log = CLogger.getCLogger(getClass());
/** Context */
private Properties m_ctx = null;
/** System */
protected volatile static MSystem p_system = null;
/** Client */
@ -102,7 +100,7 @@ public abstract class AdempiereServer implements Runnable
*/
public Properties getCtx()
{
return m_ctx;
return Env.getCtx();
} // getCtx
/**
@ -112,18 +110,41 @@ public abstract class AdempiereServer implements Runnable
{
return m_sleepMS;
} // getSleepMS
public long getInitialNap()
{
return m_initialNap;
public long getInitialNap()
{
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
*/
public void runNow()
{
m_sleeping = false;
public void doRunNow()
{
p_startWork = System.currentTimeMillis();
doWork();
long now = System.currentTimeMillis();
@ -135,31 +156,55 @@ public abstract class AdempiereServer implements Runnable
//
p_model.setDateLastRun(new Timestamp(now));
p_model.saveEx();
//
//
if (log.isLoggable(Level.FINE))
log.fine(getStatistics());
m_sleeping = true;
log.fine(getStatistics());
} // runNow
public void run()
{
final Thread currentThread = Thread.currentThread();
final String oldThreadName = currentThread.getName();
String newThreadName = getName();
boolean renamed = false;
if (!oldThreadName.equals(newThreadName)) {
try {
currentThread.setName(newThreadName);
renamed = true;
} 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;
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
*/
public void run ()
{
final Thread currentThread = Thread.currentThread();
final String oldThreadName = currentThread.getName();
String newThreadName = getName();
boolean renamed = false;
if (!oldThreadName.equals(newThreadName)) {
try {
currentThread.setName(newThreadName);
renamed = true;
} catch (SecurityException e) {}
}
m_sleeping = false;
if (m_start == 0)
m_start = System.currentTimeMillis();
protected void doRun()
{
if (m_start == 0)
m_start = System.currentTimeMillis();
// ---------------
p_startWork = System.currentTimeMillis();
@ -169,35 +214,29 @@ public abstract class AdempiereServer implements Runnable
p_runCount++;
m_runLastMS = now - p_startWork;
m_runTotalMS += m_runLastMS;
m_runTotalMS += m_runLastMS;
// Finished work - calculate datetime for next run
Timestamp lastRun = new Timestamp(now);
if (p_model instanceof AdempiereProcessor2)
{
AdempiereProcessor2 ap = (AdempiereProcessor2) p_model;
if (ap.isIgnoreProcessingTime())
{
lastRun = new Timestamp(p_startWork);
}
}
m_nextWork = MSchedule.getNextRunMS(lastRun.getTime(),
p_model.getScheduleType(), p_model.getFrequencyType(),
p_model.getFrequency(), p_model.getCronPattern());
m_sleepMS = m_nextWork - now;
if (log.isLoggable(Level.INFO)) log.info(" Next run: " + new Timestamp(m_nextWork) + " sleep " + m_sleepMS);
Timestamp lastRun = new Timestamp(now);
if (p_model instanceof AdempiereProcessor2)
{
AdempiereProcessor2 ap = (AdempiereProcessor2) p_model;
if (ap.isIgnoreProcessingTime())
{
lastRun = new Timestamp(p_startWork);
}
}
m_nextWork = MSchedule.getNextRunMS(lastRun.getTime(),
p_model.getScheduleType(), p_model.getFrequencyType(),
p_model.getFrequency(), p_model.getCronPattern());
m_sleepMS = m_nextWork - now;
if (log.isLoggable(Level.INFO)) log.info(" Next run: " + new Timestamp(m_nextWork) + " sleep " + m_sleepMS);
//
p_model.setDateLastRun(lastRun);
p_model.setDateNextRun(new Timestamp(m_nextWork));
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);
}
p_model.saveEx();
} // run
/**
@ -261,13 +300,13 @@ public abstract class AdempiereServer implements Runnable
} // getDescription
/**
* Get Model
* @return Model
*/
public AdempiereProcessor getModel()
{
return p_model;
} // getModel
* Get Model
* @return Model
*/
public AdempiereProcessor getModel()
{
return p_model;
} // getModel
/**
* Is Sleeping
@ -317,35 +356,35 @@ public abstract class AdempiereServer implements Runnable
} // getStartTime
/**
* Get Processor Logs
* @return logs
*/
public AdempiereProcessorLog[] getLogs()
{
return p_model.getLogs();
} // getLogs
protected boolean isInterrupted() {
return Thread.currentThread().isInterrupted();
}
public String getName() {
return p_model.getName();
}
public static boolean isOKtoRunOnIP(AdempiereProcessor model) {
if (model instanceof AdempiereProcessor2) {
int AD_Schedule_ID = ((AdempiereProcessor2)model).getAD_Schedule_ID();
MSchedule schedule = MSchedule.get(Env.getCtx(), AD_Schedule_ID);
if (!schedule.isOKtoRunOnIP())
{
return false; // done
}
}
return true;
}
} // AdempiereServer
* Get Processor Logs
* @return logs
*/
public AdempiereProcessorLog[] getLogs()
{
return p_model.getLogs();
} // getLogs
protected boolean isInterrupted() {
return Thread.currentThread().isInterrupted();
}
public String getName() {
return p_model.getName();
}
public static boolean isOKtoRunOnIP(AdempiereProcessor model) {
if (model instanceof AdempiereProcessor2) {
int AD_Schedule_ID = ((AdempiereProcessor2)model).getAD_Schedule_ID();
MSchedule schedule = MSchedule.get(Env.getCtx(), AD_Schedule_ID);
if (!schedule.isOKtoRunOnIP())
{
return false; // done
}
}
return true;
}
} // AdempiereServer

View File

@ -27,10 +27,8 @@ import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import org.adempiere.util.ServerContext;
import org.compiere.model.MAttachment;
import org.compiere.model.MClient;
import org.compiere.model.MNote;
@ -83,9 +81,6 @@ public class Scheduler extends AdempiereServer
/** Transaction */
protected Trx m_trx = null;
// ctx for the report/process
protected Properties m_schedulerctx = new Properties();
/**
* Work
*/
@ -95,29 +90,27 @@ public class Scheduler extends AdempiereServer
.append(" - ");
// 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());
Env.setContext(getCtx(), "#AD_Client_ID", schedclient.getAD_Client_ID());
Env.setContext(getCtx(), "#AD_Language", schedclient.getAD_Language());
Env.setContext(getCtx(), "#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(), null);
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(m_schedulerctx, "#SalesRep_ID", getAD_User_ID());
Env.setContext(getCtx(), "#AD_User_ID", getAD_User_ID());
Env.setContext(getCtx(), "#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
Env.setContext(getCtx(), "#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
ServerContext.setCurrentInstance(m_schedulerctx);
Env.setContext(getCtx(), "#Date", dateFormat4Timestamp.format(ts)+" 00:00:00" ); // JDBC format
MProcess process = new MProcess(m_schedulerctx, m_model.getAD_Process_ID(), null);
MProcess process = new MProcess(getCtx(), m_model.getAD_Process_ID(), null);
try
{
m_trx = Trx.get(Trx.createTrxName("Scheduler"), true);
@ -137,9 +130,6 @@ public class Scheduler extends AdempiereServer
m_trx.close();
}
// clear thread local context
ServerContext.dispose();
//
int no = m_model.deleteLog();
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());
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
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
//sql = Env.parseContext(m_vo.ctx, m_vo.WindowNo, sql, false, true); // replace variables
//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(""))
log.log(Level.WARNING, "(" + sPara.getColumnName() + ") - Default SQL variable parse failed: " + variable);
else {
@ -493,7 +483,7 @@ public class Scheduler extends AdempiereServer
String tail=index < (columnName.length()-1) ? columnName.substring(index+1) : null;
columnName = columnName.substring(0, index);
// try Env
String env = Env.getContext(m_schedulerctx, columnName);
String env = Env.getContext(getCtx(), columnName);
if (env == null || env.length() == 0)
env = Env.getContext(getCtx(), columnName);
if (env.length() == 0)