views:

360

answers:

2

I have created a very simple sharepoint timer job. All i want it to do is iterate through a list and update each list item so that it triggers an existing workflow that works fine. In other words all i am trying to do is work around the limitation that workflows cannot be triggered on a scheduled basis. I have written a class that inherits from SPJobDefinition that does the work and i have a class that inherits from SPFeatureReceiver to install and activate it. I have created the feature using SPVisualdev that my coleagues have used in the past for other SP development.

My Job class is below:

public class DriverSafetyCheckTrigger : SPJobDefinition
{
    private string pi_SiteUrl;
    public DriverSafetyCheckTrigger(string SiteURL, SPWebApplication WebApp):base("DriverSafetyCheckTrigger",WebApp,null, SPJobLockType.Job)
    {            
        this.Title = "DriverSafetyCheckTrigger";
        pi_SiteUrl = SiteURL;            
    }

    public override void Execute(Guid targetInstanceId)
    {
        using (SPSite siteCollection = new SPSite(pi_SiteUrl))
        {
            using (SPWeb site = siteCollection.RootWeb)
            {
                SPList taskList = site.Lists["Driver Safety Check"];
                foreach(SPListItem item in taskList.Items)
                {
                    item.Update();                        
                }
            }
        } 
    }
}

And the only thing in the feature reciever class is that i have overridden the FeatureActivated method below:

public override void FeatureActivated(SPFeatureReceiverProperties Properties)
    {
        SPSite site = Properties.Feature.Parent as SPSite;

        // Make sure the job isn't already registered.
        foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
        {
            if (job.Name == "DriverSafetyCheckTrigger")
                job.Delete();
        }

        // Install the job.
        DriverSafetyCheckTrigger oDriverSafetyCheckTrigger = new DriverSafetyCheckTrigger(site.Url, site.WebApplication);

        SPDailySchedule oSchedule = new SPDailySchedule();
        oSchedule.BeginHour = 1;

        oDriverSafetyCheckTrigger.Schedule = oSchedule;

        oDriverSafetyCheckTrigger.Update();
    }

The problem i have is that when i try to activate the feature it throws a NullReferenceException on the line oDriverSafetyCheckTrigger.Update(). I am not sure what is null in this case, the example i have followed for this is this tutorial. I am not sure what I am doing wrong.

A: 

I have similar code that is working in one of my Feature Receivers:

string jobName = "MyJobDefinition";

foreach (SPJobDefinition job in site.WebApplication.JobDefinitions)
{
    if (job.Name == jobName)
    {
        job.Delete();
    }
}

SPDailySchedule schedule = new SPDailySchedule();
schedule.EndHour = 2;
schedule.EndMinute = 59;
schedule.EndSecond = 59;

SPJobDefinition jobDefinition = new MyJobDefinition(jobName, site.WebApplication);
jobDefinition.Schedule = schedule;
jobDefinition.Update();

I wonder if your problem is with the schedule. Try setting BeginMinute and maybe also BeginSecond. You could also try setting the End values in conjunction with or instead of the Begin values.

Rich Bennema
+1  A: 

I ran your code in a console application and got the following exception when calling .Update()

"DriverSafetyCheckTrigger cannot be deserialized because it does not have a public default constructor"

Maybe that will help?

Paul Lucas
THanks anyway but i don't think that is the problem. It did used to have a parameterless constructor but it didn't make any difference. Also I am not trying to serialize/deserialize it. Thanks for your input anyway.
Ben Robinson
Apologies, this was in fact the problem. Sharepoint must try to serialize/deserialize the class for some reason. Anyway adding a parameterless constructor to DriverSafetyCheck class fixed the problem.
Ben Robinson
An explanation I can think of for the serialization/deserialization being necessary is because your DriverSafteyCheckTrigger class contains data. The pi_SiteUrl field is only given a value when you set up the timer job, but the timer job needs to use this value every time the job executes. If serialization wasn't happening, the pi_SiteUrl would be empty whenever the job executed.
Paul Lucas