Developing Diagnostic Plug-Ins

This chapter provides an overview of diagnostic plug-in development and discusses:

Click to jump to parent topicUnderstanding Diagnostic Plug-In Development

A diagnostic plug-in is an application package developed while adhering to the diagnostic plug-in standard. Developers use the application packages editor in Application Designer to create the application packages that are treated as diagnostic plug-ins by the framework.

PeopleTools delivers Diagnostics Framework base classes in an application package called PT_DIAGNOSTICS. To create your own diagnostic plug-in, a new application package needs to be created and extended from the application package PT_DIAGNOSTICS. The new application package can have multiple numbers of application classes which should be extended from the base classes in PTDiagnostics, delivered in the PT_DIAGNOSTICS application package.

The sub classes can call the base class methods to collect the diagnostic information and return the same information to the Diagnostics Framework. Each of the application classes within the diagnostic plug-in focuses one diagnostic area and can return different information, depending on the state of the application and the nature of the 'question'.

The application class also can contain an optional public method, called GetDynamicPrompt, to prompt users for additional information.

The following types of data can be retrieved and displayed in the Diagnostics Framework:

Note. You can also define your own private methods within the application class, which you can call only within the class.

You define diagnostic plug-ins using application classes, but you don't use them in the same way that other PeopleCode application classes are used. Diagnostic plug-in classes:

Note. Developing custom diagnostic plug-ins requires a working knowledge of PeopleCode and application classes.

See Also

Application Classes

Click to jump to parent topicDeveloping Diagnostic Plug-Ins

This section discusses how to:

Note. Except for registering the Diagnostic Plug-in, which is performed using a PIA page, you complete all of these development steps using Application Designer.

Click to jump to top of pageClick to jump to parent topicCreating the Diagnostic Application Package

To create a diagnostic application package: Open the application package in Application Designer, Save the package.

  1. In Application Designer select File, New, Application Package.

  2. Save and name the package.

See Application Classes.

Click to jump to top of pageClick to jump to parent topicCreating the Diagnostic Application Classes

In the application package you've created, create a new application class, and save the class.

Note. You can pass only one data type in each diagnostic plug-in application class. To return multiple data types, define multiple application classes. Results that are passed to the framework are retained in memory.

See Application Classes.

Click to jump to top of pageClick to jump to parent topicImplementing the Diagnostic PeopleCode

To implement the diagnostic PeopleCode:

  1. Open the PeopleCode editor (View, PeopleCode).

  2. Import the PTDiagnostic package, by entering:

    import PT_DIAGNOSTICS:*;

  3. This imports all the classes in the PT_DIAGNOSTICS application package.

  4. Define the class, using the same procedure as your would for any PeopleCode program. For example,

     

    class <class name> extends PTDiagnostic:PTDiagnostic

    This makes the class a diagnostic application class.

    The class name mentioned in the PeopleCode should be the same as the class name which is under the application package.

    All the classes defined in the diagnostic plug-in application package should be extended from the class PTDiagnostic:PTDiagnostic.

  5. Define the following mandatory methods:

    Method

    Description

    Method <class name>

    This is the constructor of the class.

    Inside the method it is mandatory to have%Super = create PT_DIAGNOSTICS:PTDiagnostics().

    More description of %Super resides in the PTDiagnostics application class.

    If you want to display the rowset in the browser, then you have to set the hasRowset property to True, otherwise make it False. For example,

    &status = %Super.SetProperty (%This, "hasRowset", "Boolean", False);

    If you want to call additional information from the user during the execution and use it as the search criteria, then set the Where property to true, otherwise make it False. For example,

    &status = %Super.SetProperty (%This, "Where", "Boolean", True);

    Method GetDiagnosticInfo

    This is the method that gets called when you launch the diagnostic plug-in.

    To display any output in the browser you have to call %Super.Insertdata(Data type, <String to name the display>, <variable name>).

    Method IsPlugIn

    The purpose of this method is to identify the application package as a diagnostic plug-in. If this method is not present, then the system does not recognize it as a diagnostic plug-in during the registration process.

    This method should appear at the end of the diagnostic application class, and it should be an empty method.

    The definition of this should be :

    Method IsPlugIn end-method;

Click to jump to top of pageClick to jump to parent topicRegistering the Diagnostic Plug-In

Before a diagnostics application package can be used, you have to register it using the Register Diagnostics page. Once the registration is complete, the application package becomes a diagnostic plug-in.

