Andrew Connell has published some great articles about creating custom Timer Jobs in SharePoint.
One thing that I think he missed to explain is how to persist data on the timer job itself.
In his MSDN article he describes a few options where to store the data required by the timer job.
He went into great detail on how to use the Hierarchical Object Storage and SPPersistedObject to store the settings.
It just happens to be that SPJobDefinition itself inherits from SPPersistedObject, so you can easily create fields on your custom job and retrieve them during execution.
So if we take Andrews sample where he stores the settings used by the timer job on the Web Application.
public class WarmupJobSettings : SPPersistedObject
{
[Persisted]
public List<Guid> SiteCollectionsEnabled = new List<Guid>();
public WarmupJobSettings() { }
public WarmupJobSettings(string name, SPPersistedObject parent, Guid id)
: base(name, parent, id)
{
}
}
public class SharePointWarmupJob : SPJobDefinition
{
// Omitted...
public override void Execute(Guid targetInstanceId)
{
// Get settings for the warmup job.
WarmupJobSettings settings = this.WebApplication.GetChild<WarmupJobSettings>(Globals.SharePointWarmupJobSettingsId);
foreach (SPSite siteCollection in this.WebApplication.Sites)
{
if (settings.SiteCollectionsEnabled.Contains(siteCollection.ID))
{
WarmUpSiteCollection(siteCollection);
}
siteCollection.RootWeb.Dispose();
siteCollection.Dispose();
}
}
}
And we rewrite it slightly to save the field on the job instead of on the WebApplication.
public class SharePointWarmupJob2 : SPJobDefinition
{
// The settings for the warmup job is stored on the Job itself
[Persisted]
public List<Guid> SiteCollectionsEnabled = new List<Guid>();
// Omitted...
public override void Execute(Guid targetInstanceId)
{
foreach (SPSite siteCollection in this.WebApplication.Sites)
{
try
{
if (this.SiteCollectionsEnabled.Contains(siteCollection.ID))
{
WarmUpSiteCollection(siteCollection);
}
}
finally
{
siteCollection.RootWeb.Dispose();
siteCollection.Dispose();
}
}
}
Here’s how the creation of the timer job changes.
protected void SetTimerJobsButton_OnClick(object sender, EventArgs e)
{
// Delete the job for the current Web application.
foreach (SPJobDefinition oldJob in this.WebAppSelector.CurrentItem.JobDefinitions)
{
if (oldJob.Title == Globals.JobName)
{
oldJob.Delete();
}
}
// Get a list of all the site collections that were requested to be enabled.
List<Guid> selectedSiteCollections = GetSelectedSiteCollections();
if (selectedSiteCollections.Count > 0)
{
// Create a new instance of the job and schedule it.
SPMinuteSchedule schedule = new SPMinuteSchedule();
schedule.BeginSecond = 0;
schedule.EndSecond = 59;
schedule.Interval = Convert.ToInt32(this.IntervalMinutesDropDownList.SelectedValue);
SharePointWarmupJob2 warmupJob = new SharePointWarmupJob2( this.WebAppSelector.CurrentItem );
// The setting is on the job itself.
warmupJob.SiteCollectionsEnabled = new List<Guid>(selectedSiteCollections);
warmupJob.Schedule = schedule;
warmupJob.Update();
}
}
Now you know that you can create arbitrary fields on the Job and use them during execution of the job, just add the fields and mark them as [Persisted].
If you prefer properties you can’t just decorate the property with the [Persisted] attribute, you have to manage the storage yourself like this:
public List<Guid> SiteCollectionsEnabled
{
get { return this.Properties["SiteCollectionsEnabled"] as List<Guid>; }
set { this.Properties["SiteCollectionsEnabled"] = value; }
}
/Jonas
Posted
May 17 2008, 11:15 PM
by
Jonas Nilsson