SyncServer Class

This chapter provides an overview of the synchronization server events and the SyncServer class and discusses the following topics:

Important! PeopleSoft Mobile Agent is a deprecated product. The SyncServer class and mobile classes currently exist for backward compatibility only.

Click to jump to parent topicUnderstanding Synchronization Server Events and the SyncServer Class

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.

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.

Click to jump to top of pageClick to jump to parent topicUnderstanding the Synchronization Events

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

Click to jump to top of pageClick to jump to parent topicUnderstanding the SyncServer Class

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;

Click to jump to top of pageClick to jump to parent topicConsiderations Using Synchronization Events and the SyncServer Class

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:

  1. 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.

  2. 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.

  3. 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.

  4. 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.

  5. 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.

  6. 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.

Click to jump to parent topicUsing the Synchronization Server Events

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:

See Also

Optimization PeopleCode

Advanced Considerations for Synchronization

Click to jump to top of pageClick to jump to parent topicUsing OnConflict

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:

See Also

ConflictAlgorithm

Click to jump to top of pageClick to jump to parent topicUsing OnSelect

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;

OnSelect and Spidering

Through spidering, rows of data can be required for the mobile device in addition to those selected by the OnSelect event. Suppose that:

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

SyncIDs

Click to jump to top of pageClick to jump to parent topicUsing OnValidate

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

validateID

validateVersion

Click to jump to parent topicUsing Attachment Events

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.

OnGetProperty Event

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;

OnGetPropertyFilter Event

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;

OnSetProperty Event

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;

Click to jump to parent topicUsing Filtering

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:

See Also

CheckForChanges

LastSyncDateTime

LastSyncRowCount

Click to jump to parent topicScope of SyncServer Objects

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;

Click to jump to parent topicSyncServer Class

The SyncServer object is accessed using the %SyncServer system variable.

Click to jump to parent topicSyncServer Class Methods

This section describes the SyncServer class methods.

Click to jump to top of pageClick to jump to parent topicAddReference

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

Click to jump to top of pageClick to jump to parent topicAddReferenceType

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);

Click to jump to top of pageClick to jump to parent topicCheckForChanges

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.LastSyncRow⇒ Count);

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", Comp⇒ Intfc.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.

Click to jump to top of pageClick to jump to parent topicNotify

Syntax

Notify(message_text, severity [, object_type, object_id])

Description

Use this method to pass an error message during synchronization.

Parameters

message_text

Specify the message text.

severity

Specify the severity of the message.

object_type

Specify the object type.

object_id

Specify the object ID.

Returns

None.

Click to jump to top of pageClick to jump to parent topicSelectAll

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

CheckForChanges

Click to jump to parent topicSyncServer Class Properties

This section describes the SyncServer class properties.

Click to jump to top of pageClick to jump to parent topicClientPlatform

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.

Click to jump to top of pageClick to jump to parent topicConflictAlgorithm

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.

Click to jump to top of pageClick to jump to parent topicConflictStatus

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.

Click to jump to top of pageClick to jump to parent topicExcludeProperty

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;

Click to jump to top of pageClick to jump to parent topicExportLocation

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.

Click to jump to top of pageClick to jump to parent topicIsReferenceUnresolved

Description

When two or more new objects are uploaded during a synchronization, and they contain references to each other, it can create a deadlock condition on the server, since the references cannot be resolved in the database yet, and therefore neither of the objects can be successfully saved. To break the deadlock, SyncServer performs a tentative save on one of the objects without attempting to resolve any of it's references. This makes it possible for the other object's reference to be resolved, and it can be permanently saved. Once that is completed, the first object's reference can also now be resolved, so a second save is performed to add the appropriate key values from the resolved reference. The purpose of this enhancement is to provide a new

This property indicates whether or not a tentative save is in progress, and whether the object being processed has had it's references resolved.

This property returns a Boolean value: true if a tentative save is in progress, false otherwise.

This property is read-only.

Click to jump to top of pageClick to jump to parent topicLastSyncDateTime

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.

Click to jump to top of pageClick to jump to parent topicLastSyncRowCount

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.

Click to jump to top of pageClick to jump to parent topicPropertyValue

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;

Click to jump to top of pageClick to jump to parent topicSessionID

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

Using OnValidateSet

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);

Click to jump to top of pageClick to jump to parent topicSynchronizing

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.

Click to jump to top of pageClick to jump to parent topicSyncIDs

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

Array Class.

Click to jump to top of pageClick to jump to parent topicTypeID

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

Using OnValidateSet

Click to jump to top of pageClick to jump to parent topicvalidateID

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.

Click to jump to top of pageClick to jump to parent topicvalidateRowCount

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.

Click to jump to top of pageClick to jump to parent topicvalidateVersion

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;

Click to jump to parent topicAdvanced Considerations for Synchronization

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:

Click to jump to top of pageClick to jump to parent topicUsing OnValidateSet

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);

Click to jump to top of pageClick to jump to parent topicUsing OnGetDefinition

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);