I'm a PeopleSoft developer working on an application that will subscribe
selected data changes from our Novell eDirectory into Peoplesoft, using
Novell's Identity Manager Driver (5.0) for PeopleSoft. So I apologize up
front for the amount of PeopleSoft-specific content in this post -- but I
promise there are some driver-general questions in it, hopefully you can
find them buried under the PSoft example information. ;->

The Novell documentation has been very helpful, esp. in conjunction with
the delivered sample application that I installed in our development
instance; and I am adhering as closely as possible to the architecture of
the sample project, using Novell's "PSA Best Practices" recommendations, etc.

Among those recommendations are the following bullet points:

-- It is important to generate transactions whenever the application
data table records are created or updated, even if the changes are made by
the driver.

-- Do not generate Transaction records until after you have
successfully updated the application tables.

Novell applies these recommendations in the sample project, which
demonstrates transfer of subscribed data updates to the schema component,
which in turn (upon save) triggers some Psoft-internal code which resides
on the schema component's underlying staging record
(DIRXML_STAGE01.DIRXML_S_ID.SPo event, for any other PSoft developers
reading this). That code, in turn, instantiates a Component Interface
session object for the sample application target component, DIRXML_TST_PERS
(again, PSoft developers, you can think of Novell's DIRXML_TST_PERS
component as functionally equivalent to, say, the BIO_DEMO_PERSF component,
although structurally less complex).

Despite its relative simplicity, thankfully the sample app's
DIRXML_TST_PERS component does contain a child scroll level (for processing
phone data), so you can see first-hand how the sample application handles
writing to the transaction schema for updates of the level 0 data, the
level 1 data, or both. The record structure for this child scroll is also
very simple, basically just an ID field (cp. Emplid), a Phone Type field,
and a Phone field; the first two are keys.

What I find when doing updates via the sample staging C.I. in the test
harness (to simulate subscription changes) is:

1. an update to a level zero field item results in a single-row insert
into the transaction table, with a DIRXML_EVENT value of "M" (modify); this
is pretty intuitive. For anyone else with the sample project installed,
the code that makes this happen is on the DIRXML_S_PERS.DIRXML_S_ID.SPo
event; for everyone else, the relevant parts look like this (never mind
what the DirXML_Trans() function does, just understand that it results in a
write to the Transaction schema / table, and that the 4th argument is the
one that populates DIRXML_EVENT):

<<<<<<< begin ( [...paraphrases...] and /* comments */ mine )

[... logic to figure out if you're publishing or subscribing, and
populate &channel and &tValue accordingly; in this case we are subscribing...]

[... checks if you're in Add mode or not; we are not, so the following

DirXML_Trans("DIRXML_TRANS01", &channel, "DIRXML_SCHEMA01",
"M", DIRXML_S_ID, %Datetime, &tValue, "", "", "A");

<<<<< end >>>>>>>>

2. an update to a single level 1 field item, on the other hand, results in
not one, but two rows being inserted to the transaction table. One of the
rows has DIRXML_EVENT value of "M", but the other has a value of "R" --
which indicates a "Row Delete".


Here is how that code works in this context (i.e. subscribing, not in Add
mode). It is on the DIRXML_S_PHONES.DIRXML_S_ID.SPo event:

<<<<<<< begin ( [...paraphrases...] and /* comments */ mine )

[... logic to figure out if you're publishing or subscribing, and
populate &tValue accordingly; we are subscribing...]

[... checks if you're in Add mode or not; we are not....]

If (FieldChanged(DIRXML_S_PHONETYPE) Or FieldChanged(DIRXML_S_PHONE)) Then

&FieldKey =

If &FieldKey <> "" Then

/* as I understand it, (&FieldKey <> "") will be true any time you're
updating PhoneType or Phone for a row with a prior value */

DirXML_Trans("DIRXML_TRANS01", &channel, "DIRXML_SCHEMA01",
"R", DIRXML_S_ID, %Datetime - 1, &tValue, "Phones", &FieldKey, "A");

/* ... so the above is causing the row with the "R" value (= RowDelete)
to be written to the Transaction table... */


If &FieldKey = "" Then



/* now note that this call to DIRXML_Trans() is not conditional on the
value of &FieldKey, so it will always execute, whether the call above did
or not... */

DirXML_Trans("DIRXML_TRANS01", &channel, "DIRXML_SCHEMA01", "M",
DIRXML_S_ID, %Datetime, &tValue, "Phones", &FieldKey, "A");


<<<<< end >>>>>>>>

So my questions are essentially the following:

a) Is this a mistake in the sample app, or is this actually how the driver
wants to see child-scroll updates handled, i.e. as a row delete followed by
a modification?

b) If it is intentional, bonus points if you can explain to me why? <g>

c) I'm unclear about the degree of granularity desired for recording
successful subscription transactions.

As discussed above, the sample app inserts a row for any field change at
level zero, and it inserts two rows (one "M", one "R") for any fieldchange
at the level 1 scroll... or is it more appropriate to say "for any
fieldchange for a given collection", in which case I should code a
subscription transaction insert (or two, if the way the sample code works
is correct) for each collection that has any of its data updated?

I ask this because the sample app only has one Collection defined (the
phones data) for its C.I. so "collection" and "level 1 scroll" are
essentially interchangeable in the sample app. But my target C.I. (based
on BIO_DEMO_PERSF) has five separate collections at level 1. So should I
code calls to DirXML_Trans() on each of the collections' primary record
updates, or just use one for the entire scroll level?

d) Given that I'm not (currently) publishing to the eDirectory, only
subscribing from it... what the heck does the driver want with the
"successful subscription" transaction rows anyway? I can see why it might
want one to acknowledge that something finished at our end. But given that
the staging schema is "flat", yet (depending on the specific staging schema
items being processed) an update to it will involve from one to several
PSoft application table updates, how does the driver handle the variable #
of transaction rows that appear to be the result of setting this up in
accordance with the sample application?

In other words, it seems to me that the driver has no way of knowing
whether it happened to update a staging (schema) field that will ultimately
trigger a PSoft-internal update to an application table level 0 data item
(and hence generate a single "M" row to the transaction table), or if it
updated a field (e.g. phone # in the example above) that will result in two
rows (one "M", one "R"). Or maybe it updated one of each (3 rows now).
Or, in my case, if it updates fields across multiple collections, it might
get several more rows back.

Thanks in advance to anyone who is willing to share their knowledge &
experience working with these drivers.