How to run my Scheduled Import on demand through a script in an Inbound Mail Action?

thomaskennedy
Tera Guru

I want to respond to the arrival of an email by importing the data through my transform map, without waiting for a scheduled import. I tried gs.executeNow() in my Inbound Mail Action:

 

var util = new x_acso_foo_imp.MailUtility();
var result = util.CopyAttachmentToDataSource(sys_email, "FooData", gs.getCurrentApplicationId());
if (result) {
    event.state = "stop_processing";
	
	// Run the import
    var gr_import = new GlideRecord('sysauto');
    gr_import.addQuery('name', 'Foo Data');
    gr_import.query();
    if (gr_import.next()) {
        gr_import.active = true;
        gr_import.update();
        gs.executeNow(gr_import); // NullPointerException
    }
    gr_import.active = false;
    gr_import.update();
}

But I get a NullPointerException. I gather from the documentation that executeNow supports only sys_auto_script. Is there a way to do this?

3 REPLIES 3

Punit S
Giga Guru

Hello,

 

Yes, you're correct that gs.executeNow() only supports sys_auto_script. However, you can use a workaround to achieve your goal.

Instead of using gs.executeNow(), you can create a scheduled job that runs your import script and then immediately executes it. You can do this by creating a new GlideRecord for sysauto_script and setting the run_type field to once. Then, set the script field to the script you want to execute and the active field to true.

After that, you can call executeNow() on the GlideScheduledJob record that corresponds to your new sysauto_script record. Here's an example of how you can modify your code to use this workaround:

 

var util = new x_acso_foo_imp.MailUtility();
var result = util.CopyAttachmentToDataSource(sys_email, "FooData", gs.getCurrentApplicationId());
if (result) {
    event.state = "stop_processing";
	
    // Create a new sysauto_script record to run the import
    var gr_import_script = new GlideRecord('sysauto_script');
    gr_import_script.setValue('name', 'Import Foo Data');
    gr_import_script.setValue('run_type', 'once');
    gr_import_script.setValue('script', 'transform.map.import("FooData")');
    gr_import_script.setValue('active', true);
    var import_script_id = gr_import_script.insert();
    
    // Schedule and execute the import script
    var scheduled_job = new GlideRecord('sysauto');
    scheduled_job.addQuery('name', 'Import Foo Data');
    scheduled_job.query();
    if (scheduled_job.next()) {
        gs.log('Executing import of Foo Data');
        gs.log('Script: ' + scheduled_job.script);
        gs.log('Run Type: ' + scheduled_job.run_type);
        gs.executeNow(scheduled_job);
    }
    gr_import_script.setValue('active', false);
    gr_import_script.update();
}

 

This code creates a new sysauto_script record with the name "Import Foo Data" and the script transform.map.import("FooData"). It then sets the run_type field to once and the active field to true, inserts the record, and stores its sys_id in the import_script_id variable.

After that, it searches for the corresponding sysauto record for the import script, executes it using gs.executeNow(), and finally sets the active field to false on the sysauto_script record. This ensures that the script won't be run again unless you activate it manually.

 

Please mark my answer correct/helpful in case it adds value and moves you a step closer to your desired ServiceNow solution goal. 

Thanks,
Punit

I want the import to run a few seconds after the data source is updated. If I edit the scheduled import and set the run start to 4:08 (two minutes from now) by hand, it runs as expected.

But if I try setting the run start in script, it seems to interpret this as UTC. The result is a run start four hours in the past:

 

var gdt = new GlideDateTime();
gdt.addSeconds(10);

var gr_scheduled_import_set = new GlideRecord("scheduled_import_set");
gr_scheduled_import_set.addQuery("name", "Spencer Data");
gr_scheduled_import_set.query();
gr_scheduled_import_set.next();
gr_scheduled_import_set.setValue("run_start", gdt.getDisplayValue()); // 2023-04-04 16:08:53
gr_scheduled_import_set.update();

thomaskennedy_0-1680642609410.png

So I corrected for this in script:

// add ten seconds
var gdt = new GlideDateTime();
gdt.addSeconds(10);
gdt.addSeconds( -1 * (gdt.getTZOffset() / 1000) );

And that works fine. But is there a better way to do this?

 

 

thomaskennedy
Tera Guru

That looks right but I've not been able to get it working. This line returns null:

var import_script_id = gr_import_script.insert();

I also tried initialize() and update();

When I try to set up a script execution by hand, it does not like this line:

thomaskennedy_0-1680623576863.png

Do you see a problem here?