To register a diagnostic plug-in:

  1. Access the Register Diagnostics page by selecting Application Diagnostics, Register Diagnostics.

  2. Add a row, if needed.

  3. In the Plug-In Name edit box, enter the name of the application package, or use the lookup prompt to select it.

    Note. When using the lookup prompt, the system displays all application packages not only diagnostic plug-in packages. When developing custom diagnostic plug-ins, using a naming convention can be helpful to refine the search.

  4. Click Save.

Note. If you have not defined the IsPlugIn method or if it is not at the end of the class, an error message appears. The system only registers application packages containing all the required elements of a diagnostic plug-in.

Click to jump to top of pageClick to jump to parent topicSharing Diagnostic Definitions

Once the registration is complete, the application package can be selected as a Diagnostic Plug-In in Application Designer. Inserting diagnostic plug-ins into projects, enables them to be shared, copied to or compared between databases, and exported to and imported from files. Sharing diagnostic plug-ins would be necessary for plug-ins that need to be sent to Oracle support staff for their review, for example, or to other developers at your site.

The project should contain the:

To insert a plug-in into a project:

  1. In Application Designer, select Insert, Definitions into Project.

  2. Select Diagnostic Plug-Ins as the definition type.

  3. Select the plug-in and click Insert.

  4. After inserting the plug-in, make sure to include the underlying application packages and application package PeopleCode in the project as well.

Once the diagnostic plug-in definitions have been inserted into a project, you can share a diagnostic plug-in. Check the Upgrade tab to see these definition types: Application Packages, Diagnostic Plug-Ins, and PeopleCode. You cannot see these with the Development tab selected.

To share a diagnostic plug-in:

  1. Open the project containing the diagnostic definitions in Application Designer.

  2. Select Tools, Copy Project, to File.

  3. Share the generated XML file with the interested parties.

See Also

Working With Projects

Click to jump to parent topicWorking With The Delivered PT_DIAGNOSTIC Application Package

PeopleTools delivers the PT_DIAGNOSTIC application package as part of the Diagnostics Framework. This package is the base package and its classes are base classes for the diagnostic plug-in.

To define a new plug-in, create a new application package, containing one or more application classes that imports the PT_DIAGNOSTIC application package.

When working with the PT_DIAGNOSTIC application package, make sure you understand:

These elements are described in the following sections.

Click to jump to parent topicPTDiagnostics Application Class

The PTDiagnostics application class is part of the PT_DIAGNOSTICS application package. It establishes the basic framework for developing the diagnostic plug-ins. The PTDiagnostics application class contains methods and properties that you can extend to develop your diagnostic plug-ins. The PTDiagnostics Class is not a built-in class, like Rowset, Field, Record, and so on. It's an application class.

Before you can use this class in your PeopleCode program, you must import it into your program, using an import statement. The application package PT_DIAGNOSTICS contains the PTDiagnostics class. The import statement should be as follows:

import PT_DIAGNOSTICS:*;

Using the asterisk (*) after the package name makes all the application classes directly contained in the named package available. Application classes contained in subpackages of the named package are not made available.

In the constructor of the application class which extends the PTDiagnostics class you need to instantiate the PTDiagnostics class. The extended application classes collect the information whenever required and pass it to the super class, which is the PTDiagnostics class. You instantiate this class as:

%Super = create PT_DIAGNOSTICS:PTDiagnostics()

Click to jump to parent topicPTDiagnostics Class Methods

This section discusses the diagnostic methods for the PTDiagnostics PeopleCode class. The methods are listed in alphabetical order.

Click to jump to top of pageClick to jump to parent topicGetDiagnosticInfo

Description

Use this required public method to define the code that retrieves diagnostic information and returns it to Diagnostics Framework for presentation to the user. This method is invoked by Diagnostics Framework to initiate information collection, then output the results.

The GetDiagnosticInfo method uses the base class InsertData method to pass the results of the diagnostic to Diagnostics Framework for presentation to the users, for example:

&status = %Super.InsertData("Number", "Number of Records: ", &rs1.RowCount);

InsertData can pass output data using the following data types:

Before you can pass rowset data as output, you must first use the base class SetProperty method to set the base class hasRowset property to True.

Considerations for GetDiagnosticInfo include:

Note. You can also set the Purpose property in the constructor or in the GetDynamicPrompt method.

