Download as pdf or txt
Download as pdf or txt
You are on page 1of 84

Integration

Technologies
PeopleCode
People Tools - 3 Day Class
[A comprehensive 2 day tour on the capabilities of the SQR language and
its usage in PeopleSoft]

People Tools - 3 Day Class


Table of Contents
1.1 Agenda...................................................................................................3
1.2 Technology Overview................................................................................3
1.3 Introduction to Component Interface..........................................................8
1.3 Creation and Testing of Component Interface............................................ 17
Activity 1 – Create a Component Interface on Vendor component...................22
Activity 2 – Grant Security......................................................................... 25
Activity 3 – Test Component Interface.........................................................25
1.4 Implementing Component Interface..........................................................25
Activity 4 – Activate a Component Interface.................................................33
1.5 Component Interface Collections..............................................................33
Activity 5 – Updating row using a Component Interface................................. 44
Activity 6 – Adding row using a Component Interface....................................44
1.6 Component Interface API........................................................................ 44
2.0 Excel to Component Interface Utility.........................................................50
3.0 Integration Broker..................................................................................53
4.0 File Objects & Components Interface........................................................ 62
Activity 7 – Importing a Fixed Format Flat file ..............................................78
Activity 8 – Writing data to flat file..............................................................84
Activity 9 – Data import using File Layout, CI and AE.................................... 84

Page 2 of 84
1.1 Agenda
We will cover the following material in next three days

Day 1 will introduce the concept of Component interface. We will talk about
• Technology Overview
• Introduction to Component Interface (Component Interface)
• Creation and testing of Component Interface
• Implementing Component Interface

Day 2 will talk about the use of Component Interface from 3 rd party tool and the
Excel toCI utility. The topics to be covered are
• Component Interface Collections
• Component Interface API
• Excel to Component Interface Utility

Day 3 will focus on using File object with Component Interface and Application
Engine to read and write data to flat files.

1.2 Technology Overview


There are three levels of integration in PeopleSoft.

Enterprise Portal – to integrate and offer a seamless user experience. This the
integration at People level and is concerned with the aggregation and presentation of
information. The information from different PeopleSoft or other systems are
aggregated and shown together. All the portals that we use like, Yahoo, MSN are
examples of this level of integration.

Page 3 of 84
PeopleSoft Enterprise Portal aggregates business critical transactions and provides
relevant context for more accurate, timely and effective business decisions.

Enterprise Warehouse - The data layer is primarily concerned with the extraction of
key information from different types of databases and applications and warehoused
together for all kind of business analysis and insight. This is the data warehouse
offered by PeopleSoft.

Integration Broker - The process layer which handles the system-to-system


communications This layer is squarely focused on optimizing existing business
processes, and enabling new value-added operations through the powerful use of
web technology.

We will focus on this process integration layer in the course. There are multiple
technologies offered by PeopleSoft under this. The key ones are
• Integration broker
• Component Interface
• WSDL Integration
• File Processing

Integration Broker is a messaged based system which allows synchronous and


asynchronous messaging using different formats. This allows for integration of a
PoepleSoft system with other PeopleSoft system or 3 rd party systems. A sample of
integrating two PeopleSoft systems is as given below

Page 4 of 84
Another scenario which integrates PeopleSoft with a 3rd party system is..

There are four components to the way integration works in PeopleSoft


• Delivered connectors
• Routing
• Transformations
• Development and monitoring environment

Delivered Connectors
All messages go through a single point known as Gateway. PeopleSoft comes
delivered with standard connectors. Further, you can also develop your own
connectors using the Application Development environment.

Routing
Routing ensures that the incoming message is delivered to the right receiving
system(s), and that the requesting system has the required security privileges.

Page 5 of 84
Based on the definition and setting of the message, Integration Broker delivers the
message in real-time (synchronous) in deferrable mode(asynchronous). The
messages are queued in different types of queues based on the definition and setup.

Transformation
Transformation is required to translate a message between different systems. The
Integration Broker takes a system message and converts the data from one system’s
format into another systems format.

Development and Monitoring Environment


Developers define the message structure, prepare the transformation and delivery
rules. Write the code to send messages or receive and process messages based on
the event when this needs to be done.

There is a front end PIA based monitoring environment as well to configure and
manage the messaging environment and also to take corrective actions on a day to
day basis to administer the Integration Broker environment.

Component Interface provides a non graphical way to access the PeopleSoft


system. It mimics the data entry that an online user would do. It validates all the
logic of a component in run time which can be used to access a component within a
program. The program could be a PeopleCode or a 3 rd party system trying to access
or modify data stored in PeopleSoft system. These systems do not need to know the
full implementation of transaction they are trying to access and treat it as a black
box. Essentially Component interface provides:
• A way to access data while enforcing all the business logic, validations, workflows
– just like the way it will happen from a front end PIA.
• PeopleSoft is a synchronous way to access data. What this means that the
system freezes while waiting for a response or trying to access the PeopleSoft
system.
• You can build APIs based on a Component Interface which opens up that
transaction for access and manipulation to 3rd party systems.

WSDL Integrations:

Page 6 of 84
• ERP connectors to J2EE, XML, SAP, Siebel and Oracle.
• Ability to import web services using WSDL.
• WSDL for PeopleSoft published Enterprise Integration Points (EIPs).
• A WSDL repository of all configured web services.

File Processing
File-based integrations provide the ability to exchange files with third-party system
or legacy systems that do not support messaging. Files are exchanged using File
layouts and Application Engine programs.

Importing a file into PeopleSoft.

You can handle the import in three ways.


• Read the file using a File layout object. Read the file in Application Engine and
carryout direct SQL inserts
• Read a file inside Application Engine. Then use PeopleCode to process the data
and load the data using a component interface. This resembles the way a human
operator would do if he was given all the data in a an excel and was asked to
enter the data manually. This is a synchronous way of reading and loading the
file.
• Read the file, prepare a message and publish the message to the same system.
The Message subscription code will read and process the data. Again the data
could be inserted using direct SQL or component interface. This approach
provides for a asynchronous way of loading the data.

Page 7 of 84
1.3 Introduction to Component Interface
Component Interface is a wrapper for the Component which we are trying to expose.

It encapsulates the logic, validation and business flow and opens this up as a black
box to other systems. It also allows for a non graphical way to access data from
PeopleCode.

E.g. if the address of an employee is changed, it should automatically update the


address stored in vendor table if that employee is also a vendor. This updation could
be done by direct SQL updates to the Vendor table at the time of saving the
employee address information. The other approach would be to open the Vendor
table (or rather component) using a Component Interface, locate the specific row to
be updated and then update the same. The second approach has the benefit that it
preserves all the logic, code, workflow and validation built at Vendor component
level. This would not be possible under the first approach of direct SQL update of
Vendor table.

Page 8 of 84
External applications can access a component interface’s data only by using the
component's specified properties or methods. These include:
• Properties, which are data items or fields (attributes).
• Collections, which are scroll areas or levels.
• Methods, which are PeopleCode functions.

In the online system, search keys are used to find the data that the online user
wants to access. In the component interface, these search keys are directly mapped
to keys.
In the online system, fields and levels are displayed on the page. These fields and
levels correspond to properties (fields) and collections (scroll areas or levels, such as
level 1, level 2, and so on). Properties are data items or fields (attributes).
Collections are scroll areas, levels, or records.

Page 9 of 84
PeopleCode functions are used to enforce the business logic of a component in the
online system. In the component interface, PeopleCode functions are mapped to
methods. Methods are PeopleCode (functions).

The component interface API is the API through which other applications have real-
time access to PeopleSoft Component Interfaces.

Component Interface Definition


Component Interface definition has four main components.
• Component Interface Name
• Keys
• Properties and Collections
• Methods

Each component Interface is based on a component definition which is specified


when the component is created. Click on the properties button to see the underlying
component

Page 10 of 84
The component name is provided at the time of creating a new component and then
it cannot be changed.

Keys
Keys uniquely identify an instance of a Component Interface. The keys are created
automatically based on the record property of the search record associated with
component for which the Component Interface is created. Once can add/modify the
keys.

In above example the Component Interface named DEPARTMENT_TBL is created


based on the Component DEPARTMENT_TBL. The search record for this component is
DEPT_TBL as shown below

Page 11 of 84
Shown below is the use properties of the record DEPT_TBL

The create keys are created for Components which have ADD action. They are based
on the primary search keys as defined in use properties of the search record i.e.
fields which are marked as “Key” and “Srch” both. Create keys are used for creating
new rows of data just like the search keys on a Component. Create keys cannot be
changed.

IN our example above SETID and DEPTID are the primary search keys which also
appear as the Create keys for the component interface.

Page 12 of 84
The Get keys are created for component with Update action. They are based on
search keys as defined in the use properties. You cannot change these keys. In our
example it is SETID and DEPTID. Create keys and Get keys can be different if the
Component has different Search Record and Add Search Record.

The find keys are based on the alternate search keys of the search record. I.e. the
fields in the search record that are marked as Alt and Srch both. You can modify the
keys.

Properties and Collections


Properties and Collection expose the data and structure underlying the component
based on which the Component Interface is being created.

Properties are individual fields on the component and collections are the scroll. If you
expand the scroll, you would see the properties and may be other collections (i.e.
scrolls) based on the structure of the component.

The diagram below shows that there are two properties called SETID and DEPTID
which map to DEPT_TBL.SETID and DEPT_TBL.DEPTID and then there is a collection
called DEPT_TBL. The name of the collection/scroll matches to the record which
forms the primary record at that scroll level.

If you click on the collection, it expands which shows the underlying properties and
collections which fall under the collection DEPT_TBL

Page 13 of 84
Another Component Interface which has multiple levels of collections.

You may also have noted that the original component structure and the Component
Interface is shown side by side.

Page 14 of 84
All the above are examples of user defined properties that get exposed to the
external system and can be manipulated using code i.e. PeopleCode, C++, java etc.

At runtime, you can use PeopleCode to assign a value to that property (field), or to
access the value of that field, as shown in the following example:

&MYCI.COUNTRY = "USA";
/* OR */

&COUNTRY = &MYCI.COUNTRY;

One can delete the properties that you do not want to be manipulated from outside.

There is another set of properties known as Standard properties.

The following properties affect how the component interface is run. These properties
must be set before the component interface is populated with data. That is, you must
set these properties before you use the Get or Create methods.
• EditHistoryItems
• GetHistoryItems
• InteractiveMode

EditHistoryItems and GetHistoryItems work together to determine how data is


