Advanced Customization > Business Logic Customization > Customizing Windchill Visualization Services > Custom Publishing > Solution > Procedure – Creating Custom Schedule Jobs > Custom Schedule Job Fundamentals
  
Custom Schedule Job Fundamentals
In addition to the out-of-the-box Schedule Jobs, you can also create your own custom jobs. To do this, start by creating or adding to a custom class in the Windchill codebase; for example ext.wvs.CustomJobs. In this class create a method with the following signature:
public static WTList <nameOfMethod>() or public static QuerySpec <nameOfMethod>() or public static QueryResult <nameOfMethod>()
You can use whatever method name you want, but it is important that the method be public, static, return a WTList and accept no arguments.
Then add the following to your wvs.properties.xconf file (edit as needed):
<Property default="MyCustomJob" name="myJob.description"/>
<Property default="ext.wvs.CustomJobs" name=" myJob.class"/>
<Property default="myCustomJob" name=" myJob.method"/>
<Property default="true" name=" myJob.enableOnContainers"/>
<Property default="myJob" name="schedulejobs<N>"/>
Line 1 (<Property default="MyCustomJob" name="myJob.description"/>) is what you see in the Scheduler UI to identify your custom job.
Line 2 (<Property default="ext.wvs.CustomJobs" name=" myJob.class"/>) is the fully qualified class where your custom method resides.
Line 3 (<Property default="myCustomJob" name=" myJob.method"/>) is the name of your custom method.
Line 4 (<Property default="true" name=" myJob.enableOnContainers"/>) defines whether or not the job code will have access to the container that the schedule job was initiated from. For example, the out-of-the-box schedule jobs only handle objects found in the container the schedule job was initiated from (i.e. Project, Product, Library, or Organization) because this value is set to true. If the value is set to false it would be the same as executing the job from the context of the Exchange container, no matter what container the schedule job was initiated from.
Line 5 (<Property default="myJob" name="schedulejobs<N>”/>) is to display your custom job in the Publish Scheduler Administrator. In the name string you must replace the <N> with the integer that follows that last schedulejobsN that is already defined.
Below is an example of a publish job:
public static WTlist myCustomJob() {
WTList wtl = new WTArrayList();
try {
QuerySpec qs = new QuerySpec(WTDocument.class);
WTContainerRef cr = ScheduleJobs.getCurrentContainer();
if (cr != null) {
ContainerSpec cs = new ContainerSpec();
cs.addSearchContainer(cr);
qs.setAdvancedQueryEnabled(true);
qs.appendWhere(
WTContainerHelper.getWhereContainerIn(cs, ,new Class[] {WTDocument.class}),
new int[]{0});
}
if (cr != null) qs.appendAnd();
qs.appendWhere(new SearchCondition(WTDocument.class,
Iterated.LATEST_ITERATION,
SearchCondition.IS_TRUE),
new int[]{0});

Representable doc = null;
int offset = 0;
BasicPageableQuerySpec bpqs = new BasicPageableQuerySpec();
bpqs.setPrimaryStatement(qs);
bpqs.setOffset(offset);
bpqs.setRange(1000);
PagingQueryResult qr =
(PagingQueryResult)PersistenceHelper.manager.find(bpqs);
long sessionId = qr.getSessionId();
int total = qr.getTotalSize();

while (true) {
while (qr.hasMoreElements()) {
doc = (Representable)((Object[])qr.nextElement())[0];
wtl.add(doc);
}

offset += qr.size();
if (offset >= total) break;

PageableQuerySpec pqs = new PagingSessionSpec(sessionId);
pqs.setOffset(offset);
pqs.setRange(1000);
qr = (PagingQueryResult)PersistenceHelper.manager.find(pqs);
}
if (sessionId > 0) PagingSessionHelper.closePagingSession(sessionId);
} catch(Exception e) {e.printStackTrace(); wtl = new WTArrayList ();}

return wtl;
}
* 
This example contains the use of a BasicPageableQuerySpec and PagingSessions to avoid out of memory errors. See JavaDoc in the wt.query and wt.fc packages for details.
This example would effectively ask for all latest iterations of any WTDocuments found in the current container to be published.
In line six of the example the following method is used from com.ptc.wvs.server.schedule.ScheduleJobs:
public static WTContainerRef getCurrentContainer()
The result of this method will be null if the schedule job was initiated from the Exchange container (Site) or if the enableOnContainers value is false in the job definition (see line four of properties shown prior to the example above). If the value of enableOnContainers is true, then a WTContainerRef of the container the schedule job was initiated from will be returned. In the example code, this is used to filter the scope of the query to the Organization or the Product/Project/Library container the schedule job was initiated from.
* 
You can have multiple custom schedule jobs. Just use another method name in the same class, or use a new class altogether. For example:
public static WTList anotherCustomJob();
Then add the following to your wvs.properties.xconf file (edit as needed):
<Property default="AnotherCustomJob"
name="anotherJob.description"/>
<Property default="ext.wvs.CustomJobs" name=" anotherJob.class"/>
<Property default="anotherCustomJob" name=" anotherJob.method"/>
<Property default="true" name=" anotherJob.enableOnContainers"/>
<Property default="anotherJob" name="schedulejobs<N>"/>