Example

Following is an example of GetDiagnosticInfo that passes rowset data as output:

method GetDiagnosticInfo Local boolean &status; Local number &rc1; Local Rowset &rs1; Local string &sError; &rs1 = CreateRowset(Record.PSLANGUAGES); &rc1 = &rs1.Fill(); &status = %Super.SetProperty(%This, "hasRowset", "Boolean", True); &status = %Super.InsertData("Rowset", "LANGUAGES description, not used in output", &rs1); end-method;

Click to jump to top of pageClick to jump to parent topicGetDynamicPrompt

Description

If you want a diagnostic application class to prompt users for additional information that you can use as dynamic criteria for the diagnostic, you must define a public method called GetDynamicPrompt within the class.

Before you can use the GetDynamicPrompt method, you must first use the base class SetProperty method within the constructor to set the base class Where property to True , for example:

&status = %Super.SetProperty(%This, "Where", "Boolean", True);

Note. If the Where property is False, Diagnostics Framework ignores the GetDynamicPrompt method.

Within the GetDynamicPrompt method, use the base class InsertQuestion method to define the questions used to prompt the users.

Example

method GetDynamicPrompt Local boolean &status; &status = %Super.InsertQuestion("Recs", "Enter Records to search for, beginning with: ", "String", True); end-method;

Click to jump to top of pageClick to jump to parent topicGetUserInputByKey

Syntax

GetUserInputByKey(sKeyID, &data)

Description

The GetUserInputByKey method retrieves the user response to a question, which can then be used as an input parameter in the diagnostic. You invoke this method within the GetDiagnosticInfo method.

Parameters

sKeyID

Specify as a string the key that identifies the question for which you're retrieving the user response.

&data

Provide a variable to contain the retrieved user response.

Returns

A Boolean value: True if the user response was retrieved successfully, False otherwise.

Click to jump to top of pageClick to jump to parent topicInsertData

Syntax

InsertData(propFormat, propDescr, &data)

Description

The InsertData method passes data to Diagnostics Framework to be presented as the output of the diagnostic. This enables you to pass any information you want without having to hardcode base class methods in the plug-in. You invoke this method within the GetDiagnosticInfo method.

Parameters

propFormat

Specify as a string the data type of the data to be presented. Select from the following:

  • String

  • Number

  • Date

  • Boolean

  • Rowset

propDescr

Specify a string of text to describe or introduce the output data.

&data

Provide the output data value, in a variable of the data type specified by the propFormat parameter.

Returns

A Boolean value: True if the data has been inserted into Diagnostics Framework, False if the data can't be inserted into the framework, or if the data type specified by propFormat doesn't exist in the current framework.

Click to jump to top of pageClick to jump to parent topicInsertQuestion

Syntax

InsertQuestion(sKeyID, sQuestion, sType, GblBool)

Description

The InsertQuestion method passes a question to Diagnostics Framework, which then presents it to the user to obtain an input parameter. You invoke this method within the GetDynamicPrompt method.

Parameters

sKeyID

Specify as a string a key to identify the question. This value must be unique across all plug-ins that are made available to a user.

sQuestion

Specify as a string the question you want the user to answer.

sType

Specify as a string the data type of the response required from the user. Select from the following:

  • String

  • Number

  • Date

  • Boolean

GblBool

Specify a Boolean value indicating the scope of the question:

  • True: The question applies globally to the plug-in.

  • False: The question applies only to the current class.

Global questions are asked once per plug-in on the Additional Information prompt page. For example, a plug-in could be defined to gather employee information. The plug-in might contain many application classes that gather specific information (for example, one application class for getting employee paycheck information, and one application class for getting employee addresses). Class level questions are asked only for the current application class. For example, for the paycheck information, you might want to prompt for specific pay periods and for the address information, you might want to prompt for an effective date.

Returns

A Boolean value: True if the method is successful, False otherwise.

Click to jump to top of pageClick to jump to parent topicIsPlugIn

Description

This required public method is invoked by Diagnostics Framework when you register the plug-in. It verifies that the class is part of a diagnostic plug-in. If it is not present, the system will not register the plug-in.

IsPlugIn should be:

Example

method IsPlugIn end-method

Click to jump to top of pageClick to jump to parent topicSetProperty

Syntax

SetProperty(&obj, propName, propFormat, &propValue)

Description