accessed. If EditHistoryItems is False (the default) and GetHistoryItems is True, you
access the data in the component interface as if you were accessing a component in
Update/Display All mode. This means that all history rows are returned; however,
you can edit rows only with a date set in the future.

If EditHistoryItems is True and GetHistoryItems is True, you access the data in the
component interface as if you were accessing a component in Correction mode. This
means that all history rows are returned, and you can edit them.

If GetHistoryItems is False, you access the data in the component interface as if you
were accessing a component in Update mode. The EditHistoryItems has no effect
when GetHistoryItems is False.

Page 15 of 84
InteractiveMode causes the component interface to emulate an online component.
For example, if you set a value for a field in a component interface and you have set
InteractiveMode to True, then any FieldChange PeopleCode programs associated with
that field are initiated as soon as you set that value.

The following properties return information about the structure of the component
Interface. These properties are used to retrieve information from collections.
• CreateKeyInfoCollection
• FindKeyInfoCollection
• GetKeyInfoCollection
• PropertyInfoCollection

Methods
Methods are functions called to perform operations in a component interface. There
are two types of methods:
• Standard – which are created automatically for each Component Interface.
• User-defined – which are defined in PeopleCode.

Standard methods are created automatically, You can specify which methods to
activate.

Standard methods are like the human operator actions that can be taken on an
online component from PIA.

Page 16 of 84
User-defined methods are PeopleCode programs that you can write to perform
operations on a component interface. Each method is specific to a particular
component interface.

1.3 Creation and Testing of Component Interface


We will first talk about component interface creation. Following steps needed to be
performed:
• Create the Application that will use Component Interface
• Create/modify any supporting definition, if required.
• Create the Component Interface
• Apply the security for Component Interface
• Test the Component Interface in Application Designer
• Write the code to instantiate the Component Interface
• Test the Code

Let us consider the activity 14 from PeopleCode class wherein we created a vendor
table which had address fields being read from PERSONAL table for all vendors who
had an emplid field and had a tick in “Same Address” field. We now need to write a
code on the PERSONAL table so that whenever it is saved, a peoplecode will be used
to examine the vendor table and update the Vendor table with correct address. There
are two approaches to do this. We could write a SQLEXEC or use Record class to
make changes to Vendor table. But this approach has an issue, what if the vendor
component has some workflow or other logic. For example, what if the change in
vendor address needs to be communicated to procurement department or some
other department. We will have to examine all the code behind Vendor component
and recreate all that code in the save event of PERSONAL component.

There is another approach, we could use a Component Interface to open the vendor
component inside the save code of PERSONAL component and make changes using
the Component Interface. This ensures that all the code and validation written inside
the Vendor component is fired and taken care.

Keeping this objective in mind, let us create a Component Interface on vendor


component. So with our previous exercise, we have already carried out the first two
steps of a) creating the application that uses Component Interface and b)

Page 17 of 84
creating/modifying any supporting definitions. Now we will move through the
remaining steps

Create the Component Interface


Steps
1. In the Application designer, click on New definition, Component Interface and
click ok. It opens a dialog box where we specify the component on which the
Component Interface needs to be created.
2. We choose S1_VENDOR and click on Select

3. It asks for how to populate default properties. As a starting point we will base
it on the underlying component. Accordingly, we click on “Yes”.

4. The component Interface is created

Page 18 of 84
5. We will save the definition as S1_VENDOR_Component Interface.

Notes:
1. The component with its structure is displayed on the left side. This is same as
what we would see if we open the component in application designer and view
its structure. All objects in the component view are part of the underlying
component interface, and they are accessible through user-defined methods
or through PeopleCode events in the component. However, only the objects in
the component interface view are exposed to the calling program at runtime.
2. The Component Interface with its keys, properties and methods are displayed
on the right side.

The right hand side has five columns:


Name: which is the name of the element i.e. Component Interface, keys, properties,
methods.
Record: Name of the underlying record.
Field: name of the underlying field.
Read Only: A value of yes or no. A value of yes means that this property can only be
read or accessed from the runtime code but cannot be updated.
Comments: where a designer can record his comments to help it easier for recall or
program maintenance.

You can click on the Properties tab

Page 19 of 84
Here you can specify the general information under the General Tab. You specify the
Standard methods that you want to activate as seen earlier. Synchronization tab is
used for mobile pages which will not be covered in this course.

Coming back to the Component Interface view, we can highlight any property and
double click to examine the name, ready-only and comments fields.

When the component is originally created the property element is named as the
underlying field but we can change the name. This name is used in the code to
access and manipulate the underlying record.field value of the component.

We can provide some comments in the comments box.

We can make a property read-only if we do not want a code to change the value.

Please remember that you can also delete the properties that you do not want to
expose at all.

Page 20 of 84
Note: If the component under goes a change after the creation of Component
Interface, when you open the Component Interface it may contain invalid values for
examples properties that are not valid since the underlying record.field was removed
from the component. These will appear with a red cross before the element name.
You can validate a component by opening it. Then click on the tools menu and click
on the item “Validate for Consistency”

Let us briefly examine the process of creating a User defined method in PeopleCode.
However, please note that it is optional to create a user defined method.

First step is to click on the METHODS. Right click and click on “View PeopleCode”.
You then write a PeopleCode function (e.g. MyUser_Function”) and save. The
function appears as a separate entry under the tab METHODS.

The properties are created based on the default structure of the component abased
on our action in step 3 above.

Page 21 of 84
Activity 1 – Create a Component Interface on Vendor component.
IN this activity, students are required to create a component interface definition
based on the Vendor component. Once the component is created and saved,
students are required to discuss and modify the properties so that Component
Interface only allows required access to view and update the address fields as
discussed above.

Testing of Component Interface


Before we can test or use a component interface, we need to define security so that
access to Component Interface is granted.
Use the access “PeopleTools, Security, Permissions & Roles, Permission Lists,
S1_PL001 to open the permission list page. Click on the “Component Interface” tab
and populate the Component Interface name.

Click on the Edit link and specify the access for each of the methods. Just like a
component needs to be available in the security path of a user through the tree
Permission List -> Role -> User, a Component Interface also needs to be available in
the user’s security path before the same can be tested or accessed in run time using
code.

Once the security is defined, we revert back the Component Interface definition in
Application designer. Right click on the Component Interface name in the right side
pane of the definition. Click on “Test Component Interface”. It opens a new windows
where we can test the Component Interface.

Page 22 of 84
The box displays the keys in the upper portion and standard properties in the lower
half.

You use the Component Interface Tester tool to test methods associated with the
component interface:
• Use the Get Existing option to test the Get method.
• Use the Create New option to test the Create method.
• Use the Find option to test the Find method.
After adding or modifying data in the Component Interface Tester tool, you can test
the Save method by right-clicking the component interface and selecting Save from
the popup menu.

Results of Get Key test

Page 23 of 84
Let us click on the S1_SAME_ADDRESS field, change the value from ‘N’ to “Y’ and
see the impact on fields S1_ADDRSS. You can see that Address field has changed

The reason is that we wrote a code behind FieldChange event of field S1_ADDRESS
on Vendor component which would read the address from the PERSONAL table and
update the Address field on vendor from Personal if the SAME_ADDRESS flag was
ticked as Yes (Y).

Page 24 of 84
You have just seen how the validation and code written on the VENDOR component
is getting executed by using Component Interface to change the values.

Note: Component Interface provides live access to the data. When you test using
Component Interface, all the changes that you make get committed to the database.

Activity 2 – Grant Security


IN this activity, students are required to grant the security to the component created
in Activity 1.

Activity 3 – Test Component Interface


IN this activity, students are required to test the Component Interface. Also create a
new row using Component Interface and check it from SQL query to confirm that the
data has actually been written to the database.

create a component interface definition based on the Vendor component. Once the
component is created and saved, students are required to discuss and modify the
properties so that Component Interface only allows required access to view and
update the address fields as discussed above.

1.4 Implementing Component Interface


Till now we have created the Component Interface and tested it from Application
designer. This section will explain the process to be followed for deploying the
Component Interface and using it within Peoplecode to access and modify
collections/properties.

Before you can instantiate a component interface, you must establish a session with
the PeopleSoft application. Component interfaces can be called from external
systems. Before the external system can access the component interface, a session
needs to be established with the PeopleSoft application. The external system must
supply the proper credentials (user ID and password) to access the session. You use
the Connect method to sign on.

Page 25 of 84
The session class provides the following methods to instantiate the component
interface:
• FindCompIntfcs - This returns a list of component interfaces from which you can
choose.
• GetCompIntfc - This returns the specific component interface requested.

A component interface can be instantiated from:


• PeopleCode
• Microsoft COM (including Visual Basic)
• Java
• C or C++

COM stands for Component Object Model. It is a software architecture developed by


Microsoft to build component-based applications. ActiveX is also based on COM.

Life Cycle of a Component Interface

A high level overview of the process for instantiating a component interface has
following steps:
1. Session is established. This is followed by use of GetCompIntfc method to
instantiate the component interface.

Page 26 of 84
2. The key values for the component interface are set. If the key uniquely defines a
component interface, the next step is skipped.
3. If only partial keys are entered, then the Find method is used to display a list that
meets the criteria.
4. Get or Create method to retrieve data into the component interface.
5. You access the property values or set the property values. You can also run the
user defined methods.
6. You run the Save standard method to initiate the standard PeopleCode save
business rules and commit any changes to the database.

At any point, the standard method Cancel can be run to reset the component
interface to its state in step 1.

Writing Component Interface PeopleCode in an Application


Usually PeopleCode that calls a component interface is written in the
SavePostChange event which is fired after the component processor updates the
database.

SavePostChange is generally used to update tables that are not in the component. A
SQL Commit is issued after this event terminates successfully. Accordingly, a
Component Interface code written in this event which causes an error of causes a fail
of Component Interface update, will cause the unsuccessful termination of this
event. Accordingly, the update to the source component from where the Component
Interface code is fired is also not carried out.

Application designer creates a template for the code which can be used to instantiate
and get/set values using Component Interface. To create this template open the
PeopleCode editor and point the cursor at the point where you want the code to be
placed.

Page 27 of 84
Note that we can write the Component Interface Peoplecode at component or record
level at SavePostChange event.

Now drag and drop the Component Interface from project window to the place you
want the template code to be pasted.

Sample code generated is given below:


/* ===>

This is a dynamically generated PeopleCode template to be used only as a helper


to the application developer.
You need to replace all references to '[*]' OR default values with references to
PeopleCode variables and/or a Rec.Fields. */

Local File &fileLog;


Local ApiObject &oSession, &oS1VendorCi;

