Community Tip - Want the oppurtunity to discuss enhancements to PTC products? Join a working group! X
Hi.
I need run some code in Windchill to update objects. I need start this task at specified time and rerun it in some period.
So i tried to use java.util.TimerTask implementation.
Some code example i used:
public class MyServiceManager extends wt.services.StandardManager {
private static Logger LOGGER = LogR.getLogger(MyServiceManager .class.getName());
public static MyServiceManager newMyServiceManager () throws WTException {
MyServiceManager instance = new MyServiceManager ();
instance.initialize();
return instance;
}
@Override
protected synchronized void performStartupProcess() throws ManagerException {
try {
/*some code to init firstTime and period*/
Timer timer = new Timer();
timer.scheduleAtFixedRate(new MyTimerTask(), firstTime, period);
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
}
public class MyTimerTask extends java.util.TimerTask {
private static Logger LOGGER = LogR.getLogger(MyTimerTask.class.getName());
public MyTimerTask() {
//
}
@Override
public void run() {
try {
QuerySpec querySpec = new QuerySpec();
//fill query spec with conditions
QueryResult qr = PersistenceHelper.manager.find((StatementSpec) querySpec); // and i get exception here
//
} catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
}
}
In PersistenceHelper.manager.find i get exception:
Message: Resource bundle/Message key = wt.pom.pomResource/0
(wt.pom.pomResource/0) wt.pom.POMInitException: A persistence error occurred. System message follows:
Nested exception is: wt.method.MethodServerException: No active method context
at wt.method.MethodContext.getContext(MethodContext.java:1725)
at wt.pom.PersistentObjectManager.getPom(PersistentObjectManager.java:289)
at wt.fc.StandardPersistenceManager._query(StandardPersistenceManager.java:1993)
at wt.fc.StandardPersistenceManager._find(StandardPersistenceManager.java:2022)
at wt.fc.StandardPersistenceManager.find(StandardPersistenceManager.java:681)
at sun.reflect.GeneratedMethodAccessor22.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at wt.services.ServiceFactory$ServerInvocationHandler.invoke(ServiceFactory.java:399)
at com.sun.proxy.$Proxy9.find(Unknown Source)
What shouild i do to fix this? Or is there more appropriate way to run same task in Windchill?
I expect get java code example.
Thanks.
I wouldn't do it manually with a timer. Windchill has the ability to schedule jobs.
Have a look at the customization guide and search for the chapter: Procedure – Creating Custom Schedule Jobs
It works.
But is there a way to solve by background queue?
Yes, the task will probably running in the Methodserver. I don't have any solution to run it in the BMS. Perhaps somebody else can help...?
If you wan't to use a time, you need to create a Windchill context :
import wt.method.MethodContext
import wt.method.RemoteMethodServer
import wt.session.SessionContext
import wt.session.SessionHelper
new MethodContext(null, null)
SessionContext.newContext()
SessionHelper.manager.setPrincipal("wcadmin")
RemoteMethodServer rms = RemoteMethodServer.getDefault()
rms.setUserName("wcadmin")
rms.setPassword("wcadmin")
But as Bjorg said, it's not the best way. In fact, if you have several MS & a BGMS, the thread would run everywhere, and it would probably raise stranges issues.
I had to do something similar, and I used wt.queue.ScheduleQueue and its associated entry wt.queue.ScheduleQueueEntry
ScheduleQueueEntries have a "processAt" parameter.
The algorithm is :
And iat the end of the code launched by the ScheduleQueueEntry, you add a new entry in the queue. So there is always a pending job.
Some code :
The starting point is to call addQueueEntry(); in the performStartupProcess method.
Everyhting is done from this method.
Of course you need to define some constants, like HAGER_QUEUE_NAME
private static ScheduleQueue initialiseQueue(String qname)
throws WTException {
ScheduleQueue q = (ScheduleQueue) QueueHelper.manager.getQueue(qname, wt.queue.ScheduleQueue.class);
if (q == null) {
q = createScheduleQueue(qname);
//QueueHelper.manager.setInterval(q, interval);
// q = (ScheduleQueue)PersistenceHelper.manager.save(q); Voila qui ne m'a plus l'air n�cessaire.....
if (logger.isDebugEnabled()) {
logger.debug("initialiseQueue() - " + CLASSNAME + ".initialiseQueue() Creating Queue " + qname); //$NON-NLS-1$ //$NON-NLS-2$
}
}
if (logger.isDebugEnabled()) {
logger.debug("initialiseQueue() - " + CLASSNAME + ".initialiseQueue() Starting Queue " + qname); //$NON-NLS-1$ //$NON-NLS-2$
}
QueueHelper.manager.startQueue(q);
return q;
}
//##begin newStandardHagerService%newStandardHagerServicef.doc preserve=no
private static ScheduleQueue createScheduleQueue(String qname)
throws WTException {
ScheduleQueue schedulequeue = null;
try {
schedulequeue = QueueHelper.manager.createScheduleQueue(qname);
} catch (ObjectIsStaleException objectisstaleexception) {
schedulequeue = (ScheduleQueue) QueueHelper.manager.getQueue(qname, wt.queue.ScheduleQueue.class);
} catch (UniquenessException uniquenessexception) {
schedulequeue = (ScheduleQueue) QueueHelper.manager.getQueue(qname, wt.queue.ScheduleQueue.class);
}
return schedulequeue;
}
//##begin getAllSigleService%3BF8E35000FAg.doc preserve=no
public static void addQueueEntry() {
ScheduleQueue queue = null;
// Check existing entries
try {
QuerySpec qs = new QuerySpec(wt.queue.ScheduleQueueEntry.class);
ClassAttribute theClassAttribute = new ClassAttribute(wt.queue.ScheduleQueueEntry.class, "targetClass");
RelationalExpression theExpression = ConstantExpression.newExpression("ext.hager.services.StandardHagerService", theClassAttribute.getColumnDescriptor().getJavaType());
SearchCondition theCondition = new SearchCondition(theClassAttribute, SearchCondition.EQUAL, theExpression);
qs.appendWhere(theCondition);
qs.appendAnd();
theClassAttribute = new ClassAttribute(wt.queue.ScheduleQueueEntry.class, "statusInfo.code");
theExpression = ConstantExpression.newExpression("READY", theClassAttribute.getColumnDescriptor().getJavaType());
theCondition = new SearchCondition(theClassAttribute, SearchCondition.EQUAL, theExpression);
qs.appendWhere(theCondition);
QueryResult qr = PersistenceServerHelper.manager.query(qs);
if (qr.size() > 0) {
// Found something
if (logger.isDebugEnabled()) {
logger.debug("addQueueEntry() - " + CLASSNAME + ".addQueueEntry() No need to add an entry. "); //$NON-NLS-1$ //$NON-NLS-2$
}
return;
}
} catch (WTException wte) {
if (logger.isDebugEnabled()) {
logger.debug("addQueueEntry() - " + CLASSNAME + ".addQueueEntry() Exception caught " + wte.toString()); //$NON-NLS-1$ //$NON-NLS-2$
}
logger.error("addQueueEntry()", wte); //$NON-NLS-1$
return;
}
try {
queue = initialiseQueue(HAGER_QUEUE_NAME);
GregorianCalendar cDate = new GregorianCalendar();
cDate.add(Calendar.DAY_OF_YEAR, NB_JOURS_SCHED_QUEUE);
cDate.set(Calendar.HOUR, HEURE_TACHE_ARCHIVAGE);
cDate.set(Calendar.MINUTE, 0);
cDate.set(Calendar.SECOND, 0);
Timestamp processAt = new Timestamp(cDate.getTime().getTime());
//processAt = new Timestamp((new java.util.Date()).getTime()+10000);
WTPrincipal user = SessionContext.getEffectivePrincipal();
WTPrincipal admin = SessionHelper.manager.getAdministrator();
WTPrincipal admin2 = SessionContext.setEffectivePrincipal(admin);
queue.addEntry(
admin,
"archiveDocuments",
CLASSNAME,
new Class[]{},
new Object[]{},
processAt);
if (logger.isDebugEnabled()) {
logger
.debug("addQueueEntry() - " + CLASSNAME + ".addQueueEntry() Prochaine recherche des documents obol�tes � " + cDate.getTime()); //$NON-NLS-1$ //$NON-NLS-2$
}
SessionContext.setEffectivePrincipal(user);
} catch (WTException wte) {
if (logger.isDebugEnabled()) {
logger
.debug("addQueueEntry() - " + CLASSNAME + ".addQueueEntry() Exception caught " + wte.toString()); //$NON-NLS-1$ //$NON-NLS-2$
}
logger.error("addQueueEntry()", wte); //$NON-NLS-1$
return;
}
}
//-------------------------------------- code executed by the queue :
public static void archiveDocuments() throws WTException {
// all the hthings you need goes here...
// And here we go again.
addQueueEntry();
}
Will this code run only once at a specified time "processAt" ?
Yes, and the keey is to call
addQueueEntry();
at the end of your task, in "archiveDocuments" in this example