The SetProperty method sets a property of an instantiated PTDiagnostics object to the value that you specify.

Parameters

&obj

Specify the PTDiagnostics object for which you want to set a property. Typically, you'll specify %This.

propName

Specify as a string the name of the property that you want to set. The values are:

  • hasRowset

  • Purpose

  • Where

propFormat

Specify as a string the data type of the property that you want to set. For hasRowset and Where, specify Boolean. For Purpose, specify string.

&propValue

Provide the property value, in a variable that has the data type specified by the propFormat parameter.

Returns

A Boolean value: True if the property specified by propName exists and can be set in the base class, False if the property can't be set (for example, if the current plug-in is used in a previous release of Diagnostics Framework where that property isn't defined).

Click to jump to parent topicPTDiagnostics Class Properties

This section lists the properties for the PTDiagnostics PeopleCode class. The properties are listed in alphabetical order.

Click to jump to top of pageClick to jump to parent topichasRowset

Description

Use the hasRowset property to indicate whether the InsertData method passes output data to Diagnostics Framework as a rowset. This property only needs to be defined for classes that use rowsets. This property takes a Boolean value:

Note. You must use the SetProperty method to set the value of this property.

See Also

InsertData

SetProperty

Click to jump to top of pageClick to jump to parent topicPurpose

Description

Use the Purpose property to specify as a string the text that introduces and describes the purpose of the diagnostic that this application class performs. This text will be displayed as part of the diagnostic output.

The default value of this property is Unknown.

Note. You must use the SetProperty method to set the value of this property.

See Also

SetProperty

Click to jump to top of pageClick to jump to parent topicWhere

Description

Use the Where property to indicate whether this application class should dynamically prompt the user for relevant parameters. This property only needs to be defined for classes that prompt the user.

This property takes a Boolean value:

Note. You must use the SetProperty method to set the value of this property, and you must set it from within the constructor method. If you set this property to True, you must define the GetDynamicPrompt method in your application class to prompt the user.

See Also

SetProperty

GetDynamicPrompt

Click to jump to parent topicDiagnostic Plug-In Examples

The following are examples of typical actions found in diagnostic plug-ins. Examples include:

Click to jump to top of pageClick to jump to parent topicExample: Rowset-Based Output

The following example demonstrates how to retrieve record output and display it. In this case, the plug-in retrieves the list of languages from the database.

import PT_DIAGNOSTICS:*; class GetLanguages extends PTDiagnostics /* Constructor */ method GetLanguages(); /* Public Method */ method GetDiagnosticInfo(); method IsPlugIn(); private end-class; method GetLanguages; Local boolean &status; %Super = create PTDiagnostics(); &status = %Super.SetProperty(%This, "hasRowset", "Boolean", True); &status = %Super.SetProperty(%This, "Purpose", "String", "This is a diagnostic to determine all of the languages installed in your PeopleSoft Database."); end-method; method GetDiagnosticInfo Local boolean &stat; Local number &rc1; Local Rowset &rs1; Local string &sError; &rs1 = CreateRowset(Record.PSLANGUAGES); &rc1 = &rs1.Fill(); &stat = %Super.InsertData("Rowset", "LANGUAGES description, not used in output", &rs1); end-method; method IsPlugIn end-method;

Click to jump to top of pageClick to jump to parent topicExample: String-Based Output

This example demonstrates how to retrieve string-based output and display it. In this case, the plug-in retrieves the license code.

import PT_DIAGNOSTICS:*; class GetLicenseCode extends PTDiagnostics /* Constructor */ method GetLicenseCode(); /* Public Method */ method GetDiagnosticInfo(); method IsPlugIn(); private end-class; method GetLicenseCode; Local boolean &status; Local string &sError; %Super = create PTDiagnostics(); &status = %Super.SetProperty(%This, "Purpose", "String", "This is a diagnostic to determine your license code"); end-method; method GetDiagnosticInfo Local string &sLicenseCode, &sLicenseGroup; Local boolean &status; Local string &sError; SQLExec("SELECT LICENSE_CODE, LICENSE_GROUP FROM PSOPTIONS", &sLicenseCode, &sLicenseGroup); &status = %Super.InsertData("String", "Your License Code is: ", Upper(&sLicenseCode)); end-method; method IsPlugIn end-method;

Click to jump to top of pageClick to jump to parent topicExample: Number-Based Output