Function errorHandler()
Local ApiObject &oPSMessageCollection, &oPSMessage;
Local number &i;
Local String &sErrMsgSetNum, &sErrMsgNum, &sErrMsgText, &sErrType;

&oPSMessageCollection = &oSession.PSMessages;
For &i = 1 To &oPSMessageCollection.Count
&oPSMessage = &oPSMessageCollection.Item(&i);
&sErrMsgSetNum = &oPSMessage.MessageSetNumber;
&sErrMsgNum = &oPSMessage.MessageNumber;

Page 28 of 84
&sErrMsgText = &oPSMessage.Text;
&fileLog.WriteLine(&sErrType | " (" | &sErrMsgSetNum | "," | &sErrMsgNum | ") -
" | &sErrMsgText);
End-For;
rem ***** Delete the Messages from the collection *****;
&oPSMessageCollection.DeleteAll();
End-Function;

try
rem ***** Set the Log File *****;
&fileLog = GetFile("C:\temp\S1_VENDOR_Component Interface.log", "w", "a",
%FilePath_Absolute);
&fileLog.WriteLine("Begin");
rem ***** Get current PeopleSoft Session *****;
&oSession = %Session;

rem ***** Set the PeopleSoft Session Error Message Mode *****;
rem ***** 0 - None *****;
rem ***** 1 - PSMessage Collection only (default) *****;
rem ***** 2 - Message Box only *****;
rem ***** 3 - Both collection and message box *****;
&oSession.PSMessagesMode = 1;

rem ***** Get the Component Interface *****;


&oS1VendorCi = &oSession.GetCompIntfc(CompIntfc.S1_VENDOR_Component
Interface);
If &oS1VendorCi = Null Then
errorHandler();
throw CreateException(0, 0, "GetCompIntfc failed");
End-If;

rem ***** Set the Component Interface Mode *****;


&oS1VendorCi.InteractiveMode = False;
&oS1VendorCi.GetHistoryItems = True;
&oS1VendorCi.EditHistoryItems = False;

rem ***** Set Component Interface Get/Create Keys *****;


&oS1VendorCi.S1_VENDOR_ID = [*];

rem ***** Execute Get *****;


If Not &oS1VendorCi.Get() Then
rem ***** No rows exist for the specified keys.*****;
errorHandler();
throw CreateException(0, 0, "Get failed");
End-If;

rem ***** Execute Create ******;


rem If Not &oS1VendorCi.Create() Then;

Page 29 of 84
rem ***** Unable to Create Component Interface for the Add keys provided.
*****;
rem errorHandler();
rem throw CreateException(0, 0, "Create failed");
rem End-If;

rem ***** Begin: Get/Set Component Interface Properties *****;


rem ***** Get/Set Level 0 Field Properties *****;
&fileLog.WriteLine("&oS1VendorCi.S1_DESCR = " | &oS1VendorCi.S1_DESCR);
rem &oS1VendorCi.S1_DESCR = [*];
&fileLog.WriteLine("&oS1VendorCi.S1_EMPLID = " | &oS1VendorCi.S1_EMPLID);
rem &oS1VendorCi.S1_EMPLID = [*];
&fileLog.WriteLine("&oS1VendorCi.S1_SAME_ADDRESS = " |
&oS1VendorCi.S1_SAME_ADDRESS);
rem &oS1VendorCi.S1_SAME_ADDRESS = [*];
&fileLog.WriteLine("&oS1VendorCi.S1_ADDRESS = " | &oS1VendorCi.S1_ADDRESS);
rem &oS1VendorCi.S1_ADDRESS = [*];
&fileLog.WriteLine("&oS1VendorCi.S1_PHONE = " | &oS1VendorCi.S1_PHONE);
rem &oS1VendorCi.S1_PHONE = [*];
rem ***** End: Get/Set Component Interface Properties *****;

rem ***** Execute Save *****;


rem If Not &oS1VendorCi.Save() Then;
rem errorHandler();
rem throw CreateException(0, 0, "Save failed");
rem End-If;

rem ***** Execute Cancel *****;


rem If Not &oS1VendorCi.Cancel() Then;
rem errorHandler();
rem throw CreateException(0, 0, "Cancel failed");
rem End-If;

rem ***** Execute MyUser_Function *****;


rem &[*] = &oS1VendorCi.MyUser_Function([*]);
catch exception &ex
rem Handle the exception;
&fileLog.WriteLine(&ex.ToString());
end-try;
&fileLog.WriteLine("End");
&fileLog.Close();

Important sections have been highlighted in bold above.

Error handing is provided by use of the following code


Function errorHandler()
Local ApiObject &oPSMessageCollection, &oPSMessage;

Page 30 of 84
Local number &i;
Local String &sErrMsgSetNum, &sErrMsgNum, &sErrMsgText, &sErrType;

&oPSMessageCollection = &oSession.PSMessages;
For &i = 1 To &oPSMessageCollection.Count
&oPSMessage = &oPSMessageCollection.Item(&i);
&sErrMsgSetNum = &oPSMessage.MessageSetNumber;
&sErrMsgNum = &oPSMessage.MessageNumber;
&sErrMsgText = &oPSMessage.Text;
&fileLog.WriteLine(&sErrType | " (" | &sErrMsgSetNum | "," | &sErrMsgNum | ") -
" | &sErrMsgText);
End-For;
rem ***** Delete the Messages from the collection *****;
&oPSMessageCollection.DeleteAll();
End-Function;

The session object handles error processing for all APIs, such as component
interfaces.

All errors are contained in the PSMessages collection. (The PSMessages property of a
session object returns this collection.) Each item in this collection is a PSMessage
object. A PSMessage object contains information about the specific error that has
occurred; for example, the explanatory text for the error, the message set number,
and so on. The type of information depends on the type of error.
In the template, the errors are recorded in a log file at the path indicated in the
code, as shown here:

rem ***** Set the Log File *****;


&fileLog = GetFile("C:\temp\S1_VENDOR_Component Interface.log", "w", "a",
%FilePath_Absolute);
&fileLog.WriteLine("Begin");

The code used to populate the file as per the template above is:
For &i = 1 To &oPSMessageCollection.Count
&oPSMessage = &oPSMessageCollection.Item(&i);
&sErrMsgSetNum = &oPSMessage.MessageSetNumber;
&sErrMsgNum = &oPSMessage.MessageNumber;
&sErrMsgText = &oPSMessage.Text;
&fileLog.WriteLine(&sErrType | " (" | &sErrMsgSetNum | "," | &sErrMsgNum | ") -
" | &sErrMsgText);

Page 31 of 84
End-For;
This is called inside the function errorHandler.

Exception Class
Exception handling is done using the exception class. This class provides a try-catch
and throw mechanism so you don't need to check after each operation for errors, but
can instead declare by the structure of the try-catch statements when you are
interested in handling exceptions, and how you want to handle them.

Try-Catch
The statements that immediately follow the Try keyword are called the protected
statements. These are the only statements that are 'protected' by the catch clauses
in the Try-Catch statements. The catch clauses in a Try-Catch statement can be
executed only if an exception is thrown by the protected statements. In addition, a
catch clause is executed only when handling an exception that matches the type
given on the catch. Any exceptions thrown by the catch clauses are not caught by
their own Try-Catch statement.

The execution of the Try-Catch statement starts by executing the protected


statements. If none of these statements, as well as none of the statements called by
them, causes an exception to be thrown, the try-catch is done. The statements in
the catch clauses are not executed.

The Get and Create keys need to be set by replacing [*] with the appropriate value
in the following section:
rem ***** Begin: Get/Set Component Interface Properties *****;
rem ***** Get/Set Level 0 Field Properties *****;
&fileLog.WriteLine("&oS1VendorCi.S1_DESCR = " | &oS1VendorCi.S1_DESCR);
rem &oS1VendorCi.S1_DESCR = [*];
&fileLog.WriteLine("&oS1VendorCi.S1_EMPLID = " | &oS1VendorCi.S1_EMPLID);
rem &oS1VendorCi.S1_EMPLID = [*];
&fileLog.WriteLine("&oS1VendorCi.S1_SAME_ADDRESS = " |
&oS1VendorCi.S1_SAME_ADDRESS);
rem &oS1VendorCi.S1_SAME_ADDRESS = [*];
&fileLog.WriteLine("&oS1VendorCi.S1_ADDRESS = " | &oS1VendorCi.S1_ADDRESS);
rem &oS1VendorCi.S1_ADDRESS = [*];
&fileLog.WriteLine("&oS1VendorCi.S1_PHONE = " | &oS1VendorCi.S1_PHONE);

Page 32 of 84
rem &oS1VendorCi.S1_PHONE = [*];
rem ***** End: Get/Set Component Interface Properties *****;

Example of getting the value would be


&phone = &oS1VendorCi.S1_PHONE ;

Example of setting the value would be


&oS1VendorCi.S1_PHONE = &newNumber;
&oS1VendorCi.S1_PHONE = “4565643”;

Activity 4 – Activate a Component Interface


In this activity, students will be required to write the code for instantiating a
Component Interface and testing the Component. We will continue with the example
of Vendor Component Interface for this activity.

Run the component and examine the log file. Discuss the various log files with the
whole class.

1.5 Component Interface Collections

In this topics we will discuss in detail about the collections which map to the scrolls
in pages. This is also similar to rowset, row and record class that we talked about in
PeopleCode class.

Page 33 of 84
Each level of data in a Component Interface is known as collection.

A sample Component Interface with three levels of collections is shown below

ACAD_HISTROY is a collection at level 1.


EXT_ACAD_DATA is a collection at level 2.
EXT_ACAD_SUM is a collection at level 3.

The template PeopleCode generated for the above Component Interface shows how
we loop through the scrolls (i.e. collections)

&oAcadHistoryPers = &oSession.GetCompIntfc(CompIntfc.ACAD_HISTORY_PERS);

rem ***** Set/Get ACAD_HISTORY Collection Field Properties -- Parent: PS_ROOT Collection
*****;
&oAcadHistoryCollection = &oAcadHistoryPers.ACAD_HISTORY;
Local integer &i18;

Page 34 of 84
For &i18 = 1 To &oAcadHistoryCollection.Count;
&oAcadHistory = &oAcadHistoryCollection.Item(&i18);

rem ***** Set EXT_ACAD_DATA Collection Field Properties -- Parent: ACAD_HISTORY Collection
*****;
rem &oExtAcadDataCollection = &oAcadHistory.EXT_ACAD_DATA;
Local integer &i224;
For &i224 = 1 To &oExtAcadDataCollection.Count;
&oExtAcadData = &oExtAcadDataCollection.Item(&i224);

rem ***** Set EXT_ACAD_SUM Collection Field Properties -- Parent: EXT_ACAD_DATA Collection
*****;
rem &oExtAcadSumCollection = &oExtAcadData.EXT_ACAD_SUM;
Local integer &i343;
For &i343 = 1 To &oExtAcadSumCollection.Count;
&oExtAcadSum = &oExtAcadSumCollection.Item(&i343);

rem ***** Set EXT_ACAD_SUBJ Collection Field Properties -- Parent: EXT_ACAD_DATA Collection
*****;
rem &oExtAcadSubjCollection = &oExtAcadData.EXT_ACAD_SUBJ;
Local integer &i359;
For &i359 = 1 To &oExtAcadSubjCollection.Count;
&oExtAcadSubj = &oExtAcadSubjCollection.Item(&i359);

rem ***** Set EXT_DEGREE Collection Field Properties -- Parent: ACAD_HISTORY Collection
*****;
rem &oExtDegreeCollection = &oAcadHistory.EXT_DEGREE;
Local integer &i266;
For &i266 = 1 To &oExtDegreeCollection.Count;
&oExtDegree = &oExtDegreeCollection.Item(&i266);

rem ***** Set EXT_COURSE Collection Field Properties -- Parent: ACAD_HISTORY Collection
*****;
rem &oExtCourseCollection = &oAcadHistory.EXT_COURSE;
Local integer &i280;
For &i280 = 1 To &oExtCourseCollection.Count;
&oExtCourse = &oExtCourseCollection.Item(&i280);
End-For;

End-For;
rem ***** End: Get/Set Component Interface Properties *****;

A data collection is data—available at runtime or during test mode—that is


associated with a particular scroll area (or record). It has the following
characteristics:
• The data collection object returns information about each row of data (referred to
as an item) that is returned for the record at runtime.

Page 35 of 84
• To access a data collection, you use the name of the record (scroll area) as a
property in a component interface.
• At runtime, the Item() method of a collection is used to return information about
a particular row.

&Level_1 = &Component Interface.Level_1;


&Level_1_Item = &Level_1.Item(ItemNumber);
&Level_2 = &Level_1_Item.Level_2;

We first get a collection as shown below. This maps to Rowset as well i.e. a collection
of multiple rows.
&oAcadHistoryCollection = &oAcadHistoryPers.ACAD_HISTORY;

We then get a specific row of the collection. This is similar to a row in a rowset
&oAcadHistory = &oAcadHistoryCollection.Item(&i18);

This row may contain record fields i.e. properties or other collections. To get another
collection i.e. the next level of collection, we use the same constrcut as before
&oExtAcadDataCollection = &oAcadHistory.EXT_ACAD_DATA;

Next step is to get a row of this collection


&oExtAcadData = &oExtAcadDataCollection.Item(&i224);

We can then get/set the properties or go deeper to read the next level of collection
and so on.

Data Collection Methods

CurrentItem
Syntax
CurrentItem()

Page 36 of 84
Description
If the component associated with the Component Interface is effective-dated,
CurrentItem returns a reference to the current effective-dated item (row of data). To
get a specific item based on a date, use GetEffectiveItem.
If there is no current item, a Null is returned.

Example
&MYCD = &MYCI.EMPL_CHKLST_ITM;
&ITEM = &MYDC.CurrentItem();

DeleteItem
Syntax
DeleteItem(number)
Description
The DeleteItem method deletes the item (row of data) at the position specified by
number. This parameter takes a number value.
When the DeleteItem method is executed, if there are any RowDelete PeopleCode
programs associated with any of the fields, they fire as well, as if the user pressed
ALT+8 and ENTER or clicked the DeleteRow icon. However, the programs are
executed as if turbo mode was selected. (In turbo mode default processing is
performed only for the row being deleted.)
If you set the InteractiveMode property to True, any RowDelete PeopleCode runs
immediately after you execute DeleteItem. If this property is set to False, any
RowDelete PeopleCode runs after you execute the Save method.
The deleted item is not actually deleted from the database until after you use the
Save method.
Example
For example, suppose your Component Interface had two scrolls: EMPL_CHECKLIST
and EMPL_CHKLST_ITM. The data collection EMPL_CHECKLIST has four items (rows
of data.) The data collection EMPL_CHKLST_ITM (under the third item) has five items
(rows of data.) If you run this component in the Component Interface Tester, it
would look as follows:

Page 37 of 84
EMPL_CHK_BC in Component Interface Tester

To delete the third row in the third item, use the following:
Local ApiObject &MYSESSION;
Local ApiObject &MYCI;

&MYSESSION = %Session;
&MYCI = &MYSESSION.GetCompIntfc(COMPINTFC.EMPL_CHK_BC);
&MYLVL1 = &MYCI.EMPL_CHECKLIST;
&ITEM2 = &MYLVL1.Item(3);
&MYLVL2 = &ITEM2.EMPL_CHKLST_ITM;
&MYLVL2.DeleteItem(3);
&MYCI.Save();

GetEffectiveItem
Syntax

GetEffectiveItem(DateString, SeqNo)

Description
If the component associated with the Component Interface is effective-dated,
GetEffectiveItem returns a reference to the closest effective-dated item (row of data)
that is less than or equal to the date specified by the DateString. To get an item
based on the current effective date, use CurrentItem.

Page 38 of 84
Note. DateString takes only a string value. You must convert a date variable into a
string before you can use it for DateString. You can use the String function to do
this.
Parameters
DateString Specify the year, month, and day of the effective date that you want to
look for. This parameter takes a string value. You can specify the date
either as YYYY-MM-DD orMM/DD/YY.
SeqNo Specify the sequence number of the effective date that you want to look
for. This parameter takes a number value.
Returns
A reference to an effective-dated item.
Example
&MYCD = &MYCI.EMPL_CHKLST_ITM;
&DSTRING = String(&MYDATE);
&ITEM = &MYDC.GetEffectiveItem(&DSTRING, 1);

GetEffectiveItemNum
Syntax
GetEffectiveItemNum(DateString, SeqNo)
Description
If the component associated with the Component Interface is effective-dated,
GetEffectiveItemNum returns a reference to the number of the closest effective-
dated item (row of data) that is less than or equal to the date specified by the
DateString. To get an item number based on the current effective date, use
CurrentItemNum.
Note. DateString takes only a string value. You must convert a date variable into a
string before you can use it for DateString. You can use the String function to do
this.
Considerations for Returning Rows
GetEffectiveItemNum returns a valid row number only when EFFDT is less than or
equal to DateString. If the value you use for DateString pre-dates all the rows in the
data collection, this method returns a zero and logs a message in the PSMessages
collection.
For example, if 12/01/1990 was the earliest date in the collection, the following
would return zero:

Page 39 of 84
&NUM = &MYDC.GetEffectiveItemNum("01/01/1900", 1);

Parameters

DateString Specify the year, month, and day of the effective date that you want to look for. This
parameter takes a string value. You can specify the date either as YYYY-MM-DD
orMM/DD/YYYY.
SeqNo Specify the sequence number of the effective date that you want to look for. This
parameter takes a number value.

Returns
A number. This method returns 0 if no row matching the criteria is found.

Example
&MYCD = &MYCI.EMPL_CHKLST_ITM;
&DSTRING = String(&MYDATE);
&ITEMNUM = &MYDC.GetEffectiveItemNum(&DSTRING, 1);

InsertItem
Syntax
InsertItem(number)
Description
The InsertItem method inserts the item (row of data) at the position specified by
number. This parameter takes a number value. You can insert items below only the
zero level scroll. If you need to add a new data item, use the Create method instead.
InsertItem adds the new row after the current row. If the row has an effective date
(EFFDT) or an effective sequence (EFFSEQ), these values are copied into the new
row.
If you specify -1 for number, InsertItem inserts a new item (row) after the last row.
The InsertItem method returns a reference to the newly created item (row of data).
When the InsertItem method is executed, if there are any RowInsert PeopleCode
programs associated with any of the fields, they fire also, as if the user pressed
ALT+7 and ENTER or clicked the InsertRow icon. However, the programs are
executed as if turbo mode was selected. (In turbo mode default processing is
performed only for the row being inserted.)

Page 40 of 84
If you set the InteractiveMode property to True, any RowInsert PeopleCode runs
immediately after you execute InsertItem. If this property is set to False, any
RowInsert PeopleCode runs after you execute the Save method.
The inserted item is not added to the database until after you use the Save method.
Example
In the following example a new item (row of data) is added at the end of the current
collection.
&MYDC = &MYCI.EMPL_CHECKLIST;
&COUNT = &MYDC.Count;
&ITEM = &MYDC.InsertItem(&COUNT);
&ITEM.CHECKLIST_CD = "00001";
&ITEM.RESPONSIBLE_ID = "6609";
&RSLT = &MYCI.Save();

Item
Syntax
Item(number)
Description
The Item returns the item (row of data) that exists at the number position in the
data collection executing the method. The parameter takes a number value.

ItemByKeys
Syntax
ItemByKeys(­key_values)
Description
The ItemByKeys method returns the item specified by the parameters. The number
and type of keys are unique to each specific collection. Each key must be separated
by a comma.
The collection reference must be the name of the Component Interface, followed by
the record name. This method won’t work on a collection reference (that is,
&Component Interface.RECNAME.ItemByKeys, not &MYCOLLECTION.ItemByKeys).
After you’ve returned an item, use the ItemNum property to determine the number
of the item.
The keys must be in the exact order as in the Component Interface. A second level
data collection also contains the keys of the parent data collection.

Page 41 of 84
An easy way to determine the keys and their order in PeopleCode is to open the
Component Interface in PeopleSoft Application Designer, and use the Test
Component. To determine the keys in Visual Basic, use the Object Browser.

To see the signature for ItemByKeys:


1. Open the Component Interface in PeopleSoft Application Designer.
2. Start the Component Interface Tester.
Select the open Component Interface, then right-click, and select Test Component
Interface from the pop-up menu.
3. Instantiate an object.
Add data to the Get or Create keys and click Get Existing or Create New, respectively.
4. Expand the instantiated component until you find the collection in which you’re interested.
5. Right-click on the collection and select ItemByKeys from the resulting pop-up menu.
6. The dialog that follows shows you the specific parameters, types, and order in which you
should call ItemByKeys.
Returns
An item (row) of data from a data collection.
Example
Local ApiObject &MYSESSION;
Local ApiObject &Component Interface;
Local ApiObject &Component Interface_COLLECTION;
Local ApiObject &Component Interface_ITEM;

&MYSESSION = %Session;
&Component Interface = &MYSESSION.GetCompIntfc(COMPINTFC.CM_EVAL);
&Component Interface.EMPLID = "8001";
If &Component Interface.Get() <> 1 Then
Exit;
End-If;

&Component Interface_COLLECTION = &Component Interface.CM_EVALUATIONS;


&COUNT = &Component Interface_COLLECTION.Count;

&Component Interface_ITEM = &Component


Interface.CM_EVALUATIONS.itembykeys("01");
&Component Interface_ITEM.DESCR50 = "TEST";
If &Component Interface.Save() <> 1 Then
Exit;
End-If;

Data Collection Properties

Count
Description

Page 42 of 84
This property returns the number of data items (rows of data) in the data collection.
This property is read-only.
Example
&Component Interface = &MYSESSION.GetCompIntfc(COMPINTFC.CM_EVAL_BC);
&Component Interface.EMPLID = "8001";
&Component Interface.Get()

&Component Interface_COLLECTION = &Component Interface.CM_EVALUATIONS;


&COUNT = &Component Interface_COLLECTION.Count;

CurrentItemNumber Description
If the component associated with the Component Interface is effective-dated, this
property returns the item number for the current effective-dated item (row of data).
This property is read-only.

Data item Class Properties


ItemNum Description
This property returns the number of the data item (row) in the collection. For
example, many of the data collection methods takes a number as a parameter. Use
this property to determine the item number (row number) of an item in a collection,
then use that number in another method.
This property is read-only.
Example

Evaluate USER_ACTION

. . .

When = "D"
&Component Interface_ITEM = &Component
Interface_LVL1_NAMES.ItemByKeys(&NAME_TYPE, &NAME_PART);
If &Component Interface_ITEM <> Null then
&I = &Component Interface_LVL1_NAMES.ItemNum;
&Component Interface_LVL1_NAMES.DeleteItem(&I);
End-if;
. . .
End-Evaluate;

Page 43 of 84
Activity 5 – Updating row using a Component Interface
In this activity, students will be required to extend the work done in activity 4. We
will be required to update vendor table with correct address information whenever it
undergoes a change in PERSONAL component.

Activity 6 – Adding row using a Component Interface


In this activity, we will further enhance the automation and create a new vendor
every time a new employee is added. High level steps are:
1. Modify the S1_INSTALLATION table so that it captures the last vendor id
assigned.
2. modify the code in Vendor component so that the vendor id is auto
generated. Similar to the exercise we did for EMPLID field in PeopleCode
class.
3. Modify the Component Interface peoplecode in PERSONAL component so that
whenever the component is opened in Add mode, it will create a new Vendor
row for that employee. It should not be fired in any other mode of component
access for PERSONAL component.

1.6 Component Interface API


An API (application program interface) is a set of routines, protocols, and tools for
building software applications. PeopleSoft provides support for building component
interface APIs in:
• Microsoft COM (Visual Basic and Active Server pages).
• C/C++.
• Java Binding.

To build component interface APIs:


1. Open any component interface in PeopleSoft Application Designer.
2. Select Build, PeopleSoft APIs.
3. Select the appropriate check boxes and enter the appropriate paths,
depending on the type of binding that you want to build.

Page 44 of 84
4. Select All APIs.
5. Click OK to build the bindings that you selected.

Explaining Microsoft COM


Target directory – directory where COM type library is created. Typically
<PS_HOME>\bin\client\winx86.

COM server DLL location is where the PeopleSoft API adapter (psapiadapter.dll) is
located: <PS_HOME>\bin\client\winx86.

Use the AutoRegister check box to execute the registry file immediately upon
building the API.

Use the Clean-up Registry check box to clean up the registry if you have applied
previous versions of PeopleSoft_PeopleSoft.reg.

Explaining Java Classes


The target directory indicates the directory where the Java class source files will be
created.

Page 45 of 84
Explaining C Header Files
The target directory indicates the directory where the C header source files will be
created.

Generating Runtime Code Templates


You can create a runtime template in PeopleSoft Application Designer for Visual
Basic, C++, and Java. To generate the template:

1. Open the desired component interface in Application Designer.


2. Right-click anywhere in the Definition view to display the pop-up menu.
3. Select either Generate Visual Basic Template, Generate C++ Template, or
Generate Java Template.
4. Open the generated file and modify the source as needed.

Similar to the template code generated for PeopleCode, the code below is the
template code for Java.

//===>
//This is a dynamically generated Java template to be used only as a helper
//to the application developer.
//You need to replace all references to '<*>' OR default values with references to
//Java variables.

//package <*>;
import java.io.*;
import psft.pt8.joa.*;

Page 46 of 84
import PeopleSoft.Generated.CompIntfc.*;
public class S1_VENDOR_Component Interface {
public static ISession oSession;

public static void ErrorHandler() {


//***** Display PeopleSoft Error Messages *****
if (oSession.getErrorPending() || oSession.getWarningPending()) {
IPSMessageCollection oPSMessageCollection;
IPSMessage oPSMessage;

oPSMessageCollection = oSession.getPSMessages();
for (int i = 0; i < oPSMessageCollection.getCount(); i++) {
oPSMessage = oPSMessageCollection.item(i);
if (oPSMessage != null)
System.out.println("(" +
oPSMessage.getMessageSetNumber() + "," + oPSMessage.getMessageSetNumber() + ") : " +
oPSMessage.getText());
}
//***** Done processing messages in the collection; OK to delete *****
oPSMessageCollection.deleteAll();
}
}

public static void main (String args[]) {


try {
//***** Set Connect Parameters *****
String strServerName, strServerPort, strAppServerPath;
String strUserID, strPassword;
BufferedReader inData = new BufferedReader(new
InputStreamReader(System.in));

//Get Application Server Machine Name


System.out.print("Enter Application Server Machine Name: ");
strServerName = inData.readLine();

//Get Application Server Port Number


System.out.print("Enter Application Server Port Number: ");
strServerPort = inData.readLine();

//Get PeopleSoft UserID


System.out.print("Enter PeopleSoft UserID: ");
strUserID = inData.readLine();

//Get PeopleSoft UserID Password


System.out.print("Enter PeopleSoft UserID Password: ");
strPassword = inData.readLine();

if (strServerName.length() == 0 ||
strServerPort.length() == 0 ||
strUserID.length() == 0 ||

Page 47 of 84
strPassword.length() == 0) {
System.out.println("\nConnect information provided is incomplete");
return;
}

//Build Application Server Path


strAppServerPath = strServerName + ":" + strServerPort;

//***** Create PeopleSoft Session Object *****


oSession = API.createSession();

//***** Connect to the App Server *****


if (!oSession.connect(1, strAppServerPath, strUserID, strPassword, null)) {
System.out.println("\nUnable to Connect to Application Server.");
ErrorHandler();
return;
}

//***** Get Component Interface *****


IS1VendorCi oS1VendorCi;
String ciName;
ciName = "S1_VENDOR_Component Interface";
oS1VendorCi = (IS1VendorCi) oSession.getCompIntfc(ciName);
if (oS1VendorCi == null) {
System.out.println("\nUnable to Get Component Interface " + ciName);
ErrorHandler();
return;
}

//***** Set the Component Interface Mode *****


oS1VendorCi.setInteractiveMode(false);
oS1VendorCi.setGetHistoryItems(true);
oS1VendorCi.setEditHistoryItems(false);

//***** Set Component Interface Get/Create Keys *****


String strS1VendorId;
System.out.print("\nEnter S1VendorId: ");
strS1VendorId = inData.readLine();
oS1VendorCi.setS1VendorId(strS1VendorId);

//***** Execute Get *****


if (!oS1VendorCi.get()) {
System.out.println("\nNo rows exist for the specified keys.\nFailed to
get the Component Interface.");
ErrorHandler();
return;
}

//***** Execute Create *****


//if(!oS1VendorCi.create()) {

Page 48 of 84
// System.out.println("\nUnable to Create Component Interface for the
Add keys provided.\n");
// return;
//}

//***** BEGIN: Set/Get Component Interface Properties *****


//***** Set Level 0 Properties *****
System.out.println("oS1VendorCi.S1VendorId: " +
oS1VendorCi.getS1VendorId());
System.out.println("oS1VendorCi.S1Descr: " + oS1VendorCi.getS1Descr());
//oS1VendorCi.setS1Descr(<*>);
System.out.println("oS1VendorCi.S1Emplid: " + oS1VendorCi.getS1Emplid());
//oS1VendorCi.setS1Emplid(<*>);
System.out.println("oS1VendorCi.S1SameAddress: " +
oS1VendorCi.getS1SameAddress());
//oS1VendorCi.setS1SameAddress(<*>);
System.out.println("oS1VendorCi.S1Address: " + oS1VendorCi.getS1Address());
//oS1VendorCi.setS1Address(<*>);
System.out.println("oS1VendorCi.S1Phone: " + oS1VendorCi.getS1Phone());
//oS1VendorCi.setS1Phone(<*>);

//***** END: Set Component Interface Properties *****

//***** Execute Standard and Custom Methods *****


//***** Execute Save *****
//if (!oS1VendorCi.save()) {
// System.out.println("Unable to Save Component Interface");
// ErrorHandler();
// return;
//}

//***** Execute Cancel *****


//if (!oS1VendorCi.cancel()) {
// System.out.println("Unable to Cancel Component Interface");
// ErrorHandler();
// return;
//}

//***** Execute MyUser_Function *****


//<*> = oS1VendorCi.myUser_Function(<*>);

//***** Disconnect from the App Server *****


oSession.disconnect();
return;
}
catch (Exception e) {
e.printStackTrace();
System.out.println("An error occurred: ");
ErrorHandler();
}

Page 49 of 84
}
}

2.0 Excel to Component Interface Utility

The Excel to Component Interface Utility is an excel spreadsheet that contains the
visual basic code enabling you to upload data to your PeopleSoft database. The code:
• Formats the spreadsheet data into a PeopleSoft readable Document Object Model
(DOM) structure.
• Submits the DOM structure to PeopleSoft.
• Parses the DOM structure.
• Utilizes the component interface to create entries in the PeopleSoft database.
• Based upon the save results, another DOM document is created that returns
success, error or warnings.
• Records in error can be corrected and resubmitted.

The Excel to Component Interface workbook has five (5) worksheets, the first is the
coversheet, and the next four are the steps used to upload data:

1. Coverpage
2. Connection Information
3. Template
4. Data Input
5. Staging and Submission

The cover page provides information about the ExcelToCI and steps involved in it.

Page 50 of 84
2nd sheet relates to connection information. Here you provide the details to connect
to the web server.

Page 51 of 84
Click on 3rd sheet and then click on “new Template”. Here we provide the information
about the component interface for which the template has to be generated.

This generates the component structure as shown below.

Once the template is generated, the next stage is to generate the Input Data
worksheet i.e. deicing on the input fields and the fields that need to be marked for
submission to database using the Component Interface. The fourth stage is to input
the data into the excel which will then be uploaded.

Page 52 of 84
The last step is stage and Submit data. If there are errors, then we need to correct
the same in Input Data stage and then resubmit.

3.0 Integration Broker


PeopleSoft Integration Broker is a middleware technology that facilitates
synchronous and asynchronous messaging among internal systems and trading
partners, while managing message structure, message format, and transport
disparities. Because of its modular design, many elements that you develop for an
integration using Integration Broker can be reused in other integrations.

PeopleSoft Integration Broker consists of two subsystems: the integration gateway


and the integration engine. The integration gateway resides on a PeopleSoft web
server, and the integration engine is installed on an application server as part of the
PeopleSoft application.

The integration gateway manages the receipt and delivery of messages passed
among systems through PeopleSoft Integration Broker. It supports the standard
TCP/IP protocols used in the marketplace today and provides extensible interfaces to
develop new connectors for communication with legacy, enterprise resource
planning, and internet-based systems.

Page 53 of 84
The integration engine runs on the PeopleSoft application server. It’s tied closely to
the PeopleSoft application, and it sends or receives messages for the application.
Rather than communicating directly with other applications, the integration engine
sends and receives messages through one or more separately installed integration
gateways.

You use an integration gateway to receive and send messages among integration
participant systems.

Listening connectors receive incoming messages and deliver the incoming requests
to the gateway manager, which is a dispatcher for messages that flow through an
integration gateway. The gateway manager determines which target connector to
use to properly deliver the messages to their intended recipients. The target
connector then delivers the messages to the intended recipients using the recipients’
preferred protocols. Listening connectors and target connectors transport messages
between integration participants and the integration gateway. These connectors
support asynchronous and synchronous message handling. Many connectors are
configurable at the integration gateway and system levels.

Page 54 of 84
Listening Connectors
Listening connectors receive incoming data streams and perform services based on
the content of the stream. They are invoked externally by other PeopleSoft systems
and third-party systems.

Target Connectors
Target connectors initiate communication with other PeopleSoft systems or third-
party systems. A target connector might not receive a response from the target
system during each operation, but every transmission requires a low-level
acknowledgment.

Gateway Manager
The gateway manager processes every message that flows through an integration
gateway and maintains links to the other major integration gateway components,
including target connectors, listening connectors, and each of the gateway services.

Listening connectors invoke the gateway manager when they receive a message
request. The gateway manager uses the messaging objects IBRequest and
IBResponse to determine how to route each message.

Page 55 of 84
The gateway manager uses a number of the gateway services during this stage to
perform operations such as message validation. The gateway manager then invokes
the appropriate target connector based on the content of the message object and
waits for a reply from the target connector. When the reply is received, the gateway
manager forwards the reply to the calling listening connector.

If an error occurs, the gateway manager uses the error handling service and works
with the service to prepare an error reply for the listening connector.

Gateway Services
Error Handling
The integration gateway provides a standard error handling interface that is exposed
to each connector. This service provides error handling and error logging for most
connectors delivered with PeopleSoft Integration Broker.

Messaging Objects
Two objects comprise the messaging objects service in the integration gateway:
IBRequest
IBResponse
These objects represent the request and response that enter and exit PeopleSoft
Integration Broker.

XML Parsing
Most IBRequest objects and IBResponse objects that are processed in the system
contain a content section, called IBInfo, that represents the actual business message
sent.

Most of the time, these content sections contain XML data. Consequently, often
connectors must parse and traverse XML. Many developers find that the standard
Java XML objects are cumbersome for manipulating XML, so the integration gateway
provides an XML parsing service consisting of objects that provide an intuitive
interface for manipulating XML objects. This service is delivered as a set of three
classes: XmlDocument, XmlNode and XmlNodeList.

Page 56 of 84
Message Validation
Messages that pass into PeopleSoft Integration Broker must contain certain elements
to be processed. Because the integration gateway is the first component that
processes messages sent to a PeopleSoft application, it performs basic message
validation—such as making sure that the message identifies its requestor and
message name—to ensure that the integration engine and the target application can
process them.

Connector Management
The connector management service is a composite of several services that manage
connectors. The gateway processes each IBRequest to determine the appropriate
connector to call in each situation. This is primarily a message routing function that
has varying levels of complexity abstracted from the connectors. The connector
management service also processes the IBResponse returned by each connector.

Error and Message Logging


Most components in the system use a standard error logging interface. Each
PeopleSoft-delivered connector uses the logging API in the same fashion, ensuring
that an administrator can quickly drill down on problems or simply review message
logs to see the IBRequest object, the IBResponse object, and even the raw data
exchanged with integration participants.

Transaction Actions
Type

Outbound 1. The application generates and sends a request message.


asynchronous 2. One or more target system receives and processes the
request message.

Outbound 1. The application generates and sends a request message.


synchronous 2. The application suspends activity and waits for a response
message.
3. A single target system receives and processes the request
message, then generates and sends a response message.
4. The application resumes its activity and receives and
processes the response message.

Inbound 1. A source system generates and sends a request message.

Page 57 of 84
Transaction Actions
Type

asynchronous 2. The application receives and processes the request


message.

Inbound 1. A source system generates and sends a request message.


synchronous 2. The source system suspends activity and waits for a
response message.
3. The application receives and processes the request
message, then generates and sends a response message.
4. The source system resumes its activity and receives and
processes the response message.

The diagram below describes the flow of a typical request message through
PeopleSoft Integration Broker. First diagram is a message flow for an inbound
request and 2nd diagram is about an out bound message request.

Page 58 of 84
Message Definition
Till now we studied the messaging architecture. Now this section will briefly touch
upon the message definition and channels.

Message definitions are the heart of PeopleSoft Integration Broker. They are
templates for the data that the application sends or receives. You create message
definitions in PeopleSoft Application Designer. There are two types of messages:

Rowset-based messages.
For hierarchical data based on PeopleSoft records, you create a message definition
by assembling records, organizing them into a hierarchy, and selecting fields from
those records to include in the message. The result is a rowset that doesn’t need to
match an existing rowset structure in the application. Use the PeopleCode Rowset
and Message classes to generate, send, receive, and process these messages.

Non-rowset-based messages.
These messages can have virtually any structure and content. You create a message
definition, but you do not insert any records. The message definition serves as a
placeholder for the actual message. Use the PeopleCode XmlDoc and Message
classes to generate, send, receive and process these messages. If you’re handling
Simple Object Access Protocol (SOAP) compliant data, you can also use the SoapDoc
class to generate and process these messages.

Page 59 of 84
Message Channel
Channels are logical groupings of messages. Each message must belong to exactly
one message channel. Channels are used to:

• Establish message processing sequence.


• Increase throughput by using unordered processing.
• Maintain messaging security.
• Maintain messages with common configuration properties.
• Define processing attributes for timeout parameters, error thresholds, and
delivery type.

You create channel definitions in PeopleSoft Application Designer. You must define a
channel before you define the messages that are assigned to it.

Publishing Asynchronous Messages


The simplest way to populate a message with data is to copy the rowset from an
existing component. The message must have the same structure as the rowset being
copied. High level steps are:
1. Instantiate the message object using the built-in function CreateMessage
(MESSAGE.messagename).
2. Use the IsActive property of the message to ensure that the message is
active.
3. Copy the data from the component using one of the CopyRowset methods.
4. Publish the message using Publish method in the following places to
asynchronously send a message:
 A record field PeopleCode event.
 A component PeopleCode event.
 An Application Engine program.

Page 60 of 84
 A message subscription program.
 The message OnRequest PeopleCode event.

Subscribing to Asynchronous Messages


The PeopleCode that you use to receive a message must be associated with the
message definition.
For asynchronous messages, enter subscription PeopleCode in the Message
Subscriptions section of the message structure view.
For synchronous messages, enter receiving PeopleCode in the OnRequest
PeopleCode event associated with the root of the message structure.

Subscription PeopleCode should perform the following:


• Instantiate the message.
• Execute edits.
• Instantiate the rowsets.
• Evaluate the message PSCAMA record to determine the action to perform.

Assigning Transactions to Nodes


You set up a transaction for a specific message on these nodes:
• Each node to which you are sending a message (outbound).
• Each node from which you will accept messages (inbound).

Page 61 of 84
4.0 File Objects & Components Interface

File Layouts
A file layout is a definition that represents the data structure of a text file to be
processed. The file layout:
• Serves as a template to identify and process the file’s records and fields.
• Works with hierarchical and nonhierarchical data.
• Handles files that combine data records with nondata records (that is, audit and
control records).
• Simplifies reading, writing, and manipulating hierarchical transaction data with
PeopleCode.

A file layout is a definition that represents the data structure of a flat (text) file to be
processed. When reading from or writing to a flat file, the PeopleCode can use a file
layout as a template to identify and correctly process the file’s records and fields. File
layouts work with hierarchical and nonhierarchical data, and they can handle files
that combine data records with nondata (audit or control) records.

The PeopleSoft system supports three file layout formats:


 Fixed position (FIXED) - Each field has a starting position and a length, which
together specify its location in the file. This is the default format for new file
layouts.
 Comma-separated values (CSV) - Fields are located in the file by their
sequence, and they are separated by commas.
 XML tagged (XML) - A field is located not by its position or sequence within a
record but by the named XML tags surrounding it.

Example of a FIXED position file format

The following table describes the properties of FIXED format files:

Page 62 of 84
Property Description PeopleSoft EDI Manager
Equivalent

File Layout File format (FIXED). None.


Format

File Record ID A group of numbers that can be used to RowID.


identify the file record.

ID Start The column starting position of the file record Treated as a field within
Position ID. each map.

(Record) ID The length of the file record ID. Treated as a field within
Length each map.

File Record A user-specified name for the file record. PeopleSoft record name.
Name

File Field A user-specified name for the file field. PeopleSoft record’s field
name.

(Field) Start The column starting position of the file field. Starting position.
Position

Field Length The length of the file field. Length of the field.

Field Format The formatting options for both inbound and Based on the field type.
outbound field processing.

Example of a CSV file format

The following table describes the properties of CSV format files:

Page 63 of 84
Property Description EDI Manager
Equivalent

File Format File format (CSV). None.

File Record ID A group of numbers that can be used to identify the RowID.
file record.

ID Sequence The sequence number of the field that contains the file Treated as a field
Number record ID. within each map.

Qualifier The character that surrounds a field to mark its Delimiter.


extent. This can be set at the file layout, file record,
or file field level.

Delimiter The character used to separate fields from each other. Separator.
This can be set at the file layout or file record level.

File Record A user-specified name for the file record. None.


Name

File Record A user-specified name for the file field. None.


Field

Field Format The formatting options for both inbound and outbound Based on the field
field processing. type.

Example of a XML file Format

Page 64 of 84
The following table describes the properties of XML format files:

Property Description

File Format The file format (XML).

File Record ID The tag name representing the file record.

Field Identifier The tag name representing the file field.

Field Format The formatting options for both inbound and outbound field processing.

File Record Name A user-specified name for the file record.

Field Name A user-specified name for the file field.

Page 65 of 84
Creating a File Format
Click on File New Objects and select File Format.

Click on Properties button to access and define the type of file format and its
associated properties

Page 66 of 84
Next is you Insert a record. By right clicking and selecting the option “Insert Record”.

Next Step is to select the Preview tab to map the file layout to a flat file. Use the
following steps to display the preview:
1. Select the Preview tab of the file layout.
2. Select the record name in the Segment Name drop-down list box.
3. In the Default File Name field, enter the name of the file to which you are
mapping.
4. Select View, Refresh Preview Data (F5), or click the refresh icon to preview
the data.

Page 67 of 84
The following table shows some examples of input data errors:

Symptom Possible Reason Solution

The preview grid The input file’s format doesn’t match Change the file layout format to
doesn’t appear. the file layout format that you match the input file.
specified in the File Layout Definition Change the definition qualifier
Properties dialog box. to match the one that is used in
A CSV file doesn’t use the definition the input file.
qualifier you specified in the File
Layout Definition Properties dialog
box.

Only the first A CSV file doesn’t use the definition Change the definition delimiter
column of the delimiter you specified in the File to match the one that is used in
preview grid is Layout Definition Properties dialog the input file.
populated. box.

The preview grid The file’s record IDs for the missing Specify file record IDs that
appears for some records don’t match their file record match the input file records.
records, but not for IDs specified in the File Layout
others. Segment Properties dialog box.

Data for a field With a FIXED file, the field length that Increase the field length to
appears truncated in you specified in the File Layout Field accommodate the input data.
the preview grid. Properties dialog box is too short to
accommodate the field data.

A field appears to With a FIXED file, the start position Decrease the start position and
start in the middle you specified in the File Layout Field adjust the field length to match

Page 68 of 84
Symptom Possible Reason Solution

of the data. Properties dialog box is too great to the input data start position
include the start of the field data. and length.

Importing Data Using File Layouts


To create the import Application Engine program:
1. Select the Preview tab of the file layout.
2. Select the record name in the Segment Name drop-down list box.
3. In the Default File Name field, enter the name of the file to which you are
mapping.
4. Select View, Refresh Preview Data (F5), or click the refresh icon to preview
the data.
5. Save the file layout.
6. Select Edit, Generate Import AE, or click the AE icon on the toolbar.
7. Enter the Application Engine program name in the dialog box.
8. The Application Engine program is created, and it appears in the project work
space.

Code generated is…


Function EditRecord(&REC As Record) Returns boolean;
Local integer &E;
REM &REC.ExecuteEdits(%Edit_Required + %Edit_DateRange + %Edit_YesNo +
%Edit_TranslateTable + %Edit_PromptTable + %Edit_OneZero);
&REC.ExecuteEdits(%Edit_Required + %Edit_DateRange + %Edit_YesNo + %Edit_OneZero);
If &REC.IsEditError Then
For &E = 1 To &REC.FieldCount
&MYFIELD = &REC.GetField(&E);
If &MYFIELD.EditError Then
&MSGNUM = &MYFIELD.MessageNumber;

Page 69 of 84
&MSGSET = &MYFIELD.MessageSetNumber;
&LOGFILE.WriteLine("****Record:" | &REC.Name | ", Field:" | &MYFIELD.Name);
&LOGFILE.WriteLine("****" | MsgGet(&MSGSET, &MSGNUM, ""));
End-If;
End-For;
Return False;
Else
Return True;
End-If;
End-Function;

Function ImportSegment(&RS2 As Rowset, &RSParent As Rowset)


Local Rowset &RS1, &RSP;
Local string &RecordName;
Local Record &REC2, &RECP;
Local SQL &SQL1;
Local integer &I, &L;
&SQL1 = CreateSQL("%Insert(:1)");
&RecordName = "RECORD." | &RS2.DBRecordName;
&REC2 = CreateRecord(@(&RecordName));
&RECP = &RSParent(1).GetRecord(@(&RecordName));
For &I = 1 To &RS2.ActiveRowCount
&RS2(&I).GetRecord(1).CopyFieldsTo(&REC2);
If (EditRecord(&REC2)) Then
&SQL1.Execute(&REC2);
&RS2(&I).GetRecord(1).CopyFieldsTo(&RECP);
For &L = 1 To &RS2.GetRow(&I).ChildCount
&RS1 = &RS2.GetRow(&I).GetRowset(&L);
If (&RS1 <> Null) Then
&RSP = &RSParent.GetRow(1).GetRowset(&L);
ImportSegment(&RS1, &RSP);
End-If;
End-For;
If &RSParent.ActiveRowCount > 0 Then
&RSParent.DeleteRow(1);
End-If;
Else
&LOGFILE.WriteRowset(&RS);
&LOGFILE.WriteLine("****Correct error in this record and delete all error messages");
&LOGFILE.WriteRecord(&REC2);
For &L = 1 To &RS2.GetRow(&I).ChildCount
&RS1 = &RS2.GetRow(&I).GetRowset(&L);
If (&RS1 <> Null) Then
&LOGFILE.WriteRowset(&RS1);
End-If;
End-For;
End-If;
End-For;
End-Function;

Page 70 of 84
rem *****************************************************************;
rem * PeopleCode to Import Data *;
rem *****************************************************************;
Local File &FILE1;
Local Record &REC1;
Local SQL &SQL1;
Local Rowset &RS1, &RS2;
Local integer &M;

&FILE1 = GetFile("C:\temp\a1.txt", "r", "a", %FilePath_Absolute);


&LOGFILE = GetFile("C:\temp\a1.txt.err", "W", %FilePath_Absolute);
&FILE1.SetFileLayout(FileLayout.S1_TEST);
&LOGFILE.SetFileLayout(FileLayout.S1_TEST);
&RS1 = &FILE1.CreateRowset();
&RS = CreateRowset(Record.S1_VENDOR);
&SQL1 = CreateSQL("%Insert(:1)");
&RS1 = &FILE1.ReadRowset();
While &RS1 <> Null;
ImportSegment(&RS1, &RS);
&RS1 = &FILE1.ReadRowset();
End-While;

&FILE1.Close();
&LOGFILE.Close();

Shown below is the properties tab of the AE. You may need to suitably modify the
properties before the same can be tested.

Page 71 of 84
File Class
The above program makes use of the File Class. The File class enables the exchange
of data with flat files by using:
 Functions
 Methods
 Properties

Errors are handled using the ExecuteEdits method in the following manner:
 If errors are detected, the rowset object’s IsEditError property returns the
value True.
 The EditError property of every field in the rowset is examined to find the one
that returns the value True.

Page 72 of 84
 The field’s MessageSetNumber and MessageNumber properties determine the
relevant error message.

Function EditRecord(&REC As Record) Returns boolean;


Local integer &E;
&REC.ExecuteEdits(%Edit_Required + %Edit_DateRange + %Edit_YesNo +
%Edit_OneZero);
If &REC.IsEditError Then
For &E = 1 To &REC.FieldCount
&MYFIELD = &REC.GetField(&E);
If &MYFIELD.EditError Then
&MSGNUM = &MYFIELD.MessageNumber;
&MSGSET = &MYFIELD.MessageSetNumber;
&LOGFILE.WriteLine("****Record:" | &REC.Name | ", Field:" |
&MYFIELD.Name);
&LOGFILE.WriteLine("****" | MsgGet(&MSGSET, &MSGNUM, ""));
End-If;
End-For;
Return False;
Else
Return True;
End-If;
End-Function;

You instantiate the File object by using the GetFile function:

GetFile

Syntax
GetFile(filename, mode [, charset] [, pathtype])

Description
Use the GetFile function to instantiate a new file object from the File class, associate
it with an external file, and open the file so you can use File class methods to read
from or write to it.

Working With Relative Paths


If you specify a relative path, that path is appended to the path specified by an
environmental variable, if the variable exists, in a particular order. This means if the

Page 73 of 84
first environmental variable in order is found, that is the one that's used. If it isn't
found, the next one is searched for, and if found, is used, and so on.
If GetFile is called from Application Engine when running standalone that is, when
not within an application server domain), the following environmental variables are
valid, and are searched for in the following order:

PS_FILEDIR[\relative_path]
PS_SERVDIR\Files[\relative_path]

The PS_FILEDIR environmental variable is not initialized and set to a path


automatically. If you want to use this environmental variable, you must set it
yourself.

Parameters
filespec Specify the name, and optionally, the path, of the file you want to open.
mode A string indicating how you want to access the file. The mode can be one of
the following:
"R" (Read mode): opens the file for reading, starting at the beginning.
"W" (Write mode): opens the file for writing. When you specify Write mode,
any existing content in the file is discarded.
"U" (Update mode): opens the file for reading or writing, starting at the
end. Any existing content is retained. Use this mode and the GetPosition
and SetPosition methods to maintain checkpoints of the current read/write
position in the file.
In Update mode, any write operation clears the file of all data that follows
the position you set.
"E" (Conditional "exist" read mode): opens the file for reading only if it
exists, starting at the beginning. If it doesn’t exist, the Open method has no
effect. Before attempting to read from the file, use the IsOpen property to
confirm that it’s open.
"N" (Conditional "new" write mode): opens the file for writing, only if it
doesn’t already exist. If a file by the same name already exists, the Open
method has no effect. Before attempting to write to the file, use the IsOpen
property to confirm that it’s open. You can insert an asterisk (*) in the

Page 74 of 84
filename to ensure that a new file is created. The system replaces the
asterisk with numbers starting at 1 and incrementing by 1, and checks for
the existence of a file by each resulting name in turn. It uses the first name
for which a file doesn’t exist. In this way you can generate a set of
automatically numbered files. If you insert more than one asterisk, all but
the first one are discarded.
charset A string indicating the character set you expect when you read the file, or
the character set you want to use when you write to the file. You can
abbreviate Unicode UTF-16 to "U" and the host operating system's default
non-Unicode (sometimes referred to as the ANSI character set) to “A”. All
other character sets must be spelled out in full, for example, ASCII, THAI,
or UTF8.
If non-Unicode (“A”) is specified, or you don't specify a character set, the
character set used is dependent on the application server configuration. On
a Windows application server, the default non-Unicode character set is
dependent on the Windows ANSI Codepage (ACP) which can be checked
using the DOS command chcp. On a Unix application server, the default
non-Unicode character set is specified in the application server configuration
file, psappsrv.cfg, and can be modified using PSADMIN. You can also use a
record field value to specify the character set (for example,
RECORD.CHARSET.)
Note. If you attempt to read data from a file using a different character set
than was used to write that data to the file, the methods used generate a
runtime error or the data returned is unusable.
When a file is opened for reading using the “U” charset argument, GetFile
expects the file to begin with a Unicode Byte Order Mark (BOM), otherwise
known as a sentinal. This mark indicates whether the file is written in big
endian order or little endian order. A BOM consisting of the hex value
0xFEFF indicates a big endian file, a BOM consisting of the hex value 0xFFEF
indicates a little endian file. If the Unicode UTF-16 file being opened does
not start with a BOM, an error is returned. The BOM is automatically
stripped from the file when it is read into the buffers by GetFile.
When a file is opened for writing using the “U” charset argument, the
Unicode BOM is automatically written to the start of the file, dependent on
whether the application server hardware platform operates in little endian or

Page 75 of 84
big endian mode.
Byte Order Marks are not expected or supported for files in other character
sets, including UTF8.
Note. When working with XML documents, specify UTF8 for charset.

If you are writing an XML file using a different charset, you must remember
to include a charset declaration in the XML file.
pathtype If you have prepended a path to the file name, use this parameter to
specify whether the path is an absolute or relative path. The valid values for
this parameter are:
%FilePath_Relative (default)
%FilePath_Absolute
If you don’t specify pathtype the default is %FilePath_Relative.
If the path is an absolute path, whatever path you specify is used verbatim.
You must specify a drive letter as well as the complete path. You can’t use
any wildcards when specifying a path.
The function automatically converts platform-specific separator characters
to the appropriate form for where your PeopleCode program is executing.
On a WIN32 system, UNIX "/" separators are converted to "\", and on a
UNIX system, WIN32 "\" separators are converted to "/".

Returns
A file object.

&FILE1 = GetFile("C:\temp\a1.txt", "r", "a", %FilePath_Absolute);


&LOGFILE = GetFile("C:\temp\a1.txt.err", "W", %FilePath_Absolute);

SetFileLayout
The SetFileLayout methods associates the specific file layout definition with a file
object. It associates a specific file layout definition with the file object executing this
method, providing easy access to rowset data. The file object must be associated
with an open file. With file layout definitions, you can read and write rowsets as
easily as strings. If the file object isn’t open or the definition doesn’t exist,
SetFileLayout fails.

Page 76 of 84
You must execute SetFileLayout before you can use any other file layout methods or
properties with a file object, otherwise those methods and properties return NULL or
False.

Note. All provided PeopleTools records that have a prefix of PSFLD are related to file
layout definitions.

Parameters
filelayoutname Specify as a string the name of an existing file layout definition
created in PeopleSoft Application Designer.
Returns
A Boolean value: True if the method succeeds, False otherwise.

Example
&FILE1.SetFileLayout(FileLayout.S1_TEST);
&LOGFILE.SetFileLayout(FileLayout.S1_TEST);

ReadRowSet
To import data, a rowset is created for the record and the ReadRowset method is
used to populate the rowset with one transaction from the file record, plus all of its
subordinate data

The ReadRowset method is a file layout method. It instantiates a PeopleCode rowset


object based on the file layout definition. It then populates the rowset with one
transaction from the file. A transaction is treated as one instance of level-0 data
contained in a file record, plus all of its subordinate data.

When ReadRowset is executed, it moves the starting point for the next read
operation to the beginning of the next rowset so that each transaction in the file can
be read in turn by subsequent ReadRowset operations. When no more data remains
to be read from the file, ReadRowset returns NULL.
&RS1 = &FILE1.CreateRowset();
&RS = CreateRowset(Record.S1_VENDOR);
&SQL1 = CreateSQL("%Insert(:1)");
&RS1 = &FILE1.ReadRowset();
While &RS1 <> Null;
ImportSegment(&RS1, &RS);
&RS1 = &FILE1.ReadRowset();

Page 77 of 84
End-While;

The diagram below shows the progression of data from flat files through a file layout
to the record definition.

Activity 7 – Importing a Fixed Format Flat file


In this activity, Students will be given a flat file which they will need to import using
the approach as outlined above into S1_VENDOR record.

Writing Data to Flat Files

Methods to read and write to plain text file


Following methods of File class are used to read from and write to plain text files
using strings.

Page 78 of 84
• Readline (string)
• WriteLine (string)
• WriteString (string)

The following program reads a plain text file from in.txt and writes it back out to
out.txt.

Local File &File1,&File2;


Local String &Str;
&File1 = GetFile(“in.txt”, “R”);
&File2 = GetFile(“C:\temp\out.txt”, “W”, %FilePath_Absolute);
While &File1.ReadLine(&Str);
&File2.WriteLine(&Str);
End-While;
&File1.Close();
&File2.Close();

Writing to Files Defined by a File Layout


Use the following methods to write to files defined by a file layout definition:
• WriteRecord(record)
• WriteRowset(rowset)

WriteRecord
Syntax
WriteRecord(record)

Description

The WriteRecord method is a file layout method. It writes the contents of the record
object record, to the output file. (Remember, a record object contains only one row
of data from an SQL table.)

Page 79 of 84
You can use this method to build a transaction in the output file, one file record at a
time, without having to instantiate and populate a rowset object. You can apply this
method to any record whose structure and name matches that of a record defined in
the current file layout.

Note. You must execute the SetFileId method from the file object before using
WriteRecord, otherwise it returns False.

Note. When you're writing text to an XML file, special HTML characters, such as
ampersands, lesser than or greater than symbols, and so on, are automatically
converted to valid XML character string, such as &amp.

Parameters
record Specify the name of an existing record object to be written. You can use
Rowset class methods such as GetField and built-in functions such as
GetRecord to populate the record with data before writing it to the file.

Returns
A Boolean value: True if the method succeeds, False otherwise. This value is
optional.

Example
The following example appends all the data in a record to an existing file:

Local File &MYFILE;

&MYFILE = GetFile("record.txt", "A");

If &MYFILE.IsOpen Then
If &MYFILE.SetFileLayout(FILELAYOUT.VOL_TEST) Then
&LN = CreateRecord(RECORD.VOLNTER_ORG_TBL);
&SQL2 = CreateSQL("%Selectall(:1)", &LN);
While &SQL2.Fetch(&LN)
&MYFILE.WriteRecord(&LN);
End-While;
Else
/* do error processing - filelayout not correct */
End-If;
Else
/* do error processing -; file not open */

Page 80 of 84
End-If;

&MYFILE.Close();

WriteRowset
Syntax
WriteRowset(rowset [, Write_Data])

Description
The WriteRowset method is a file layout method. It writes the contents of a rowset
object, rowset, to the output file associated with the file object executing this
method. Regardless of whether the rowset contains just one or more than one
transaction (level zero row), executing this method once writes the entire contents of
the rowset to the output file.
Note. You must execute the SetFileLayout method from the file object before using
WriteRowset, otherwise it returns False.

WriteRowset writes a rowset to a file only if the data in the component buffer has
changed. You must specify the WriteData parameter as True if you want the
WriteRowset method to force the rowset to be written to the file even if the buffer
has not been changed.

Considerations Using Fixed Length Files With Numeric Fields


All numeric fields are right-justified in when writing to fixed length files. In addition,
zeros are padded to the right after the decimal point if required.

Parameters
rowset Specify the name of an existing rowset object that was instantiated with
the File class CreateRowset or ReadRowset method. You can use Rowset
class methods such as Select and built-in functions such as GetLevel0 to
populate the rowset with data before writing it to the file.
WriteData Specify whether to write the rowset data to the file whether or not the
data in the buffer has changed. This parameter takes a Boolean value:

Page 81 of 84
True, write the data to the buffer regardless, False, only write the data if
changed. The default value for this parameter is False.

Returns
A Boolean value: True if the method succeeds, False otherwise.

Example
Local File &MYFILE;
Local Rowset &FILEROWSET;

&MYFILE = GetFile("c:\temp\EMP_CKLS.txt", "A", %FilePath_Absolute);


If &MYFILE.IsOpen Then
If &MYFILE.SetFileLayout(FILELAYOUT.EMPL_CHECKLIST) Then
&FILEROWSET = &MYFILE.CreateRowset();
&FILEROWSET = GetLevel0();
&MYFILE.WriteRowset(&FILEROWSET, True);
Else
/* file layout not found, do error processing */
End-If;
Else
/* file not opened, do error processing */
End-if;

&MYFILE.Close();

CreateSQL Function
The CreateSQL function instantiates a SQL object from the SQL class and opens it on
the given sqlstring and input values. The sqlstring parameter is a PeopleCode string
value that provides the SQL statement.

Any errors in the SQL processing cause the PeopleCode program to be terminated
with an error message.

SelectAll Syntax
The SelectAll function uses the following syntax:
%SelectAll(:num [ correlation _id] )

%SelectAll is shorthand for selecting all fields in the specified record, wrapping
DateTime fields with %DateOut, %TimeOut, and so on.

The pseudocode looks like this:

Page 82 of 84
Select (All Fields, :num correlation_id) from %Table(:num) prefix

This shortcut is only appropriate if the statement is being used in PeopleCode or


PeopleSoft Application Engine to read data into memory. Dynamic views should
retain the internal database formats for DateTime fields.

Page 83 of 84
Activity 8 – Writing data to flat file
In this activity, you will create an Application Engine program to write data from the
S1_COMPANY table to a flat sequential file. After the write was successful, modify
the file layout to write the file in Microsoft Excel format.

Activity 9 – Data import using File Layout, CI and AE


In this activity, we will revisit Activity 7 where we used an AE and File layout to write
data directly to a table. We saw that the edit check can be executed. But there is still
an issue in terms of the fact that all the code and workflow that may exist in Vendor
table will not be executed by this import. Accordingly, we will now modify the AE so
that data is not written directly to the table using SQL. Rather we will read data
using a file layout and load the data into S1_VENDOR table by using a Component
Interface that was designed earlier.

Page 84 of 84

You might also like