This chapter provides an overview of the synchronization server and the SyncServer classes and discusses the following topics:
Understanding the synchronization server events and SyncServer classes
Using synchronization server events
Using attachment events
Scope of a SyncServer object
SyncServer reference
Advanced considerations for synchronization
PeopleSoft Mobile Agent extends the functionality of PeopleSoft Pure Internet Architecture to disconnected mobile devices, allowing users to continue working with their PeopleSoft applications on a laptop computer or personal digital assistant (PDA) while disconnected from the internet or local network.
The mobile events control the PeopleCode programs used with the mobile device. This PeopleCode uses the mobile classes to control the changes an end user makes to the mobile data.
See Enterprise PeopleTools 8.46 PeopleBook: PeopleSoft Mobile Agent.
The synchronization server events control the synchronization of mobile data with the PeopleSoft database. The SyncServer class methods and properties are used for data selection and validation during synchronization.
When the mobile device is synchronized with the PeopleSoft database, the following events occur on the synchronization server. All of these events only fire when any PeopleCode is associated with the event.
Event Name |
Description |
OnConflict |
This event only occurs when the conflict resolution for the synchronizable component interface is selected as Custom on the properties dialog box for the definition, on the Synchronization tab. |
OnGetDefinition |
This event is used for defining Component Interface objects accessed only by a PeopleCode reference. |
OnSelect |
This event is used for specifying what data should be downloaded (distributed) to the mobile device. |
OnValidate |
Occurs when any PeopleCode is associated with the event and no PeopleCode is associated with the OnValidateSet event. This event is only used for data validation of a medium to large number of objects. |
OnValidateSet |
This event is used for data validation of a very large number of objects. |
In addition, if you create references in the synchronizable Component Interface to be used with attachments, the following events are also available:
Event Name |
Description |
OnGetProperty |
This event is used to specify how attachments are accessed and sent to the mobile device. |
OnGetPropertyFilter |
Occurs before the OnGetProperty event. This event is used for specifying filter rules to an individual attachment. |
OnSetProperty |
Occurs when the value of an attachment has changed on the mobile device. This event can is to specify which attachments are synchronized from the mobile device to the PeopleSoft database. |
Many of the SyncServer class methods and properties are only valid in specific events. The following table lists the event restrictions for the methods and properties. If a method or property is not listed, it does not have restrictions about which event it can be used in.
Method or Property |
Valid Events |
AddReference |
Only valid in the PreBuild, PostBuild, and RowInit events. |
AddReferenceType |
Only valid in the OnGetDefinition event. |
CheckForChanges |
No restrictions, but generally used in the OnSelect event. |
SelectAll |
No restrictions, but generally used in the OnSelect event. |
ConflictAlgorithm |
This property is checked after any PeopleCode in the OnConflict event has run. |
ConflictStatus |
Only valid in the ConflictStatus event. |
ExcludeProperty |
No event restrictions, but only used with attachments. |
ExportLocation |
Only valid in the OnGetProperty event. |
LastSyncDateTime |
Only valid in the OnSelect event. |
LastSyncRowCount |
Only valid in the OnSelect event. |
PropertyValue |
Only valid in the OnGetProperty and OnSetProperty events. |
SessionID |
Only valid in the OnValidateSet event. |
SyncIDs |
Only valid in the OnSelect event. |
TypeID |
Only valid in the OnValidateSet event. |
validateID |
Only valid in the OnValidate event. |
validateRowCount |
Only valid in the OnValidate event. |
validateVersion |
Only valid in the OnValidate event. |
See Also
Using the Synchronization Server Events
During synchronization, use the %SyncServer system variable to instantiate and populate a SyncServer object. You can then use this object in one of the synchronization events to specify the details of the current synchronization.
The %SyncServer variable is ignored outside of the synchronization server events, or events called by the synchronization server.
PeopleSoft recommends using the Synchronizing property in events outside of the synchronization server events to separate code that should only be executed during synchronization. For example, suppose you had additional business logic to apply to data coming from a mobile device. You could put the following in one of the Component events that gets called during synchronization, such as SavePreChange.
If %SyncServer.Synchronizing Then /* more data rules here */ End-If;
The synchronization events are not required for synchronizing a mobile device. You should only start using the SyncServer class methods and properties in the events after your mobile application is running. The following is the typical development cycle for synchronization:
Create and test your component.
If you are using an existing component, you must still test it to verify that it runs without errors and returns the data you are expecting.
Create and test your Component Interface.
If you are using an existing Component Interface, you must still test it to verify that it runs without errors and returns the data you are expecting.
Create and test your mobile pages.
Once your Component Interface is running, then and only then should you make the Component Interface synchronizable and build mobile pages based on it.
Note. Remember that any changes made to the underlying Component Interface are not automatically reflected in any mobile pages built from that Component Interface.
At this point, you should verify whether the search page associated with the component returns the data you need for your mobile application. If it does, and if you are not dealing with a large number of instances of the Component Interface that need to be synchronized, you are finished. There is no need to go any further and create PeopleCode for synchronization.
Refine the conflict resolution for your mobile application.
The properties for the synchronizable Component Interface specify which version of the data should be used if there is a conflict (device always wins, database always wins, and so on.) Use the OnConflict event to refine the conflict rules if necessary.
Refine the data used with your mobile application.
If the search record associated with the component is not adequate for returning the data you need for your mobile application, create PeopleCode associated with the OnSelect event to better define the data for your mobile device.
Note. Remember, this event fires when any PeopleCode is associated with the event, even if the PeopleCode program is commented out.
Fine tune your mobile application.
If your mobile application requires a medium to large number of objects, between 100–1000 instances of a Component Interface, you can use the OnValidate event to possibly enhance synchronization performance.
If your mobile applications requires a large number of objects, over 1000 instances of a Component Interface, you can use the OnValidateSet event to possibly enhance synchronization performance.
If you need to create references to Component Interface objects in PeopleCode, without defining the relationship in Application Designer, you can use the OnGetDefinition event.
PeopleSoft Mobile includes synchronization server events to support mobile device synchronization and data distribution. If a component interface is synchronizable, these events exist in its associated PeopleCode.
This section discusses how to use:
OnConflict
OnSelect
OnValidate
See Also
Optimization Built-in Functions
Advanced Considerations for Synchronization
The OnConflict event is invoked only when the conflict resolution for the synchronizable component interface is selected as Custom on the properties dialog box for the definition, on the Synchronization tab, and a conflict has occurred.
Property conflicts are generated when the property changed on both the server and the device, and the property value on the server is different than the property value on the device.
OnConflict PeopleCode is run for each conflict to decide whether the device update is accepted or rejected. The OnConflict PeopleCode attached to the level zero object of the Component Interface, if any, is always run after all other OnConflict PeopleCode has run. OnConflict PeopleCode can set the ConflictStatus property on the SyncServer object to %CONFLICTSTATUS_ NOCONFLICT, which causes the conflict to be ignored.
OnConflict PeopleCode can set the ConflictAlgorithm property on the SyncServer object to %CONFLICTALGORITHM_SERVERWINS or %CONFLICTALGORITHM_DEVICEWINS, which causes the device update to be rejected or accepted.
The ConflictAlgorithm property is checked after all OnConflict PeopleCode has run. The ConflictAlgorithm property overrides the ConflictStatus property. If the ConflictAlgorithm property is not set and if the ConflictStatus property is set to %CONFLICTSTATUS_NOCONFLICT for all of the conflicts, the device update is accepted, otherwise the device update is rejected.
Note. If a PeopleCode program exists in OnConflict but is commented out, the synchronization server ignores the associated conflict (that is, behaves as if it were resolved.) This may result in changes being applied to the server database that may be in error.
OnConflict PeopleCode Example: CONFLICTALGORITHM
In this example, if the mobile device is a personal digital assistant (PDA), this code causes changes on the mobile device to always be accepted.
If (%SyncServer.ClientPlatform = %MobileDevice_PDA) Then %SyncServer.ConflictAlgorithm = %CONFLICTALGORITHM_DEVICEWINS; End-If;
In this example, the program causes the property values from the mobile device owning the property to take precedence.
Function isOwner() Returns boolean Local boolean &bOwner; /* Use user profile information to determine if the sync user is the owner of this synchronized Component Interface object... */ Return &bOwner; End-Function; If (isOwner()) Then /* No conflict, always accept changes from the owner's device during synchronization... */ %SyncServer.ConflictAlgorithm = %CONFLICTALGORITHM_DEVICEWINS; Else /* Reject changes from non-owners when a conflicts occur... */ %SyncServer.ConflictAlgorithm = %CONFLICTALGORITHM_SERVERWINS; End-If;
Understanding the Merge Algorithm
The merge algorithm is used when the conflict resolution for the synchronizable component interface is selected as Device Winsor Custom on the properties dialog box for the definition, on the Synchronization tab.
When you select Custom, the merge algorithm is executed before the OnConflict PeopleCode is run. While it is possible for the OnConflict PeopleCode to change the outcome of the merge algorithm, it should not do so. The purpose of OnConflict PeopleCode is to decide whether the device update is accepted or rejected.
The following are the merge algorithm rules:
Property values changed on the device replace property values on the server.
Property values changed on the server and not on the device are left equal to the server values.
Objects added on the server are left in place. Objects added on the device are added on the server.
See Also
The OnSelect event is invoked during synchronization to implement custom data distribution.
To determine which data to send to the mobile device during synchronization, the synchronization server searches for the results of the OnSelect event as it is defined for each Component Interface. In the Component Interface, you can develop PeopleCode in the OnSelect event to select the record rows based on filtering, such as the mobile device owner, person logged in, sales region, and so on.
The OnSelect event uses the SyncServer class property SyncIDs, which is an array of synchronization Ids (from the SYNCID field.)
Using a SQL statement, select the SYNCID field for each row or instance of data to be synchronized, and pass this array of SYNCIDs in the SyncIDsproperty array to the synchronization server for retrieval. The OnSelect event runs only if the Component Interface has a corresponding mobile page on the mobile device.
If the OnSelect event definition contains no PeopleCode, the default search record for the component interface is used to return an unfiltered array of Sync Ids. All data that satisfies the search record for the component interface is synchronized to the mobile device.
If a PeopleCode program exists in OnSelect but is commented out, the PeopleCode is not invoked and nothing is pushed into the SyncIDs array. However, because a PeopleCode program exists, the synchronization server assumes that the SyncIDs array is correctly populated with no SyncID values.
If PeopleCode exists within the OnSelect event definition, the PeopleCode is run and the resulting set of synchronization Ids is used to determine which data is returned to the mobile device. You can define PeopleCode functions containing data distribution rules for reuse or write code that is specific to each Component Interface.
Using the Common Component Function DistributeDataByRules
This function, contained in the FuncLib FUNCLIB_ECMOBIL, can be used in the OnSelect event to filter data to the mobile device.
OnSelect PeopleCode Examples
In this example, the following PeopleCode on an OnSelect event populates the SyncIDs array with all of the sync Ids from the record rows that have an active lead status (LEAD_STATUS), which is a component interface property. This could be used to supply each salesperson with only the leads that are assigned to that salesperson.
/* Select Active Leads */ &sql = CreateSQL("SELECT SYNCID FROM PS_RSF_LEAD WHERE LEAD_STATUS = :1", 'A'); While &sql.Fetch(&SyncID) %SyncServer.SyncIDs.Push(&SyncID); End-While;
In the following example, the system variable %UserId associates an end user with the PERSON_ID field in the record row. The PeopleCode for the OnSelect event selects all of the synchronization Ids (and associated record rows) that are owned by that user.
/* Determine User's Person ID */ SQLExec("SELECT PERSON_ID FROM PSOPRALIAS WHERE OPRID = :1", %UserId, &PersonID); /* Select Leads with the User's Person ID */ &sql = CreateSQL("SELECT SYNCID FROM PS_RSF_LEAD WHERE PERSON_ID = :1", &PersonID); While &sql.Fetch(&SyncID) %SyncServer.SyncIDs.Push(&SyncID); End-While;
Through spidering, rows of data can be required for the mobile device in addition to those selected by the OnSelect event. Suppose that:
A contact list on a mobile device includes three people: two from the USA states of California and Illinois and one from the Canadian province of Quebec.
The OnSelect event for state calls for only states or provinces that are in the USA.
The synchronization server retrieves all of the USA states, including California and Illinois, but it also retrieves Quebec because Quebec is already present on the mobile device.
See Also
The OnValidate event is invoked during out-of-date detection during full synchronization. Use it only when you have medium to large set of data, approximately 100–1000 instances of a Component Interface.
Generally, when a Component Interface instance is accessed for synchronization, the Compoent Interface keys are set and the Get method is called on the Component Interface. If you use OnValidate (or OnValidateSet), this call to the Get method is bypassed. This means that the normal initialization events associated with a Compoent Interface (PreBuild, RowInit, and so are) are also bypassed. This can improve performance. This implies that you may want to use OnValidate (or OnValidateSet) if the performance cost of doing the Get (and running the other events) is greater than running SQL to compute the current version of the instance.
Note. OnValidate is not invoked during upload changes or bootstrap synchronization. It is only invoked during update applications and update business data synchronization.
Use the OnValidate event to compute the current version for the synchronized Component Interface object using the SyncServer validateID property, and return the result to the synchronization server using the SyncServer validateVersion property.
If the Component Interface instance does not exist or is not relevant for some other reason (for example, security), not setting a value into version is interpreted as a validate status of No Relevance and the mobile object is removed from the mobile device.
Use the OnValidate event to get the current version for the object and either set that object to be relevant or remove it from the mobile device.
The OnValidate event uses the SyncServer properties validateID and validateVersion.
Considerations Using OnValidate
If you create PeopleCode for this event, you must maintain it. Anytime you expose an additional collection in the Component Interface, or remove a collection, you must change your OnValidate PeopleCode.
If you have any PeopleCode in the OnValidateSet event, even if it is commented out, the OnValidate event does not run.
OnValidate runs on every instance of the Component Interface. This means that any code in this event fires once per Component Interface instance.
OnValidate PeopleCode Example
The following PeopleCode sets validation for this instance of the QE_DEMO_CONTACT component interface.
SQLExec("SELECT LASTUPDDTTM FROM %Table(QE_DEMO_CONTACT) WHERE SYNCID=:1", %SyncServer.validateID, %SyncServer.validateVersion);
See Also
PeopleTools supports attachments for mobile. The attachment consists of header information (such as size, type, description) and the corresponding document object. The attachment events occur when the mobile user synchronizes the mobile device.
The synchronization server invokes the OnGetProperty event when the value for the attachment property is requested. The specific implementation of this event is defined by the developer, and based on the application requirements. It can be used to specify which attachments are downloaded to the mobile device.
The following is a sample of PeopleCode that could be used in the OnGetProperty event. In the example, the PropertyValue property is used in the GetAttachment function to specify the filename and location of the attachment file on the synchronization server.
If QE_MB_CUST_NEED.FTPSITE <> "" And QE_MB_CUST_NEED.ATTACHSYSFILENAME <> "" Then %SyncServer.PropertyValue = "c:\PSMobile_FileAttach\" | QE_MB_CUST_NEED.ATTACHSYSFILENAME; &Result = GetAttachment(QE_MB_CUST_NEED.FTPSITE, QE_MB_CUST_NEED.ATTACHSYSFILENAME, %SyncServer.PropertyValue); End-If;
The synchronization server invokes the OnGetPropertyFilter event prior to invoking the OnGetProperty event to allow the application to apply filtering rules to an individual attachment.
If the SyncServer ExcludeProperty property is set to True, the synchronization server only sends the header of the attachment to the mobile device. It does not send the contents of the attachment.
Here is a sample of PeopleCode that could be used in the OnGetPropertyFilter event.
If ((%SyncServer.ClientPlatform = %MobileDevice_PDA) And (SERVICEORDER_DAMAGEDPART.SIZE > &nMaxAttachmentSize)) Then %SyncServer.ExcludeProperty = True; End-If;
The synchronization server invokes the OnSetProperty event when the value for the attachment is modified. The specific implementation of this event is based on application requirements. It can be used to specify whether the attachment is uploaded from the mobile device.
Here is a sample of PeopleCode that could be used in the OnSetProperty event. The PutAttachment function returns the location of the attachment file in PropertyValue.
If QE_MB_CUST_NEED.FTPSITE <> "" And QE_MB_CUST_NEED.ATTACHSYSFILENAME <> "" Then &Result = PutAttachment(QE_MB_CUST_NEED.FTPSITE, QE_MB_CUST_NEED.ATTACHSYSFILENAME, %SyncServer.PropertyValue); End-If;
Use the CheckForChanges method along with the LastSyncTime and LastSyncRowCount properties to specify whether the component interfaces on the devices are updated. You would use this ability if your component interfaces are relatively static, meaning that no changes will have occurred to that component interface data during most full synchronization operations.
A filter attribute indicates whether a component interface is to be synchronized or not. When the mobile device receives the response, if a full synchronization is in progress, the device looks for the presence of the filter attribute. If it is present, and the value is true, subsequent processing of the component interface is streamlined.
The filtered synchronization processing occurs as follows:
If a reference list of SyncIDs is present in the response, the synchronization server constructs lists of existing, new and deleted objects. The list of existing objects is ignored. No validate or get requests are issued for these objects. New objects are retrieved from the server, and deleted objects are removed from the device.
If the select response contains no reference list of SyncIDs, or if all SyncIDs are found to exist on the device, no other processing occurs for that component interface.
When a component interface is not filtered, the mobile device saves the timestamp and row count information once the processing for that component interface is complete. All component interface objects retain the timestamp and row count from the last time they were fully synchronized.
See Also
A SyncServer object can only be instantiated as Local. SyncServer objects are declared using the SyncServer data type. For example:
Local SyncServer &MySyncServer;
You can also declare and set the SyncServer variable in the same line. For example:
Local SyncServer &MySyncServer = %SyncServer;
The SyncServer object is accessed using the %SyncServer system variable.
This section describes the SyncServer class methods.
Syntax
AddReference(SyncID[, CIDefnName])
Description
Use the AddReference method to identify every instance of an ad-hoc referenced component interface that you identified using the AddReferenceType method. Use AddReference in one of the Component build events (PreBuild, PostBuild, RowInit).
Parameters
SyncID |
This is a string containing the synchronization ID (SyncID). |
CIDefnName |
This is a string containing the name of the referenced Component Interface. Preface this string with the reserved word CompIntfc. |
Returns
None.
Example
%SyncServer.AddReference(&SyncID, CompIntfc.RefCI);
See Also
Advanced Considerations for Synchronization
Syntax
AddReferenceType(CIDefnName)
Description
Use the AddReferenceType method in the OnGetDefinition event to identify every ad-hoc reference component interfaces. You must have one call for every instance of an an-hoc Component Interface type in the current component interface.
Parameters
CIDefnName |
This is a string containing the name of the referenced Component Interface. Prefix this string with the reserved word CompIntfc. |
Returns
None.
Example
%SyncServer.AddReferencedType(CompIntfc.RefCI);
Syntax
CheckForChanges(SyncDateTime, TotalRowCount[, HasRefList])
Description
Use the CheckForChanges method to determine if a component interface needs to be synchronized. This method determines the DateTime value of all rows that make up the object, as well as a total count of those rows. If the maximum DateTime value exceeds the device value or if the row counts are different, the component interface is identified as changed and the data in the component interface will be resynchronized.
If neither condition is true, an additional attribute is added to the result element of the response: filter="true".
Note. If you want to filter which component interface objects are updated, you should use CheckForChanges even during a bootstrap, in order to seed the RowCount setting on the device.
If there are rules to apply to the data, they must be applied whenever CheckForChanges returns false. They might also be applied when CheckForChanges returns true, especially if the data is sensitive and the relevance rules are likely to change.
Parameters
SyncDateTime |
Specify the date and time the object was last updated on the server (the maximum update DateTime across all rows that comprise the object), as a DateTime value. |
TotalRowCount |
Specify the number of rows in the object on the server, as a number. |
HasRefList |
Specify if the response must contain a reference list even when the component interface is being filtered. This parameter takes a Boolean value. The default value is false. If you specify true for the value, the relevance rules in the OnSelect event must always be applied, even when the CheckForChanges method returns True, to ensure that the rule or authorization changes take effect immediately. If the value of this parameter is false, and if CheckForChanges returns true (which means this component interface will not be processed), then no reference list is included in the response. This means the synchronization processor skips the get and delete processing of this component interface, and the device data is left as-is. |
Returns
A Boolean value: true, the device data is identical to the existing data and so the component interface should not be processed, false indicates that the data has changed and the component interface should be resynchronized.
Example
In the following example, the component interface is automatically filtered and no processing is done.
%SyncServer.CheckForChanges(%SyncServer.LastSyncTime, %SyncServer.LastSyncRowCount);
In this example, applying the relevance rules is complex and slow, and you only want to do it when changes have occurred, so the code includes false as the third parameter for CheckForChanges. This example code would go in an OnSelect event.
Local datetime &SyncDttm; Local number &RowCount; /* The following logic enables filtering based on whether any data has changed in the underlying table. */ SQLExec("SELECT MAX(SYNCDTTM), COUNT(*) FROM PS_LEVEL0", &SyncDttm, &RowCount); If %SyncServer.CheckForChanges(&SyncDttm, &RowCount, False) = False Then /* Add logic here to populate %SyncServer.SyncIDs based on relevance rules. */ /* code here */ End-If;
In the following example, the logic filters according to a customer defined synchronization frequency (in all days.) This type of code would go in the OnSelect event.
Local datetime &DateTime; Local number &SyncFrequency; If All(%SyncServer.LastSyncDateTime) Then /* Not bootstrap sync. Determine the DateTime when we should next perform a full sync. */ SQLExec("SELECT FREQUENCY FROM PS_SYNC_FREQ_TBL WHERE CINAME = :1", CompIntfc.MYCI, &SyncFrequency); &DateTime = AddToDateTime(%SyncServer.LastSyncDateTime, 0, 0, &SyncFrequency, 0, 0, 0); Else /* Bootstrap sync. Seed &DateTime so the if-condition below will be true. */ &DateTime = %Datetime; End-If; If &DateTime <= %Datetime Then /* Time for a full sync. No need to call CheckForChanges, because SyncServer will always use current date-time in the response, and the row count is irrelevant. */ Else /* Time to filter. Call CheckForChanges with request value to force it. */ %SyncServer.CheckForChanges(%SyncServer.LastSyncDateTime, 0); End-If; /* This CI has no relevance rules. Tell SyncServer to select all instances. */ %SyncServer.SelectAll();
See Also
LastSyncDateTime, LastSyncRowCount.
Syntax
SelectAll()
Description
Use the SelectAll method to perform the default select processing. If this method is called in an OnSelect event, all instances of the component interface are added to the reference list in the select response. This means that the SyncIDs array is ignored, even if it is not empty.
Warning! If the SelectAll method is not called in the OnSelect event, and if CheckForChanges does not suppress the reference list, the response has a reference list containing all elements of the SyncIDs array. If the array is empty, the reference list is also empty, therefore all instances of that component interface are removed from the device.
Parameters
None.
Returns
None.
See Also
This section describes the SyncServer class properties.
Description
This property specifies the type of mobile device.
Value |
Description |
%MobileDevice_PDA |
A PDA. |
%MobileDevice_Laptop |
A laptop computer. |
This property is read-write.
Description
This property is used to cause the device update to be rejected or accepted. This property is checked after all OnConflict PeopleCode has run. This property overrides the ConflictStatus property.
Value |
Description |
%CONFLICTALGORITHM_ SERVERWINS |
The server always wins, which causes the device update to be rejected. |
%CONFLICTALGORITHM_ DEVICEWINS |
The mobile device always wins, which causes the device update to be accepted. |
This property is read-write.
Description
This property sets the conflict status. This property is valid only with the OnConflict event.
Value |
Description |
%CONFLICTSTATUS_ NOCONFLICT |
Remove from the list of conflicts. |
%CONFLICTSTATUS_ CONFLICT |
Do not remove from the list of conflicts. |
This property is read-write.
Description
This property indicates to synchronization server that the contents of an attachment should not be downloaded to the mobile device. (The header is still downloaded.)
This property is only used with attachments.
This property is read-write.
Example
If ((%SyncServer.ClientPlatform = %MobileDevice_PDA) And (SERVICEORDER_DAMAGEDPART.SIZE > &nMaxAttachmentSize)) Then %SyncServer.ExcludeProperty = True; End-If;
Description
This property allows a developer to instruct the mobile device to export a copy of an attachment to a specific file on the device's disk during synchronization.
You can use this property to automatically extract product images (JPEGs) to a directory on the mobile device to make them accessible from HTML image tags included in HTML that is generated as part of an HTML Area.
This property takes a value of a relative or fully qualified path and filename. If you want to put files into the Res directory (all graphics must be in this directory to display correctly) you could use the following PeopleCode:
%SyncServer.ExportLocation = "..\res\filename.ext";
This property is used in the OnGetProperty event for an attachment reference file.
This property is read-write.
Description
This property returns the datetime from the last time this component interface was synchronized, as a DateTime value. This property is used only in the OnSelect event.
This property is read-only.
See Also
CheckForChanges, LastSyncRowCount.
Description
This property returns the number of rows that were available in this component interface the last time it was synchronized, as a number. This property is used only in the OnSelect event.
This property is read-only.
See Also
LastSyncDateTime, CheckForChanges.
Description
This property provides the path and filename of the attachment file on the synchronization server. It is used with the GetAttachment and PutAttachment functions.
In the OnGetProperty event, set PropertyValue in the GetAttachment function to the filename and location of the attachment file.
In the OnSetProperty event, the PutAttachment function returns the location of the attachment file in PropertyValue.
This property is read-write.
Example
In the code example below, the second If statement checks for whether the attachment was successfully retrieved, prior to setting the value for PropertyValue.
If QE_MB_CUST_NEED.FTPSITE <> "" And QE_MB_CUST_NEED.ATTACHSYSFILENAME <> "" Then %SyncServer.PropertyValue = "c:\PSMobile_FileAttach\" | QE_MB_CUST_NEED.ATTACHSYSFILENAME; &Result = GetAttachment(QE_MB_CUST_NEED.FTPSITE, QE_MB_CUST_NEED.ATTACHSYSFILENAME, %SyncServer.PropertyValue); End-If;
Description
This property returns the session ID. This is not unique for a device. It is used for internal chunking in OnValidateSet, and can only be used with this event.
This property is read-only.
See Also
Example
The following PeopleCode sets validation for batches of instances of the QE_DEMO_CONTACT Component Interface.
SQLExec("UPDATE PSSYNCSERVERVAL SET SYNCSTATUS=0 FROM PSSYNCSERVERVAL A, %Table(QE_DEMO_CONTACT) B WHERE A.SYNCSESSIONID = :1 AND A.SYNCTYPEID = :2 AND (A.SYNCID = B.SYNCID AND A.SYNCDTTM >= B.LASTUPDDTTM)", %SyncServer.SessionID, %SyncServer.TypeID); SQLExec("UPDATE PSSYNCSERVERVAL SET SYNCSTATUS=1 FROM PSSYNCSERVERVAL A, %Table(QE_DEMO_CONTACT) B WHERE A.SYNCSESSIONID = :1 AND A.SYNCTYPEID = :2 AND (A.SYNCID = B.SYNCID AND A.SYNCDTTM < B.LASTUPDDTTM)', %SyncServer.SessionID, %SyncServer.TypeID);
Description
This property is true during synchronization and false otherwise. Use this to perform (or omit) tasks during synchronization. For example, you might limit the number of rows processed in a child scroll during synchronization.
This property is read-only.
Description
This property is an array containing the synchronization Ids. Populate the SyncIDs array with the sync Ids of the synchronizable component interface objects that you want to be synchronized with the mobile objects on the mobile device. Use the array class Push method to add a SyncID to the SyncIDs array.
The SyncID array is used as a list of sync Ids for instances that satisfy a set of relevance criteria, such as only synchronize Customer objects that are associated to one salesperson. A SQL object that runs a select on a view might be used to calculate the set of sync Ids for Customer objects that are assigned to that salesperson.
This property can be used only with the OnSelect event.
This property is read-write.
See Also
Description
This property contains the sync ID for the current component interface type (not just an instance, but the entire type.) This property is used for internal chunking in OnValidateSet, and can only be used with this event.
This property is read-only.
Example
The following PeopleCode sets validation for batches of instances of the QE_DEMO_CONTACT component interface.
SQLExec("UPDATE PSSYNCSERVERVAL SET SYNCSTATUS=0 FROM PSSYNCSERVERVAL A, %Table(QE_DEMO_CONTACT) B WHERE A.SYNCSESSIONID = :1 AND A.SYNCTYPEID = :2 AND (A.SYNCID = B.SYNCID AND A.SYNCDTTM >= B.LASTUPDDTTM)", %SyncServer.SessionID, %SyncServer.TypeID); SQLExec("UPDATE PSSYNCSERVERVAL SET SYNCSTATUS=1 FROM PSSYNCSERVERVAL A, %Table(QE_DEMO_CONTACT) B WHERE A.SYNCSESSIONID = :1 AND A.SYNCTYPEID = :2 AND (A.SYNCID = B.SYNCID AND A.SYNCDTTM < B.LASTUPDDTTM)', %SyncServer.SessionID, %SyncServer.TypeID);
See Also
Description
This property contains the sync ID for the only current instance of the Component Interface. It is created using the SYNCID field for that component interface (that field is set in the record properties for that Component Interface.)
This property can be used only with the OnValidate event.
This property is read-write.
Description
This property returns the total number of rows in a hierarchical synchronizable Component Interface object.
For example, a service order with 10 lines has a validateRowCount value of 11. The property default is 1.
This property can be used only with the OnValidate event.
This property is read-write.
Description
This property contains the version for the instance of the Component Interface. Set validateVersion using the SYNCDTTM field. If the component interface object does not exist, or if the object is not to be used for some other reason (such as security), then do not set the validateVersion property.
This property can be used only with the OnValidate event.
ValidateVersion is initially set to the device version (that is, max(syncdttm) across all rows that make up the object). When leaving OnValidate, ValidateVersion must be reset to reflect the current version of the object.
If you want the object removed from the device, don't set the validateVersion property.
This property is read-write.
Example
The following code example forces an object to be re-synched:
%SyncServer.ValidateVersion = %CurrentDateTime;
If you know the object hasn't changed and want to keep it from being re-synced, use the following code (assuming the VersionRowCount property has also been set correctly):
%SyncServer.ValidateVersion = %SyncServer.ValidateVersion;
After you mobile application is running without errors, you might decide to further tune your application. Two events enable you to do this in specific circumstances.
This section discusses the following:
Using OnValidateSet
Using OnGetDefinition
You should only use OnValidateSet when you have a large number of Component Interface instances to be synchronized, more than 1000.
Before you try to create an OnValidateSet PeopleCode program, you should first create OnValidate PeopleCode. This enables you to determine the shape of the Component Interface instance, the number of child rows and collections. Having a thorough understanding of this helps you create the OnValidateSet PeopleCode.
Though the OnValidateSet PeopleCode may improve performance, there is additional maintenance with it. Every time you add an exposed collection, or remove one, you must change your PeopleCode program to reflect the new data structure.
Note. If you have any PeopleCode in OnValidateSet, including a program that has been commented out, the OnValidate event does not run.
When this event occurs, a table on the synchronization server (PSSYNCSERVERAL) is populated with all of the synchronization Ids for the component type. They table is keyed by Session ID (SYNCSESSIONID field) and Type ID (SYNCTYPEID field).
The status of the row is tracked in the status column (SYNCSTATUS field). All of the rows in the table begin with a status of 3, meaning that the corresponding Component Interface instance should be purged from the synchronization server. The other valid values for the status field are:
Status |
Description |
0 |
Current. This causes the corresponding Component Interface instance to not be synchronized. |
1 |
Out of date. This causes a Get to be called on the corresponding Component Interface instance, and the rest of the event flow to be joined. |
The OnValidateSet event uses the SyncServer properties SessionID and TypeID. These should be populated by values from the SYNCSESSIONID and SYNCTYPEID fields, respectively.
Considerations Using OnValidateSet
If you set breakpoints in a Component Interface, or do a trace , you will see OnValidateSet running multiple times. This happens when the synchronization server sends a request to an application server for OnValidateSet to run and does not receive a response soon afterward. Then the synchronization server sends out another request. In theory, OnValidateSet only runs once per Component Interface Type. In practice, more than one OnValidateSet request runs concurrently in certain environments.
OnValidateSet PeopleCode Example
The following PeopleCode sets validation for batches of instances of the QE_DEMO_CONTACT component interface.
SQLExec("UPDATE PSSYNCSERVERVAL SET SYNCSTATUS=0 WHERE SYNCSESSIONID =:1 AND SYNCTYPEID = :2 AND EXISTS (SELECT 'X' FROM %Table(QE_DEMO_CONTACT) B WHERE PSSYNCSERVERVAL.SYNCID = B.SYNCID AND PSSYNCSERVERVAL.SYNCDTTM >= B.LASTUPDDTTM)", %SyncServer.SessionID, %SyncServer.TypeID); SQLExec("UPDATE PSSYNCSERVERVAL SET SYNCSTATUS=1 WHERE SYNCSESSIONID =:1 AND SYNCTYPEID = :2 AND EXISTS (SELECT 'X' FROM %Table(QE_DEMO_CONTACT) B WHERE PSSYNCSERVERVAL.SYNCID = B.SYNCID AND PSSYNCSERVERVAL.SYNCDTTM < B.LASTUPDDTTM)", %SyncServer.SessionID, %SyncServer.TypeID);
Using the AddReference and AddReferenceType methods, you can create ad-hoc references to Component Interfaces using PeopleCode, instead of defining the reference and the relationship in Application Designer.
Use the OnGetDefinition event when you want to access the ad-hoc references specified with the AddReference method in the component events. In this event, you must specify every instance of an ad-hoc reference. The referenced Component Interfaces are defined by their SyncIDs. The referenced Component Interfaces objects can reference other referenced Component Interface objects.
When to Use OnGetDefinition
You should only consider using ad-hoc references when you want to dynamically establish read-only references of static data. Using these methods, you are not establishing a relationship between the Component Interfaces. You cannot navigate these references. You cannot make any changes to these instances.
OnGetDefinition PeopleCode Example
In the OnGetDefinition event, have one call to the AddReferenceType method for every referenced Component Interface type in the current Component Interface.
%SyncServer.AddReferencedType(CompIntfc.RefCI);
In one of the Component build events (PreBuild, PostBuild, RowInit) you must also include a call to the AddReference method for every instance (identified by the SyncID) of the referenced Component Interface.
%SyncServer.AddReference(&SyncID, CompIntfc.RefCI);