This example demonstrates how to retrieve a Number type output and display it. In this case, we retrieve the number of rows from the PSRECDEFN based on different conditions.

import PT_DIAGNOSTICS:*; class GetPSRECDEFNCount extends PTDiagnostics /* Constructor */ method GetPSRECDEFNCount(); /* Public Method */ method GetDiagnosticInfo(); method IsPlugIn(); private end-class; method GetPSRECDEFNCount; Local boolean &status; Local string &sError; %Super = create PTDiagnostics(); &status = %Super.SetProperty(%This, "Purpose", "String", "This is a diagnostic to count the number of records, views, derived work records, and sub-records in your PeopleSoft Database."); end-method; method GetDiagnosticInfo Local boolean &status; Local number &rc1; Local Rowset &rs1; Local string &sError; &rs1 = CreateRowset(Record.PSRECDEFN); &rc1 = &rs1.Fill("where RECTYPE = 0"); &status = %Super.InsertData("Number", "Number of Records: ", &rs1.RowCount); &rs1 = CreateRowset(Record.PSRECDEFN); &rc1 = &rs1.Fill("where RECTYPE = 1"); &status = %Super.InsertData("Number", "Number of Views: ", &rs1.RowCount); &rs1 = CreateRowset(Record.PSRECDEFN); &rc1 = &rs1.Fill("where RECTYPE = 2"); &status = %Super.InsertData("Number", "Number of Derived/Work Records: ", &rs1.RowCount); &rs1 = CreateRowset(Record.PSRECDEFN); &rc1 = &rs1.Fill("where RECTYPE = 3"); &status = %Super.InsertData("Number", "Number of sub-records: ", &rs1.RowCount); end-method; method IsPlugIn end-method;

Click to jump to top of pageClick to jump to parent topicExample: Prompting for Global Information Input

This example demonstrates how to use global prompting. This example includes the use of these constructs:

In this example, the plug-in retrieves the number of rows from the PSRECDEFN based on different records. The search record is usually retrieved from the user during runtime.

import PT_DIAGNOSTICS:*; class GetRecFieldsBeginningWith extends PTDiagnostics /* Constructor */ method GetRecFieldsBeginningWith(); /* Public Method */ method GetDiagnosticInfo(); method GetDynamicPrompt(); method IsPlugIn(); private end-class; method GetRecFieldsBeginningWith; Local boolean &status; %Super = create PTDiagnostics(); &status = %Super.SetProperty(%This, "Where", "Boolean", True); &status = %Super.SetProperty(%This, "Purpose", "String", "This is a diagnostic to print out a listing of fields from records in your PeopleSoft database that matches search criteria. This diagnostic tests globalType and classType prompting. The global prompt is retrieved from inputs defined by a different class in this plug-in."); end-method; method GetDynamicPrompt Local boolean &status; Local string &sError; /* define prompt for this class */ &status = %Super.InsertQuestion("Flds", "Enter FieldNames to retrieve, beginning with:", "String", False); end-method; method GetDiagnosticInfo Local boolean &status; Local string &sValRecs, &sValFlds, &sError; Local number &iCount = 0; Local Record &REC; Local boolean &bReturn; Local SQL &SQL1; &REC = CreateRecord(Record.PSRECFIELD); &SQL1 = CreateSQL("%SelectAll(:1) where RECNAME LIKE :2 and FIELDNAME LIKE :3"); /* get global prompt */ &status = %Super.GetUserInputByKey("Recs", &sValRecs); /* get class prompt */ &status = %Super.GetUserInputByKey("Flds", &sValFlds); &SQL1.Execute(&REC, Upper(&sValRecs | "%"), Upper(&sValFlds | "%")); While &SQL1.Fetch(&REC) &iCount = &iCount + 1; &status = %Super.InsertData("String", "Record: " | &REC.RECNAME.Value | " has the following field that matches your criteria: ", &REC.FIELDNAME.Value); End-While; end-method; method IsPlugIn end-method;

Click to jump to top of pageClick to jump to parent topicExample: Prompting for Global and Class-Level Information Input

The following example demonstrates the use of global and class-level prompts.

