Clarity Service Management

SPEL EVENT methods 

10-28-2015 10:55 AM

SPEL EVENT methods

 

I was investigating bopevt.maj files for the new spel methods to use, when i found the following Warnings:

//    Do not attempt to directly delete this object.  instead call

//    'cancel_me' with the object checked out.  The object may set a

//    state flag or it may delete itself.

//

//    WARNING  It is not recommended to just make one of these.  It is

//    better to use the Event methods to create one for you  Sequence

//    of setting attributes the first time is imprtant.

 

 

I always use cancel_me method to cancel events, but for inserting them to atev table i always used generic method that inserts them directly into atev. So i decided to investigate those methods.

This document describes those methods that should be used for inserting and canceling attached events.

 

new_attached_event

Definition:

 

new_attached_event ( object | nil ,string,string,duration | nil, date | nil,  string | nil, int, int, string timezone);

 

object - you can pass here top_object object. More information can be found here https://communities.ca.com/message/241836353#241836353

string - persid of the object to attach to

string - event sym

duration - owerwrite standard delay

date - owerwrite standard start time

string - atev group usualy SLA, or if you wan't to hide it empty string

int - attached_sla.id

int - if 1 event will be in status delayed

string - time zone

 

Working example:

This code will insert an event with start date now, event delay will be overwrited to 2 min. Event wil be not visible in Service Type tab, so user will have no possibility to cancel it. This example uses top_object object

duration timeout;
timeout = 120;
object group_leader;
  send_wait(0, top_object(), "get_co_group");
    if (msg_error()) {
        printf("Error'%s'", msg[0]);
        return;
    }
else{
    group_leader = msg[0];

send_wait(0, top_object(), "call_attr", "evt", "new_attached_event", group_leader, "chg:400896","1hr chg unassigned", timeout ,now(), "SLA", 0, 0,"UTC");
if (msg_error()) {
printf("Error %s",msg[0]);
}
}
send_wait(0, group_leader, "checkin");
    if (msg_error()) {
        printf("Error'%s'", msg[0]);
    }




 

new_attached_event_obj

Definition:

 

new_attached_event_obj ( object | nil ,string,object,duration | nil, date | nil,  string | nil, int, int, string timezone);

 

object - you can pass here top_object object. More information can be found here https://communities.ca.com/message/241836353#241836353

string - persid of the object to attach to

object - event object to insert

duration - owerwrite standard delay

date - owerwrite standard start time

string - atev group usualy SLA, or if you wan't to hide it empty string

int - attached_sla.id

int - if 1 event will be in status delayed

string - time zone

 

Working example

This will insert an event with default start and delay time, event will be visible in Service Type tab

duration timeout;
date startdate;
object Objevt;

send_wait(0, top_object(), "call_attr", "evt", "dob_by_persid", 0, "evt:12202");
if (msg_error()) {
printf("Error %s",msg[0]);
}
else
{
  Objevt = msg[0];
  send_wait(0, top_object(), "call_attr", "evt", "new_attached_event_obj", NULL, "chg:400619",Objevt, timeout ,startdate, "SLA", 0, 0,"UTC");
  if (msg_error()) {
  printf("Error %s",msg[0]);
  }
}


 

cancel_me

 

Definition:

 

cancel_me()

 

Takes no arguments but needs to be run on particular attached event. Event needs to be checked out

 

