Consuming Registered Interfaces

These topics provide an overview of registered interface consumption and discuss how to:

  • Invoke service interfaces.

  • Set up stale data checks in service calls.

  • Pool component interfaces.

  • Consume collection-sized interfaces.

  • Bind complex types to and from portal pages.

  • Consume SQLViews.

If there is an interface in the registry that your application needs to use, you must create code in PeopleCode events in the consuming application to invoke the interface.

Note: You can click the Generate Consumer Code button on the Registry Details page for the registered service to generate all the code the consuming application needs. Cut and paste the code into the consuming application's PeopleCode Event (for example, SavePostChange PeopleCode). Confirm that the generated code meets the criteria set out in these steps and make any necessary modifications.

Note: You can only place the code for manipulative services such as Set, Add, or Delete in the SavePostChange PeopleCode of a single field in a component. You cannot spread out manipulative service calls over several PeopleCode events. You must also not place manipulative service calls in FieldChange PeopleCode.

Consuming applications invoke service interfaces in four steps:

  1. Import, declare, and create framework classes, service classes, and type classes.

  2. Bind to the service implementation using the Service Manager's LocateService method.

    At runtime, the Service Manager determines the appropriate implemented interface application class and returns an instance of it to the consuming application for invocation as follows:

    1. The import statement in the consumer code indicates which registered interface is required.

    2. The registered interface contains information about which implemented interface class is required.

    3. The Service Manager's LocateService method returns an instance of the implementation class.

      Note: The LocateService method requires the service name and the service version in order to bind to the appropriate service.

    The consumer code only needs to know which registered interface it is using. The provider application specifies which implemented class should be returned to the consumer. This enables the provider to make changes to the implemented interface without impacting the consumer.

  3. If you are invoking a type interface, the consumer application needs to set the properties of the type class in the input parameters prior to passing it to the DoService call.

    The type interface registry entry describes the properties of the type class. The consumer can map properties individually from the consuming application to the type class properties.

  4. Invoke the DoService method of the service implementation class, passing the parameters as defined in the service signature.

    The service signature defines the zero or more input and output parameters that need to be passed to the service. Parameters can be simple types (such as string, number, date, or boolean) or complex types defined and registered as types in the interface registry:

    • When the service requires complex types as parameters, the consumer needs to import the type class, declare it as a local variable and instantiate it using the Create instruction.

    • When the service requires simple types, the simple types only need to be declared by the consumer.

  5. Catch and manage exceptions.

    The consumer code must invoke all services within a try-catch block. All code executed in between the try and the catch statement is in a protected area so that any exceptions thrown during service execution will immediately return control to the catch statement in the consumer code. The consuming application can then react to the exception.

    The consumer code can catch specific exceptions or the baseException, which is the parent class to all registered exceptions.

    Note: The consuming code should always catch for baseException to catch exceptions not specific to the service.

  6. Analyze the service execution log for relevant information.

    During service execution, the registry framework collects all warnings and messages issued by the provider and exposes them to the consumer as a service execution log. The consumer can query the execution log and take action based on the warnings and messages, if necessary.

    Each service has a property called ExecutionLog. The property has an array of LogType called Log. The LogType has the following attributes:

    • DEFAULT_TEXT

    • MESSAGE_SET_NBR

    • MESSAGE_NBR

    • MESSAGE_SEVERITY

    The service's Log class has a generic method ShowLog() to display the content of the execution log.

Note: All consumer PeopleCode runs within the scope of a consumer component session. Any services that the system invokes during the component runtime will also run within this transaction scope. If the service execution encounters fatal errors, the system will roll back the entire component transaction unless the errors are specifically caught as exceptions. For example, if the a component in the consumer application uses two services invoked by the SavePostChange PeopleCode and one executes successfully while the other throws a fatal error, the system will not save any data to the component from either service.

If the service call is updating the component in the consumer application with an action of Add, you do not need to set up a check for stale data and you can invoke the service in Component.SavePostChange PeopleCode..

However, if the service is to update prior selected data, you need to set up a stale data check to ensure that the underlying data has not been modified during user interaction on the consumer side. To do this, create a Get service in the Component.PostBuild PeopleCode and a Set service in the Component.SavePostChange PeopleCode.

If the registry detects a discrepancy in the data, it will cause an error, which can be caught using baseException.

Several services may use the same instance of a component interface in their implementations. To improve performance, you can pool component interfaces. Component interfaces must be scoped to one local PeopleCode event, but within that event the code can send several calls to services using the same open component interface.

The system then passes the component interface pool to the Service Manager's LocateService method. If a requestor is only issuing one service call in a Peoplecode Event, the system passes NULL as a component interface pool.

You can set up services to operate on items or on collections (row sets). If the consuming application is working with a collection of rows, you must set up the consuming application to pass the entire collection to the service. The service removes any items that are not passed into the service in the collection. If consumer passes an empty collection, it will effectively remove all the data rows in the provider implementation.

Use a collection-sized Get service to populate the collection type class, manipulate it, and pass it back to the Set service.

All services work with simple or complex types as parameters. Simple types are available as PeopleCode data types. The provider application implements complex types as application classes. It is not possible to view application class properties directly on a page so it is necessary for the consumer application to create pages based on Rowset.Row.Record.Field objects and map the type class properties to the fields.

In the consumer code, set up a call to the helper method PopulateToRowset to bring all data from the type class instance to the user interface of the consumer component. Set up a call to the helper method PopulateFromRowset to bring all values from the rowset used in the user interface of the type class.

Note: Not all type classes provide helper methods and not all helper methods will work in all consumer components. In these cases, you will need to write your own logic to bind the type class values to the consumer user interface.

Consuming applications can use registered sqlViews directly without binding. Use registered sqlViews for the following:

  • Search views.

  • Prompting.

  • Related display.