import PT_DIAGNOSTICS:*; class GetRecFieldsBeginningWith extends PT_DIAGNOSTICS:PTDiagnostics /* Constructor */ method GetRecFieldsBeginningWith(); /* Public Method */ method GetDiagnosticInfo(); method GetDynamicPrompt(); method IsPlugIn(); private end-class; method GetRecFieldsBeginningWith; Local boolean &status; %Super = create PT_DIAGNOSTICS:PTDiagnostics(); &status = %Super.SetProperty(%This, "Where", "Boolean", True); &status = %Super.SetProperty(%This, "Purpose", "String", "This is a diagnostic to print out a listing of fields from records in your PeopleSoft database that matches search criteria. This diagnostic tests globalType and classType prompting. The global prompt is retrieved from inputs defined by a different class in this plug-in."); end-method; method GetDynamicPrompt Local boolean &status; Local string &sError; /* define the global prompt*/ &status = %Super.InsertQuestion("Recs", "Enter RecordNames to retrieve, beginning with:", "String", True); /* define prompt for this class */ &status = %Super.InsertQuestion("Flds", "Enter FieldNames to retrieve, beginning with:", "String", False); end-method; method GetDiagnosticInfo Local boolean &status; Local string &sValRecs, &sValFlds, &sError; Local number &iCount = 0; Local Record &REC; Local boolean &bReturn; Local SQL &SQL1; &REC = CreateRecord(Record.PSRECFIELD); &SQL1 = CreateSQL("%SelectAll(:1) where RECNAME LIKE :2 and FIELDNAME LIKE :3"); /* get global prompt */ &status = %Super.GetUserInputByKey("Recs", &sValRecs); /* get class prompt */ &status = %Super.GetUserInputByKey("Flds", &sValFlds); &SQL1.Execute(&REC, Upper(&sValRecs | "%"), Upper(&sValFlds | "%")); While &SQL1.Fetch(&REC) &iCount = &iCount + 1; &status = %Super.InsertData("String", "Record: " | &REC.RECNAME.Value | " has the following field that matches your criteria: ", &REC.FIELDNAME.Value); End-While; end-method; method IsPlugIn end-method;

If you only need to define the class level prompt, use only the second InsertQuestion() method in the GetDynamicPrompt() method and one GetUserInputByKey().

If the message is not required during the dynamic input, then pass an empty string in the second parameter of the InsertQuestion() method.

Click to jump to top of pageClick to jump to parent topicExample: Joining Two Records

This example demonstrates the join between two records. This join can be done by creating a view also.

In this example, the plug-in retrieves the objects from the PSLOCK and PSVERSION tables where versions of the objects don’t match.

import PT_DIAGNOSTICS:*; class MatchVersions extends PT_DIAGNOSTICS:PTDiagnostics /* Constructor */ method MatchVersions(); /* Public Method */ method GetDiagnosticInfo(); method IsPlugIn(); private end-class; method MatchVersions; Local boolean &status = False; %Super = create PT_DIAGNOSTICS:PTDiagnostics(); &status = %Super.SetProperty(%This, "Purpose", "String", "This is to retrieve the objects whose versions doesnot match in PSLOCK and PSVERSIONS."); end-method; method GetDiagnosticInfo Local boolean &status; Local Rowset &rs1; Local Rowset &rs2; Local integer &i, &j; Local Row &ro1; &rs1 = CreateRowset(Record.PSVERSION); &rs1.Fill(); &rs2 = CreateRowset(Record.PSLOCK); &rs2.Fill(); For &i = 1 To &rs1.RowCount For &j = 1 To &rs2.RowCount If (&rs1.GetRow(&i).GetRecord(Record.PSVERSION).OBJECTTYPENAME.Value = &rs2.GetRow(&j).GetRecord(Record.PSLOCK).OBJECTTYPENAME.Value) And (&rs1.GetRow(&i).GetRecord(Record.PSVERSION).VERSION.Value <> &rs2.GetRow(&j).GetRecord(Record.PSLOCK).VERSION.Value) Then &status = %Super.InsertData("String", "OBJECTTYPENAME: ", &rs1.GetRow (&i).GetRecord(Record.PSVERSION).OBJECTTYPENAME.Value | " PSVERSION.VERSION: " | &rs1.GetRow(&i).GetRecord(Record.PSVERSION).VERSION.Value | " PSLOCK.VERSION: " | &rs2.GetRow(&j).GetRecord(Record.PSLOCK).VERSION.Value); End-If; End-For; End-For; end-method; method IsPlugIn end-method;

Click to jump to top of pageClick to jump to parent topicExample: Handling Constructor Failure