Working example (much better example, provided by cdtj, can be found here: https://communities.ca.com/message/241810464#241810464)

send_wait(0, top_object(), "call_attr", "atev", "dob_by_persid", 0, "atev:400054");
if (msg_error()) {
printf("Error %s",msg[0]);
}
else
{
object evtObj, gl;
evtObj = msg[0];
printf(evtObj.cancel_time);

send_wait(0, top_object(), "get_co_group");
      if (msg_error()) {
           logf(ERROR, "Error : %s", msg[0]);
           return;
      }
      gl = msg[0];
   send_wait(0, gl, "checkout", evtObj);
      if (msg_error()) {
           logf(ERROR, "Error : %s", msg[0]);
           return;
      }

send_wait(0, evtObj, "cancel_me");
  if (msg_error()) {
  printf("Error %s",msg[0]);
  }

send_wait(0, gl, "checkin");
       if (msg_error()) {
            logf(ERROR, "Error : %s", msg[0]);
            send_wait(0, gl, "uncheck");
            return;
       }

}


Statistics
0 Favorited
5 Views
0 Files
0 Shares
0 Downloads

Tags and Keywords

Comments

09-30-2016 11:45 AM

Using the code provided by James, I created an event that is fired only on a specific status change.  Thanks again James!

 

In our environment, the purpose of this is to notify the Assignee and Requester when they leave a CO in Implemented status without filling out a custom field capturing post change notes.  The condition attached to this event checks if the custom field is null and the status is Implemented.  We couldn't add the event onto the Update Status activity because it will fire for each update status on the change order.

 

zCHG_Events.mod

OBJECT chg { 
TRIGGERS {
POST_CI zchgPCNReminder(persistent_id) 9139
FILTER( status { -> 'IMPD' } ) ;
} ;
} ;
OBJECT chg {
FACTORY {
METHODS {
zchgPCNReminder(string) ;
} ;
} ;
} ;

 

zCHG_PCN.spl

///////////////////////////////////////////////////// 
// Attaches an event to do the following:
//
// - Notify Assignee and Requester to fill the Post Change Notes
//
/////////////////////////////////////////////////////
int chg::zchgPCNReminder( ... ) //(string persistent_id)
{
//
string method;
method = "chg::zchgPCNReminder";
string in_persid;
string evt_pcn_reminder;
in_persid = argv[3];
logf(MILESTONE, "%s, started", method);
evt_pcn_reminder = "zChange Order Post Change Note Reminder";
string theChgID; // in_persid will be 'chg:nnnnn'
theChgID = substr(in_persid,4); // Just the digits
//
// Attach event to notify Assignee and Requestor
//
misc::site_att_chg_evt_byid( evt_pcn_reminder, (int)theChgID, 5, "zChgPCN" );
logf(MILESTONE, "%s, ended", method);
}

 

zCHGAttEvt.spl

#define ZDEBUG 99
void misc::site_att_chg_evt_byid( string event_sym, int chg_id, int delay_sec, string event_group_id )
{
string method;
method = "misc::site_att_chg_evt_byid";
string myTZ; myTZ = "GMT-0800"; // Swap for your own TZ
if ( ZDEBUG > 0 ) logf(MILESTONE, "%s: Started ", method);
//check symbol of event
int evt_id;
evt_id = (int)expand(format("&{'%s' = evt.sym->id}", event_sym));
if ( is_null(evt_id) || (evt_id == 0) )
{
logf(ERROR, "%s: Symbol of event '%s' is not recognized.", method, event_sym);
return;
}
if ( ZDEBUG > 0 ) logf(SIGNIFICANT, "%s: Event sym '%s' verified, attaching with delay %d...", method, event_sym, delay_sec);
send_wait(0, top_object(), "call_attr", "evt", "new_attached_event", (object)NULL,
format("chg:%d",chg_id), event_sym, (duration) delay_sec,
(date) NULL, event_group_id , 0, 0, myTZ);
if (msg_error())
{
logf(ERROR, "%s: error returned by new_attached_event: %s", method, (string)msg[0]);
return;
}
if ( ZDEBUG > 0 )
{
logf(TRACE, "%s: Attach event called ", method);
object attevt;
attevt = msg[0];
send_wait(0, attevt, "call_attr", "id", "get_val");
int attevt_id;
attevt_id = msg[0];
logf(MILESTONE, "%s: Finished. Attached event id = %d", method, attevt_id);
}
}

09-30-2016 10:26 AM

Wow, thank you for sharing James!  This is exactly what I'm looking for.

09-30-2016 12:50 AM

Hi Grant,

 

This is an example of a trigger definition - in 'zchg_triggers.mod'.  The spaces before braces and semicolons are important to make the definitions parse properly:

OBJECT chg {
   TRIGGERS {
      POST_CI zchgSetCABRequired(persistent_id, zEnvironment, chgtype, risk, impact) 9139
      FILTER( zEnvironment { } || chgtype { } || risk { } || impact { } ) ;
   } ;
} ;

OBJECT chg {
   FACTORY {
      METHODS {
            zchgSetCABRequired(string, int, int, int, int) ;
             } ;
       } ;
} ;

Then the function that the trigger calls - in 'zchgSetCABRequired.spl':

/////////////////////////////////////////////////////
// Attaches an event to do either of the following:
//
// - set CAB approval to YES if chg type is NORMAL and chg environment is PROD or PROD/TRAIN or RELEASE
// or if type is Emergency regardless of environment;
// - otherwise set CAB approval to NO.
//
// If change Risk AND Impact are both 'Low' (risk >= 4 AND impact <= 1),
// CAB approval is NOT required.
//
/////////////////////////////////////////////////////
#define ZDEBUG 1
int chg::zchgSetCABRequired( ... ) //(string persistent_id, int zEnvironment, int chgtype, int risk, int impact)
{
//
string method;
method = "chg::zchgSetCABRequired";

string in_persid;
int in_chgtype;
int in_risk;
int in_impact;
int in_zEnvironment;

string evt_set_cab_approval;

in_persid = argv[3];
in_zEnvironment = (int)argv[6];
in_chgtype = (int)argv[9];
in_risk = (int)argv[12];
in_impact = (int)argv[15];

logf(MILESTONE, "%s, started", method);

if (ZDEBUG > 0) logf(TRACE, "%s, chg %s, zEnv %d, chgtype %d, risk %d, impact %d", method, in_persid, in_zEnvironment, in_chgtype, in_risk, in_impact);

evt_set_cab_approval = "zChgSetCABNo";

// type is Emergency or (Normal AND (Env is Prod or Env is Prod/Train or Release))
if ( in_chgtype == 300 || (in_chgtype == 200 && (in_zEnvironment == 400001 || in_zEnvironment == 400002 || in_zEnvironment == 400008))
{
   if (in_risk < 4 || in_impact > 1) // Either risk or impact is NOT low.
    {
      evt_set_cab_approval = "zChgSetCABYes";
   }
}

string theChgID; // in_persid will be 'chg:nnnnn'
theChgID = substr(in_persid,4); // Just the digits
//
// Attach event to update the CAB approval flag.
//
misc::site_att_chg_evt_byid( evt_set_cab_approval, (int)theChgID, 5, "zChgC" );

logf(MILESTONE, "%s, ended", method);
}

Finally the attach event function, in 'zchgAttEvt.spl':


#define ZDEBUG 99

void misc::site_att_chg_evt_byid( string event_sym, int chg_id, int delay_sec, string event_group_id )
{
string method;
method = "misc::site_att_chg_evt_byid";

string myTZ; myTZ = "GMT+0800 (2)"; // Swap for your own TZ

if ( ZDEBUG > 0 ) logf(MILESTONE, "%s: Started ", method);
//check symbol of event
int evt_id;
evt_id = (int)expand(format("&{'%s' = evt.sym->id}", event_sym));

if ( is_null(evt_id) || (evt_id == 0) )
{
   logf(ERROR, "%s: Symbol of event '%s' is not recognized.", method, event_sym);
   return;
}

if ( ZDEBUG > 0 ) logf(SIGNIFICANT, "%s: Event sym '%s' verified, attaching with delay %d...", method, event_sym, delay_sec);

send_wait(0, top_object(), "call_attr", "evt", "new_attached_event", (object)NULL,
          format("chg:%d",chg_id), event_sym, (duration) delay_sec,
          (date) NULL, event_group_id , 0, 0, myTZ);

if (msg_error())
{
   logf(ERROR, "%s: error returned by new_attached_event: %s", method, (string)msg[0]);
   return;
}

if ( ZDEBUG > 0 )
{
   logf(TRACE, "%s: Attach event called ", method);
   object attevt;
   attevt = msg[0];
   send_wait(0, attevt, "call_attr", "id", "get_val");
   int attevt_id;
   attevt_id = msg[0];
   logf(MILESTONE, "%s: Finished. Attached event id = %d", method, attevt_id);
}
}

Hope that helps :-).

Regards,

James

09-29-2016 05:53 PM

Hi James,

 

Can you share an example trigger you use to call this script?  I'm trying to use your example to attach an event to a change order and seeing the other side of this would really help!  

05-16-2016 02:03 PM

That issue was related to our environment. I checked with CA Support and for some reasons it had OBJ_ID as 30. even though ATT_EVT.xml file has size 60. well, code is working and i am able to attach an event to CI on given date and time.

05-11-2016 05:12 PM

i am trying to attach an event to a CI.

 

this is the statement i am using

send_wait(0, top_object(), "call_attr", "evt", "new_attached_event", NULL, persid, "Notify CI Stakeholders", (duration)dur, (date)warrant_end, "SLA", 0, 0, "");

 

stdlog says:

 

SQL Statement Failed. ORA: 12899  Message: ORA-12899: value too large for column "MDBADMIN"."ATT_EVT"."OBJ_ID" (actual: 35, maximum: 30)

05/11 16:04:46.80 DOTSTOLLCASDM1 sqlagt:upinde        3124 ERROR        orclclass.c           1303 Clause (INSERT INTO att_evt ( cancel_time, event_tmpl, fire_time, first_fire_time, group_name, last_mod_dt, num_fire, obj_id, owning_ast, persid, start_time, status_flag, timezone, user_smag, wait_time, id ) VALUES ( :val1 , :val2 , :val3 , :val4 , :val5 , :val6 , :val7 , :val8 , :val9 , :val10 , :val11 , :val12 , :val13 , :val14 , :val15 , :val16 )) Input (<cancel_time:time>(NULL)|<event_tmpl:string>evt:2193845|<fire_time:time>05/11/2016 16:05:00|<first_fire_time:time>05/11/2016 16:05:00|<group_name:string>SLA|<last_mod_dt:time>05/11/2016 16:04:46|<num_fire:int>0|<obj_id:string>nr:EEE2C489119E2A49A5F49CF06421E168|<owning_ast:int>0|<persid:string>atev:19822503|<start_time:time>05/11/2016 16:05:00|<status_flag:int>2|<timezone:string>(NULL)|<user_smag:string>(NULL)|<wait_time:duration>0|<id:int>19822503)

05/11 16:04:46.82 DOTSTOLLCASDM1 spelsrvr             3744 ERROR        bopevt.spl             310 error in checkin: AHD04199:An unexpected error occurred. Contact your administrator. ORA-12899: value too large for column "MDBADMIN"."ATT_EVT"."OBJ_ID" (actual: 35, maximum: 30)

 

 

ok now WSP shows this: size 60

 

 

 

but DB desc att_evt says:

 

 

am i lost? doing something wrong?

11-18-2015 07:11 AM

noticed one sad thing in this method,

haven't found a way to get handles of newly created atevs.

message arrays after new_attached_event or checkin haven't any usefull info.

10-29-2015 10:42 AM

answering to my question - Yes, user defined delay can setted even for fixed events via this methods,

while "new_dob" method will throw error that fixed delay cannot be changed.

10-29-2015 08:01 AM

open any event, there should be checkbox: Allow time resetting,

No - means that delay is fixed and cannot be reseted.

10-29-2015 07:54 AM

Yes we are planing to switch to them, because we already had some additional work with generic ones when client switched to tenants it also makes code more understandable and clean. I did not have any expirience with fixed events could you give some examples of that.

10-29-2015 03:34 AM

I have for years used variants of the function below to attach events to objects from triggers.  This is the wf version - with minor mods it can be generalised to attach an event to a cr, chg or wf.  For trigger purposes I usually prefer to attach an event rather than update an object directly in spel - for one thing, it saves me having to think about locking.  I usually set the 'event group' string to something other than SLA, because I want these events not to behave as Service Type events.

 

#define ZDEBUG 99

void misc::site_att_wf_evt_byid( string event_sym, int wf_id, int delay_sec, string event_group_id )
{

//

// R12+ version

// Example of use: misc::site_att_wf_evt_byid( "zwfNotifyAssignee", wf_id, 30, "zWFA");

//
   string method;
   method = "misc::site_att_wf_evt_byid";

   if ( ZDEBUG > 0 ) logf(SIGNIFICANT, "%s: Started ", method);
   //check symbol of event
   int evt_id;
   evt_id = (int)expand(format("&{'%s' = evt.sym->id}", event_sym));

   if ( is_null(evt_id) || (evt_id == 0) )
   {
      logf(ERROR, "%s: Symbol of event  '%s' is not recognized.", method, event_sym);
      return;
   }

   if ( ZDEBUG > 0 ) logf(SIGNIFICANT, "%s: Event sym '%s' verified, attaching with delay %d...", method, event_sym, delay_sec);

   send_wait(0, top_object(), "call_attr", "evt", "new_attached_event", (object)NULL,
             format("wf:%d",wf_id), event_sym, (duration) delay_sec,
             (date) NULL, event_group_id , 0, 0, "GMT+0800 (2)");
   //
   // Change the text "GMT+0800 (2)" above to the Service Desk timezone identifier appropriate to your location!
   //

   if (msg_error())
   {
      logf(ERROR, "%s: error returned by new_attached_event: %s", method, (string)msg[0]);
      return;
   }

   if ( ZDEBUG > 0 )
   {
      logf(SIGNIFICANT, "%s: Attach event called ", method);
      object attevt;
      attevt = msg[0];
      send_wait(0, attevt, "call_attr", "id", "get_val");
      int attevt_id;
      attevt_id = msg[0];
      logf(SIGNIFICANT, "%s: Finished. Attached event id = %d", method, attevt_id);
   }
}

10-29-2015 02:59 AM

Thanks for sharing, Gutis!

This doc is really gives reason to think.

 

Most of my methods uses events if they fails in direct action,

firstly I used new_dob and then switched to insert_object from your SPEL API methods

 

The only problem I faced using generic methods is that some events have constant delay and cannot be reseted, this gives an error while I trying to define my own delay,

sure this can be checked in 3 extra string of code but better to prevent from events form.

 

If you have some time may check what happen if you try to define delay time for fixed events?

PS: what is your personal opinion about generic methods vs described before methods, will you switch to them? :)

Related Entries and Links

No Related Resource entered.