The following example demonstrates error handling when the constructor fails.

import PT_DIAGNOSTICS:*; class TestFailedConstructor extends PTDiagnostics /* Constructor */ method TestFailedConstructor(); /* Public Method */ method GetDiagnosticInfo(); method IsPlugIn(); private instance boolean &constructorFailed; end-class; method TestFailedConstructor Local boolean &status; Local string &sError; %Super = create PTDiagnostics(); &status = %Super.SetProperty(%This, "Purpose", "String", "This is a diagnostic to show how developers can trap a failure in the constructor and print out results to the web page."); /* introduce unknown propName of Where1 rather than Where */ &status = %Super.SetProperty(%This, "Where1", "Boolean", True); If Not &status Then %This.constructorFailed = True; Else %This.constructorFailed = False; End-If; end-method; method GetDiagnosticInfo Local string &sError, &sLicenseCode, &sLicenseGroup; Local boolean &status; If %This.constructorFailed Then &status = %Super.InsertData("String", "Status Failed!", "This message will be printed out in the HTML page if something fails in the constructor. This is expected behaviour."); Else SQLExec("SELECT LICENSE_CODE, LICENSE_GROUP FROM PSOPTIONS", &sLicenseCode, &sLicenseGroup); &status = %Super.InsertData("String", "Your License Code is: ", Upper(&sLicenseCode)); End-If; end-method; method IsPlugIn end-method;

Click to jump to top of pageClick to jump to parent topicExample: Handling InsertData Method Failure

The following example demonstrates error handling when InsertData fails.

import PT_DIAGNOSTICS:*; class TestFailedGetDiagnosticInfo extends PTDiagnostics /* Constructor */ method TestFailedGetDiagnosticInfo(); /* Public Method */ method GetDiagnosticInfo(); method IsPlugIn(); private end-class; method TestFailedGetDiagnosticInfo; Local boolean &status; %Super = create PTDiagnostics(); &status = %Super.SetProperty(%This, "Purpose", "String", "This is a diagnostic to show how developers can trap a failure in GetDiagnosticInfo method and print out results to the web page."); end-method; method GetDiagnosticInfo Local string &sError, &sLicenseCode, &sLicenseGroup; Local boolean &status; SQLExec("SELECT LICENSE_CODE, LICENSE_GROUP FROM PSOPTIONS", &sLicenseCode, &sLicenseGroup); /* introduce unknown propFormat of String1 */ &status = %Super.InsertData("String1", "Your License Code is: ", Upper(&sLicenseCode)); If Not &status Then &status = %Super.InsertData("String", "Status Failed!", "This message will be printed out in the HTML page if something fails here. This is expected behaviour."); End-If; end-method; method IsPlugIn end-method;

Click to jump to top of pageClick to jump to parent topicExample: Handling Dynamic Prompting Failure

The following example demonstrates error handling when retrieving user prompts.

import PT_DIAGNOSTICS:*; class TestFailedGetUserInputByKey extends PTDiagnostics /* Constructor */ method TestFailedGetUserInputByKey(); /* Public Method */ method GetDiagnosticInfo(); method IsPlugIn(); private end-class; method TestFailedGetUserInputByKey; Local boolean &status = False; %Super = create PTDiagnostics(); &status = %Super.SetProperty(%This, "Purpose", "String", "This is a diagnostic to test getting a 'False' from GetUserInputByKey."); end-method; method GetDiagnosticInfo Local boolean &status = False; Local string &sVal, &sError; Local number &iCount = 0; Local Record &REC; Local SQL &SQL1; &REC = CreateRecord(Record.PSRECDEFN); &SQL1 = CreateSQL("%SelectAll(:1) where RECNAME LIKE :2"); /* sKeyID "Recs" has already be defined elsewhere in the package see if we can get RecJY. should get a False */ &status = %Super.GetUserInputByKey("RecsJY", &sVal); If &status Then &SQL1.Execute(&REC, Upper(&sVal | "%")); While &SQL1.Fetch(&REC) &iCount = &iCount + 1; &status = %Super.InsertData("String", "Record #" | &iCount, &REC.RECNAME.Value | " (" | &REC.RECDESCR.Value | ")"); End-While; Else &status = %Super.InsertData("String", "Status Failed!", "Failed status encountered in retrieving RecsJY key. This is expected behaviour."); End-If end-method; method IsPlugIn end-method;