|
Foundation |
|
| |||||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |
See:
Description
Interface Summary | |
---|---|
Execution2Interface | This interface describes various aspects associated with the execution of a stored process. |
ExecutionBaseInterface | This interface describes various common aspects associated with the execution of a stored process. |
ExecutionInterface | Deprecated. Use Execution2Interface instead. |
ExecutionStatusListener2Interface | This interface is implemented by clients who need to be notified of stored process execution status changes. |
ExecutionStatusListenerInterface | Deprecated. Use ExecutionStatusListener2Interface instead. |
OutputParameterInterface | This interface describes an output parameter. |
StoredProcess2Interface | This interface describes the second generation of the stored process service object. |
StoredProcessBaseInterface | This interface describes various common aspects of the stored process service object. |
StoredProcessInterface | Deprecated. Use StoredProcess2Interface instead. |
StoredProcessServiceInterface | This interface describes a stored process service. |
Class Summary | |
---|---|
GenericStream | Describes a GenericStream data source or target. |
PermanentPackageResultHints | Deprecated. |
ResultHints | Deprecated. |
SASLog | A collection of SAS log or listing lines. |
StoredProcessServiceFactory | Factory used to manufacture a stored process service. |
StoredProcessServiceProxy | Stored Process service proxy. |
TransientPackageResultHints | Deprecated. |
WebDAVPackageDAVServerResultHints | Deprecated. |
WebDAVPackagePRResultHints | Deprecated. |
WebDAVPackageURLResultHints | Deprecated. |
XMLStream | Describes a XMLStream data source or target. |
Exception Summary | |
---|---|
AlertProcessingException | This class describes exceptions thrown while creating and updating the StoredProcessAlert item and may wrap an underlying exception |
ExecutionException | This base class describes exceptions thrown when StoredProcessInterface.execute() or
StoredProcess2Interface.execute() is invoked. |
ExecutionStatusListenerException | This class wraps exceptions thrown while invoking methods in the user supplied listener. |
InvalidParameterValueException | This exception is thrown when a parameter has a non-conforming value. |
MissingParameterException | This exception is thrown when a required parameter has not been assigned a value. |
ResultsBindingException | This class wraps exceptions thrown when trying to bind to the results. |
SASServerException | This class wraps exceptions thrown while accessing the SAS Server. |
SessionNotAvailableException | This exception is thrown when the StoredProcessService knows about the session described in the message, but you are supplying the wrong user context. |
SessionNotFoundException | This exception is thrown when the StoredProcessService cannot find the session described in the message. |
Execute stored processes.
The Stored Process Service enables a client to execute stored processes. A stored process is a SAS language program that is stored on a SAS server or in metadata. Input parameters (name/value pairs) and input data (via a streaming interface, client-side file or client-side data-set) can be passed to the stored process. Output can be returned to the client in a package, via a streaming interface or to a client side file or client-side data-set. Stored processes can also access any SAS data source or external file and create new data sets, files, or other data targets supported by SAS.
Note: The Stored Process Service cannot be used to execute a SAS language program stored on a client.
The Information Service is used to search for and identify stored processes that meet specified criteria. A stored process is then selected for exploitation. Alternatively, the Information Service can be used to access a stored process at a known location in metadata. Input parameters, if present, can be assigned values. For package-capable stored processes, the package location can be specified via input parameters. The locations of input and output tables and filerefs can also be be specified. The stored process can then be executed either synchronously or asynchronously. A package might be generated. If executed asynchronously, streaming input might be provided to the stored process and streaming results might be available during execution. An alert might be created in the Personal Repository to capture the execution of the stored process.
Stored Processes can also be manually created for exploitation though this is not the normal usage pattern: methods are provided to completely specify certain types of stored processes. For more information about manually creating a stored process, see the sample code provided.
The following sections apply to the exploitation of stored processes defined in a SAS Metadata Repository, though some sections are also applicable to manually created stored processes.
The Stored Process Service is one of the SAS Foundation Services, though not one of the core services. To use it within the Discovery Service framework, the Stored Process Service must be specified in the service deployment being used. No specific configuration information is needed for the Stored Process Service.
At initialization, the Stored Process Service determines whether the Logging Service is available and, if it is, various items related to the use of the Stored Process Service can be logged. Service deployments are typically created using the Foundation Services Manager Plug-in in the SAS Management Console and that plug-in automatically adds a dependency on the Logging Service.
To provide enhanced capabilities, the format of the metadata describing stored processes was changed in version 9.2 and again in 9.3. As a result there have been various changes to the API, including the creation of new interfaces in 9.2 and the enhancement of those interfaces in 9.3. The version of the stored processes metadata format introduced in 9.2 was version 1 and the version introduced in 9.3 was version 2. Hence 9.2 stored processes are also known as version 1 stored processes and 9.3 stored processes may be called version 2 stored processes. Both version 1 and version 2 stored processes can be present in a 9.3 metadata repository. Summaries of the changes for 9.2 and the changes for 9.3 are available.
Stored process definitions can be created in a SAS Metadata Repository using the Folder View of the SAS Management Console or by any SAS component that has the ability to create stored process metadata. A design time Java api based on the stored process smart object is provided to programmatically create and modify stored processes.
The Stored Process Service is used to execute stored processes that exist in a
SAS Metadata Repository. The typical pattern is to obtain a smart object corresponding
to the stored process of interest and then create a service object (in other words, an object that implements
StoredProcess2Interface) from the smart
object. A StoredProcess2Interface
contains all
of the information needed to execute a stored process. This includes the location
of the stored process program, the server to be used to execute the stored process,
any input parameters, and the desired output. Detailed information about that stored
process, if needed, can be obtained from the smart object.
A StoredProcess2Interface
can also be manually initialized by obtaining an
empty object which implements
StoredProcess2Interface from
the Stored Process Service and then calling various setter methods with
appropriate values to create a version 1 stored process, though
this is not the anticipated use of the service.
Stored processes accept input parameters. Input parameters at the stored process (SAS code) level have string names and string values. Input parameters are optionally defined in stored process metadata and might include default values and / or lists of valid values which may be statically specified or dynamically obtained. Values for input parameters can be set programmatically using the setParameterValue() method call.
If defined at the metadata level, input parameters metadata is compatible with that used by the Prompting Framework. The SMC support for defining and modifying stored processes uses a design time component provided by the Prompting Framework and the term input parameters is used interchangably with "prompts". And, since StoredProcess2Interface surfaces a com.sas.prompts.PromptValuesInterface, parameter values can be initialized and modified by components that support the Prompting Framework. An example of such components would be com.sas.prompts.components.webapp.visuals.PromptPropertiesPanel and com.sas.prompts.visuals.swing.PromptPropertiesPanel, which can be used to display a visual so that parameter values can be entered in the servlet and Swing environments respectively.
Therefore, at execution time, when a stored process object is instantiated from metadata, parameter names are in the case used to enter them in the SMC Folder View. However, the various flavors of the setParameterValue method function in a case-insensitive way. e.g. if StoredProcess2Interface's setParameterValue() method is invoked, case insensitive comparisons are performed to determine if a parameter of that name exists in the deserialized stored process. If you directly manipulate Prompting Framework objects you need to keep this case-sensitivity issue in mind.
The value is examined to see if there are any unsafe characters such as a percent sign (%), ampersand (&), single quotation mark ('), double quotation marks ("), or semicolon (;). If an unsafe character is present, the character is enclosed by the %NRSTR() macro. If the unsafe character is a percent sign, single quotation mark or double quotation marks then the unsafe character is escaped using a percent sign before being enclosed by a %NRSTR() macro.
Processing similar to that described above is done on the server for all other stored processes.StoredProcess2Interface
is called, the session context is examined to
see if a DataProviderInterface is bound to DataProviderInterface.DATA_PROVIDER_KEY.
If a DataProviderInterface is bound, a DynamicPromptValueValidator is constructed using
the data provider for value validation; if one is not bound, a DynamicPromptValueValidator
is constructed without a data provider and validation against dynamic data sources will not be done.
Given these differences between the servers and the performance characteristics of each type of server, the writer of the stored process may choose to restrict the execution of the stored process to a certain type of server. If the stored process is not restricted, default behavior of the service for a version 2 stored process is to attempt to first obtain a connection to a Stored Process Server and if that fails (either because no such server is defined in metadata or a connection to the server could not be obtained), an attempt is made to obtain a connection to a Workspace Server.
Version 1 stored processes are directly associated with either a Workspace Server or a Stored Process Server and an attempt is only made to obtain a connection to the server associated with the stored process.
A version 2 stored process can also be designated to run on other Application Servers (in addition to the one specified in metadata). For such stored processes, the setServerContext() method allows the run time specification of the Application Server to be used for execution.
If a client supplies a connection to a pooled Workspace servers, the available feature set is similar to that available on a Workspace server.
The Stored Process service provides methods to access certain types of results (packages and streams) if the stored process is defined in metadata to possess those capabilities and if any needed parameters have appropriate values at execution time. StoredProcess2Interface surfaces two methods (isPackageCapable() and isStreamCapable()) which can be used to determine the result capabilities of the stored process. Stored processes defined in metadata possess the capabilities specified in their definition; manually created stored processes are version 1 and are created with package only capability on a Workspace server and with both capabilities (stream and package) on a Stored Process server.
The following section describes the input parameters generated by the service when the execute() method or executeAsynch() method of StoredProcess2Interface is called. It also lists which of these input parameters the client is allowed to set. The combination of client set and service generated values is a set of name-value pairs that are passed, along with other input parameters, to the stored process to be used by the STPBEGIN / STPEND macros and can be ignored if these macros are not used. And, for certain types of packages, additional parameters recognized by the STPBEGIN and STPEND macros can be set by the client (consumer of this API).
Because output is streamed while the stored process executes, streaming stored processes should normally be executed asynchronously.
For both WebDAV cases: if the stored process writes the package to a unique service created instance name (as determined by _CREATE_NEW_PACKAGE_INSTANCE), _COLLECTION_URL reflects the unique name value.
If credentials are available, input parameters _HTTP_USER and _HTTP_PASSWORD are generated based on the credentials. Credentials are obtained from the User Context and depend on how the WebDAV server is defined in metadata. If the WebDAV sever's authentication type is "metadata", a one time password is generated; otherwise, the domain is used to try to get credentials using the UserContext's getIdentityByDomain() method and, if successful, bound to _HTTP_USER and _HTTP_PASSWORD. An exception is if _PUBLISH_TO_PR is absent or set to False and if the client supplies _HTTP_USER and optionally _HTTP_PASSWORD - in that case client supplied values are used and no attempt is made to obtain credentials.
The only output parameter relevant to result capabilities is _ARCHIVE_FULLPATH which must be set by the stored process to the path of the archive (the STPBEGIN / STPEND macros, if used, automatically do this) in the case of "PACKAGE_TO_ARCHIVE" on a Stored Process server. On completion of execution, the service uses the value of _ARCHIVE_FULLPATH to bind to the result package.
As discussed in the previous section, the type of any result (package or stream) and destination (if package) is determined by a combination of the capabilities of the stored process and the presence and values of various parameters. Provided the capabilities permit it the type and destination (if applicable) can be changed by suitable changes to the parameter values. StoredProcess2Interface's setParameterValue() can be used to add a parameter or modify the value of an existing parameter. Alternatively, the parameter hierarchy can be directly manipulated by obtaining a handle to it via StoredProcess2Interface's getPromptValues()
In addition to the result capability based input parameters described above, the following input parameters are generated by the service:
ClientName; JVM java.version; os.name (os.arch) os.version
ClientName
is obtained via the
getClientName() method
of StoredProcess2Interface
. If not present, a value of "StoredProcessService 9.3"
is used for ClientName
. java.version, os.name, os.arch
and os.version
are the properties returned by Java's
System.getProperty() method. If the value of any of these properties is not available
a blank is substituted.
If the client does set a value on an input parameter which the service would typically set and if the value set by the service is different, the client value will be overridden unless explicitly described otherwise. If overridden, a warning is logged in all cases except _PROGRAM and _METAFOLDER.
Multiple data sources and data targets are supported and can be defined in metadata. Data sources and data targets are used to model SAS files and SAS datasets.
Streaming input and output is not supported for version 1 stored processes that run on a Workspace Server but is supported for all other stored processes. This streaming feature is independent of the result capability of the stored process and the stored process should only be marked stream capable if it coded to use that capability. That capability is equivalent to the stored process streaming output to a fileref of name _WEBOUT.
For data sources, the expected content type specified in metadata is set in the
stream headers at the time the stream is constructed using the header property name
"HTTP:Content-type"
. If no expected content type is specified in metadata,
the service sets a default value of "text/xml"
for
XMLStreams
and "application/unknown"
for GenericStreams.
The client can override the value set by the service by invoking the setHeader()
method on the corresponding OutputStreamHeaderInterface
.
At run time the actual name of the dataset is associated with the prefix added table parameter name in one of the following ways:
Detailed metadata about the data sources and data targets defined in a stored process can be obtained from the getDataSourcesAndTargets() method of the smart object for those consumers which need this information.
Executing a stored process creates an Execution2Interface object. This object is a placeholder for the stored process that is executing or has completed execution and contains the execution status and results of the stored process. A single stored process can be executed multiple times; each execution returns a new Execution2Interface.
For stored processes defined by metadata, a connection to the server is obtained by the Stored Process service via the Connection service. However, the client can override this behavior by supplying a connection. A connection based on stored process metadata can be obtained by calling the getConnection() method.
Stored process execution can be synchronous or asynchronous. If synchronous, the
execute()
method blocks until execution is completed. If asynchronous, the method returns
immediately. An execution
listener interface
is provided to notify the caller when
execution starts and completes. Alternatively, the caller can poll the
Execution2Interface associated with the execution
for a completion status or call one of the waitForCompletion()
methods.
After the stored process has completed execution, the consumer can obtain the values of output parameters, test the completion status (the SAS return code), or fetch the SAS log or SAS listing.
Stored processes that run on Workspace Servers can be run synchronously or asynchronously. Stored processes that run on Stored Process Servers that deal with streams (for the reasons noted in Data Sources and Data Targets) are typically executed asynchronously. If the stored process that generates a package is run asynchronously, the package is not available until the stored process has completed execution.
The execution of the stored process can be captured in the MyInbox folder of the Personal Repository by a StoredProcessAlertItemInterface object.
Alerts are described in complete detail later in this document.
The Execution2Interface is closed with an explicit call to its destroy() method after the client application has completed processing results.
The StoredProcess2Interface
is closed with an explicit call to its
destroy() method when there is no
further need for it. Unless the client intends to re-execute the stored process,
there is no further use for this object after the execute method has returned.
Note: The Stored Process service locks the Session Context associated with the stored process for the duration of the execution of the stored process. After execution is complete, it unlocks the Session Context and then attempts to destroy the Session Context. "Best practices" associated with the Session Service for Context sharing require applications which use the Session Context to lock it for the duration of their use, therefore the Stored Process Service's attempt to destroy the Session Context should not affect the controlling application's use of it. If the controlling application does not lock the Session Context, the Stored Process Service will destroy the Session Context and any attempt to retrieve artifacts (e.g. a package which depends on the Session Context) after the execute method has returned may result in errors.
If desired, notification of completion of execution can be provided by installing a listener.
Packages generated by certain package capable stored processes are surfaced by Execution2Interface's getResultPackage() method. The package can be either SAS server based or WebDAV based depending on various prompt settings. Package surfaced by getResultPackage() are automatically closed by Execution2Interface's destroy method.
If there is a need for the package to have a life-span independent of the Execution2Interface, Execution2Interface's setResultPackageLifeCycleBound() method can be used. If this method is used to unbind the life cycle of the package from the Execution2Interface, the Stored Process service copies the package to the mid-tier for SAS server based packages since access to the package is lost once the connection to the server is closed; for WebDAV based packages no such copy is needed and setLifecycleBound() is a directive to the Stored Process service to not close the package when Execution2Interface's destroy method is called. The Usage section contains a code example.
Alerts provide a more permanent mechanism to access a package beyond the life-span of Execution2Interface and the SessionContext session. If the application requires the creation of an alert, "best practices" recommend accessing the package via the alert if access is needed beyond the life-span of Execution2Interface, and not via Execution2Interface's setResultPackageLifeCycleBound() method as described above.
The Stored Process Service uses one or more of the following services depending on the usage pattern:
Routines which require specific permissions to run if a security manager is installed that the service calls are:
These methods are called from within "privileged code" in the service. Refer to the documentation for those methods to determine the permissions which need to be given to the CodeSource associated with the Stored Process Service.
The Stored Process Service uses the Logging Service to log usage under a logging context of "com.sas.services.storedprocess".
The context used for output directed to the SAS Management Console Application Monitor plug-in is "ApplicationMonitor.StoredProcessService".
The Stored Process follows Foundation services best practices in its locale usage. If a locale needs to be supplied (e.g. when interacting with the prompting framework) one is obtained from the User Service via the UserContext's getLocale() method. When establishing a connection to a Workspace or Stored Process server there is no explicit locale passing to the Connection service as the Connection service also follows Foundation services best practices in its locale handling.
Code fragments to perform various operations are as follows:
// Find all stored processes that contain the search string specified in the "Name" field import com.sas.services.storedprocess.metadata.StoredProcessFilter; import com.sas.services.information.InformationServiceInterface; import com.sas.services.user.UserContextInterface; ... InformationServiceInterface informationService; UserContextInterface userContext; ... // At this point in the code it is assumed that the Foundation Services // have been deployed and the variable "informationService" // is a handle to a discovered Information Service and "userContext" is // the UserContextInterface (obtained from the User Service) // representing the user. ... StoredProcessFilter filter = new StoredProcessFilter("Name", com.sas.services.information.FilterComponent.CONTAINS, search); java.util.List list = informationService.search(userContext, filter);"list" contains a list of Information Service stored process smart objects. The client can then present this list of stored processes to the user, who can select one for execution.
import com.sas.services.storedprocess.metadata.StoredProcessInterface; ... // assuming the user selects the ith object StoredProcessInterface smartObject = (StoredProcessInterface)list.get(i);Alternatively, if the path in metadata to the stored process is known, the smart object can be directly obtained as follows:
// Get the stored processes given its location in metadata. import com.sas.services.information.InformationServiceInterface; import com.sas.services.user.UserContextInterface; import com.sas.services.information.metadata.PathUrl; import com.sas.services.storedprocess.metadata.StoredProcessInterface; ... InformationServiceInterface informationService; UserContextInterface userContext; ... // At this point in the code it is assumed that the Foundation Services // have been deployed and the variable "informationService" // is a handle to a discovered Information Service and "userContext" is // the UserContextInterface (obtained from the User Service) // representing the user. ... String path = set to a path like "SBIP://METASERVER/Shared Data/Test_Stored_Process(StoredProcess)" StoredProcessInterface smartObject = (StoredProcessInterface)informationService.getObjectByPath(userContext, new PathUrl(path));The client then obtains a StoredProcess object for exploitation by calling the newServiceObject() method on the stored process smart object:
import com.sas.services.storedprocess.metadata.StoredProcessInterface; import com.sas.services.storedprocess.StoredProcess2Interface; ... StoredProcessInterface smartObject = ... // set as shown previously StoredProcess2Interface storedProcess = (StoredProcess2Interface)smartObject.newServiceObject();The object returned is a Stored Process Service StoredProcess2Interface.
import com.sas.services.storedprocess.StoredProcessServiceInterface; ... Class[] desiredServiceTypes = new Class[] {StoredProcessServiceInterface.class}; ServiceTemplate serviceTemplate = new ServiceTemplate(desiredServiceTypes); StoredProcessServiceInterface storedProcessService = (StoredProcessServiceInterface)DiscoveryService.defaultInstance().findService(serviceTemplate);
StoredProcessServiceFactory spsf = new StoredProcessServiceFactory(); StoredProcessServiceInterface storedProcessService = (StoredProcessServiceInterface)spsf.getStoredProcessService();
StoredProcessOptions options = new StoredProcessOptions(); StoredProcess2Interface storedProcess = (StoredProcess2Interface) storedProcessService.newStoredProcess(StoredProcessInterface.SERVERTYPE_WORKSPACE, options);
or
StoredProcessOptions options = new StoredProcessOptions(); StoredProcess2Interface storedProcess = (StoredProcess2Interface) storedProcessService.newStoredProcess(StoredProcessInterface.SERVERTYPE_STOREDPROCESS, options);As described in the javadoc for the method, the former will create a stored process to run on a Workspace server with package capability only and the latter will create a stored processs to run on a Stored Process server with both stream and package capabilities. See the section on result capabilities to learn how _RESULT dictates the type of result. By default, a transient result package will created if _RESULT is not specified. To obtain streaming results:
storedProcess.setParameterValue("_RESULT", "STREAM");
storedProcess.setSourceFromFile("/sas/pub/sprocess", "prdsale.sas");
storedProcess.setParameterValue("pCountry", "US"); storedProcess.setParameterValue("pYear", "1993");
Two code fragments follow to illustrate how the Prompting Framework can be used to set prompt values on the stored process. The first one is Swing based.
com.sas.prompts.PromptValuesInterface promptValues = storedProcess.getPromptValues(); if (com.sas.prompts.PromptUtil.isPromptPresentAndVisible(promptValues)) { com.sas.prompts.DataProviderInterface dataProvider = new com.sas.prompts.valueprovider.dynamic.DataProvider(userContextInterface); com.sas.prompts.swing.visuals.PromptDialog pd = new com.sas.prompts.swing.visuals.PromptDialog(promptValues, dataProvider, parentFrameOrDialog, "Prompts", true, locale); pd.pack(); pd.setVisible(true); }
The second one is servlet based.
com.sas.prompts.PromptValuesInterface promptValues = storedProcess.getPromptValues(); if (com.sas.prompts.PromptUtil.isPromptPresentAndVisible(promptValues)) { com.sas.prompts.DataProviderInterface dataProvider = new com.sas.prompts.valueprovider.dynamic.DataProvider(userContextInterface); com.sas.prompts.components.webapp.visuals.model.PromptPropertiesPanelModelInterface model = new com.sas.prompts.components.webapp.visuals.model.DefaultPromptPropertiesPanelModel(promptValues, dataProvider , request.getLocale()); com.sas.prompts.components.webapp.visuals.PromptPropertiesPanel propertyPanel = new com.sas.prompts.components.webapp.visuals.PromptPropertiesPanel(model); propertyPanel.setId("myPrompt"); propertyPanel.setRequest(request); propertyPanel.setResponse(response); propertyPanel.write(out); }
For further details, see the Javadoc on the com.sas.prompts.* packages.
// The first parameter to execute determines whether execution is synchronous Execution2Interface spExecution = storedProcess.execute(true,null,false,null); // synchronous
// The third parameter to execute determines whether an alert is created Execution2Interface spExecution = storedProcess.execute(false,null,true,null); // create alertThe alert can be accessed either via the Execution2Interface or at a later time by examining the Personal Repository. From an Execution2Interface the alert is obtained as follows:
StoredProcessAlertItemInterface alert = spExecution.getStoredProcessAlert();See the section on accessing alerts for an example of obtaining the alert from the Personal Repository.
Note: In order to create an alert, the user must have access to the Personal Repository. For further instructions, see documentation describing Personal Repository setup.
ExecutionStatusListenerInterface listener = new ClientsExecutionStatusListener(); Execution2Interface spExecution = storedProcess.execute(false,listener,false,null); // asynchronous with a listener
public void executionStatusChanged(Execution2Interface spExecution) { int status = spExecution.getStatus(); if (status == spExecution.STATUS_EXECUTING) { // execution commencing ... } else if (status == spExecution.STATUS_COMPLETED_WITHOUT_EXCEPTION) { ResultPackageInterface pkg = spExecution.getResultPackage(); // Display the results. } else { // An exception occurred. } }
The following code sample executes a stored process that produces a package. The stored process accepts two input parameters.
// The stored process is named "ResultPackageDemo". Locate this stored process. import com.sas.services.storedprocess.metadata.StoredProcessFilter; ... StoredProcessFilter filter = new StoredProcessFilter("Name", com.sas.services.information.FilterComponent.EQUALS, "ResultPackageDemo"); java.util.List list = informationService.search(userContext, filter); // Assume we have one object returned from the search. // Get a Stored Process Service object from the smart object. com.sas.services.storedprocess.metadata.StoredProcessInterface spSmartObject = (com.sas.services.storedprocess.metadata.StoredProcessInterface)list.get(0); com.sas.services.storedprocess.StoredProcess2Interface spi = spSmartObject.newServiceObject(); // Set the values of the two parameters. spi.setParameterValue("pyear", "1993"); spi.setParameterValue("pcountry", "US"); // We are now ready to execute. // The first parameter (true) determines whether the execution is synchronous. // The call to execute blocks until the stored process completes. com.sas.services.storedprocess.Execution2Interface ei = spi.execute(true, null, false, null); // In a real case, you would test the status code using // ei.getStatus() before proceeding to get the package. // You can use the status code to determine whether any // additional processing is needed. // For example, an application might choose to dump out // exceptions / get the SAS log if errors are encountered. com.sas.services.publish.ResultPackageInterface rpi = ei.getResultPackage(); // You can now process the results. ... rpi.close(); // Destroy the Stored Process Service objects that are created. ei.destroy(); spi.destroy();
... Execution2Interface ei = storedProcess.execute(...); // the following call to setResultPackageLifeCycleBound() should be made before a reference // to the result package is obtainted via the getResultPackage() call on Execution2Interface ei.setResultPackageLifeCycleBound(false); // now the result package can be obtained for processing com.sas.services.publish.ResultPackageInterface rpi = ei.getResultPackage(); ...The package obtained will now have a life-time under consumer control and is no longer automatically closed when Execution2Interface.destroy() is called. The code to process the result package is no different.
The following code sample executes a stored process that streams results back. The stored process accepts three fixed input parameters.
// The stored process is named "StreamingDemo". Locate this stored process. import com.sas.services.storedprocess.metadata.StoredProcessFilter; ... StoredProcessFilter filter = new StoredProcessFilter("Name", com.sas.services.information.FilterComponent.EQUALS, "StreamingDemo"); java.util.List list = informationService.search(userContext, filter); // Assume we have one object returned from the search. // Next, get a Stored Process Service object from the smart object. com.sas.services.storedprocess.metadata.StoredProcessInterface spSmartObject = (com.sas.services.storedprocess.metadata.StoredProcessInterface)list.get(0); com.sas.services.storedprocess.StoredProcess2Interface spi = spSmartObject.newServiceObject(); // Set the values of the three parameters. spi.setParameterValue("ODSSTYLE", "boring"); spi.setParameterValue("CHARTTYPE", "vbar"); spi.setParameterValue("TIMEUNIT", "weeks"); // We are now ready to execute. // The first parameter (false) determines whether the execution is synchronous. // The call to execute does not block but returns with an Execution2Interface from which // input and output streams can be accessed to supply data to the stored process and // read data from the stored process. com.sas.services.storedprocess.Execution2Interface ei = spi.execute(false, listener, false, null); // Get the InputStream associated with "_WEBOUT." InputStream is = ei.getInputStream("_WEBOUT"); // If a Reader is desired it may be obtained as shown in the next three // statements (which are commented out): // InputStreamHeaderInterface ishi = ei.getInputStreamHeader("_WEBOUT"); // String encoding = ishi.getCharacterEncoding(); // InputStreamReader r = new InputStreamReader(is, encoding); // You can now can process the input stream - read until end-of-file // [code to process the input stream is not shown] // Wait for completion of the stored process. // The stream closing does not necessarily mean that the stored process has completed. int status = ei.waitForCompletion(); // You can use the status code to determine whether any additional processing is needed. // For example, an application might choose to dump out // exceptions / get the SAS log if errors are encountered. // Destroy the Stored Process Service objects that are created. ei.destroy(); spi.destroy();
Version 1 stored processes that run on a Stored Process Server and all version 2 stored processes can accept one or more streams of input. The following code fragment is based on one input stream, "_webin", being defined in the metadata. The execute() is called to specify asynchronous execution so that control returns to the code following the call to execute() after which input may be streamed to the stored process.
// ... find the stored process and specify parameter values if needed // We are now ready to execute. // The first parameter (false) specifies asynchronous execution com.sas.services.storedprocess.Execution2Interface ei = spi.execute(false, null, false, null); // Get the OutputStream associated with "_WEBIN". OutputStream os = ei.getOutputStream("_WEBIN"); OutputStreamWriter osw = new OutputStreamWriter(os); osw.write("line1: some text for line 1\n"); osw.write("line2: and this is line 2\n"); osw.write("line3: and here's the third and last line\n"); osw.close(); // ... process results as before
The execution of the stored process can be captured by an alert in the MyInbox folder of the Personal Repository by a StoredProcessAlertItemInterface object. You can view a code example which describes how the creation of an alert is requested. The event contained in the StoredProcessAlertItemInterface provides information about various aspects of the stored process (e.g., its name, description, Information Service entity key, etc.), the particular execution (e.g., parameters values, package (if present)) that it describes and execution status. Do note that generated parameters are not captured by the alert.
The Alert is created as soon as the stored process begins execution and seeded with those elements of the event that are known. After the stored process has completed execution, the alert is updated and contains all of the elements appropriate to that stored process. If the listener mechanism provided by ExecutionStatusListener2Interface is used, the alert is created before executionStatusChanged() is called for the first time and is updated before executionStatusChanged() is called for the subsequent call(s). If the stored process is executed using the execute() method the alert is updated once after creation; if the executeAsynch() method is used the alert is updated twice after creation. A typical use case would be for the stored process to be executed asynchronously and for a separate application to examine and display the execution status of stored processes of interest to the user. If the stored process creates a package, this separate application can use StoredProcessAlertItemInterface's getResults() to materialize the package.
Alerts are persisted in the MyInbox folder of the Personal Repository. See the section about accessing alerts for more details about accessing the alert.
Alerts are described in XML with an "Event" structure defined by the Event Service. Version 2 stored processes create alerts using the same format as that used in alerts created by version 1 stored processes. The specification for an alert follows:
<sas-event:Event xmlns:sas-event= "http://www.sas.com/xml/namespace/services.events-1.1" sas-event:name="com.sas.services.storedprocess.ExecutionStatusEvent"> <sas-event:Header> <sas-event:Version>1.0</sas-event:Version> <sas-event:SentAt>timestamp</sas-event:SentAt> <sas-event:Response sas-event:type="none"/> <sas-event:Properties> <Version xmlns="http://www.sas.com/xml/namespace/services.alerts.sp-1.1"> 2.0</Version> <ResultType xmlns="http://www.sas.com/xml/namespace/services.alerts.sp-1.1"> resultType</ResultType> <Status xmlns="http://www.sas.com/xml/namespace/services.alerts.sp-1.1"> status</Status> <StoredProcessName xmlns="http://www.sas.com/xml/namespace/services.alerts.sp-1.1"> storedProcessName</StoredProcessName> </sas-event:Properties> </sas-event:Header> <sas-event:Body> <sas-alerts-sp:StoredProcessAlert xmlns:sas-alerts-sp= "http://www.sas.com/xml/namespace/services.alerts.sp-1.1" sas-alerts-sp:version="2.0" sas-alerts-sp:name=name sas-alerts-sp:startTime=startTime sas-alerts-sp:endTime=endTime> <sas-alerts-sp:AlertEntityKey>entityKey </sas-alerts-sp:AlertEntityKey> <sas-alerts-sp:Description>description </sas-alerts-sp:Description> <sas-alerts-sp:StoredProcessName>storedProcessName </sas-alerts-sp:StoredProcessName> <sas-alerts-sp:StoredProcessDescription> storedProcessDescription </sas-alerts-sp:StoredProcessDescription> <sas-alerts-sp:Status>status</sas-alerts-sp:Status> <sas-alerts-sp:ResultType>resultType </sas-alerts-sp:ResultType> <sas-alerts-sp:StoredProcessEntityKey>storedProcessEntityKey </sas-alerts-sp:StoredProcessEntityKey> <sas-alerts-sp:StoredProcessPath>storedProcessPath </sas-alerts-sp:StoredProcessPath> <sas-alerts-sp:StoredProcessParameters> <sas-alerts-sp:StoredProcessParameter> <sas-alerts-sp:ParmName>parmName </sas-alerts-sp:ParmName> <sas-alerts-sp:ParmValue>parmValue </sas-alerts-sp:ParmValue> </sas-alerts-sp:StoredProcessParameter> ... </sas-alerts-sp:StoredProcessParameters> <sas-alerts-sp:Package> <sas-alerts-sp:PackageEntityKey>packageEntityKey </sas-alerts-sp:PackageEntityKey> <sas-publish:Package> ... </sas-publish:Package> </sas-alerts-sp:Package> <sas-alerts-sp:ExecutionExceptions> <sas-alerts-sp:Exception>exception message, cause and stack trace</sas-alerts-sp:Exception> ... </sas-alerts-sp:ExecutionExceptions> </sas-alerts-sp:StoredProcessAlert> </sas-event:Body> </sas-event:Event> |
The header elements are standard event elements as defined by the Event Services. The name of the event is "com.sas.services.storedprocess.ExecutionStatusEvent". The following table offers an explanation of those header elements, which vary by event. Descriptions of elements that are an intrinsic part of the Event structure are described in the Event Service.
Element/Attribute: | Description: |
sas-event:SentAt | A time stamp indicating when the event was created. |
sas-event:Properties |
Properties set by the stored process are
|
Explanations of the body elements are in the following table. If an element does not have a value when the alert is created, or if its value changes when the stored process completes, the behavior is documented in the Description column.
Element/Attribute: | Description: |
sas-alerts-sp:name | The name of the alert. |
sas-alerts-sp:version | The version number of the alert. Currently 2.0. |
sas-alerts-sp:startTime | The approx time at which the stored process began execution. The timezone is GMT and the format used is yyyy-MM-dd'T'HH:mm:ss'Z'. |
sas-alerts-sp:endTime | The approx time at which the stored process completed execution in the same format as startTime. Is blank if the stored process is still executing. |
sas-alerts-sp:AlertEntityKey | The Information Service entity key of the alert. |
sas-alerts-sp:Description | The description of the alert. It contains the name of the stored process. After execution completes, the text also has the completion time. |
sas-alerts-sp:StoredProcessName | The name of the stored process. |
sas-alerts-sp:StoredProcessDescription | The description of the stored process. |
sas-alerts-sp:Status | The status of this execution. When the alert is created, it is set to ExecutionBaseInterface.STATUS_EXECUTING. When execution is completed, it is set to ExecutionBaseInterface.STATUS_SAS_EXCEPTION_OCCURRED, ExecutionBaseInterface.STATUS_COMPLETED_WITHOUT_EXCEPTION, ExecutionBaseInterface.STATUS_EXCEPTION_OCCURRED, or Execution2Interface.STATUS_ABORTED. |
sas-alerts-sp:ResultType | The type of result generated by the stored process. One of the values from StoredProcessInterface2.RESULT_TYPE_*. |
sas-alerts-sp:StoredProcessEntityKey | The Information Service Entity Key of the stored process. |
sas-alerts-sp:StoredProcessPath | The SBIP URL of the stored process. |
sas-alerts-sp:StoredProcessParameters | Describes the parameters of the stored process. Contains zero or more StoredProcessParameter entries. |
sas-alerts-sp:StoredProcessParameter | Describes each parameter of the stored process. If the parameter is a scalar it's described as follows:
If the parameter is an array it's described as follows:
|
sas-alerts-sp:Package | Describes the package. This element is present only if the
result type is a transient package, a SAS server based file package, or a WebDAV server based
package. When the stored process starts executing an empty Package element is created. After execution is complete, the following two elements are added:
|
sas-alerts-sp:ExecutionExceptions | Describes any exceptions encountered in the execution of the stored process. Contains zero or more Exception entries. When the stored process starts executing an empty ExecutionExceptions element is created. After execution is complete, Exception elements are added if exceptions occurred. |
sas-alerts-sp:Exception | Describes the exception: the message, the cause, and a stack trace of the root exception. |
A sample alert is shown:
<?xml version="1.0" encoding="UTF-8"?> <sas-event:Event xmlns:sas-event= "http://www.sas.com/xml/namespace/services.events-1.1" sas-event:name="com.sas.services.storedprocess.ExecutionStatusEvent"> <sas-event:Header> <sas-event:Version>1.0</sas-event:Version> <sas-event:SentAt>2008-04-02T20:16:48Z</sas-event:SentAt> <sas-event:Response sas-event:type="none"/> <sas-event:Properties> <ResultType xmlns= "http://www.sas.com/xml/namespace/services.alerts.sp-1.1">512 </ResultType> <Status xmlns= "http://www.sas.com/xml/namespace/services.alerts.sp-1.1">3 </Status> <Version xmlns= "http://www.sas.com/xml/namespace/services.alerts.sp-1.1">2.0 </Version> <StoredProcessName xmlns= "http://www.sas.com/xml/namespace/services.alerts.sp-1.1">SP2_PSR (PR Existing Instance - Workspace) </StoredProcessName> </sas-event:Properties> </sas-event:Header> <sas-event:Body> <sas-alerts-sp:StoredProcessAlert xmlns:sas-alerts-sp= "http://www.sas.com/xml/namespace/services.alerts.sp-1.1" sas-alerts-sp:version="2.0" sas-alerts-sp:name="Sd7458859" sas-alerts-sp:startTime="2008-04-02T20:15:39.638Z" sas-alerts-sp:endTime="2008-04-02T20:16:17.211Z"> <sas-alerts-sp:AlertEntityKey> storedprocessalert+dav:RGWebDav/noname/PR/MyInbox/Sd7458859/storedprocessalert </sas-alerts-sp:AlertEntityKey> <sas-alerts-sp:Description>This alert describes the execution of stored process "SP2_PSR (PR Existing Instance - Workspace)" which completed at 2008-04-02T20:16:17.211Z.</sas-alerts-sp:Description> <sas-alerts-sp:StoredProcessName>SP2_PSR (PR Existing Instance - Workspace) </sas-alerts-sp:StoredProcessName> <sas-alerts-sp:StoredProcessDescription> Sample Product Sales Report (PSR) Stored Process - to the Personal Repository reusing an exisiting instance. </sas-alerts-sp:StoredProcessDescription> <sas-alerts-sp:Status>3</sas-alerts-sp:Status> <sas-alerts-sp:ResultType>512</sas-alerts-sp:ResultType> <sas-alerts-sp:StoredProcessEntityKey> StoredProcess+omi://Primary/reposname=primary/ClassifierMap;id=A5Z6U1YS.AK0016D1 </sas-alerts-sp:StoredProcessEntityKey> <sas-alerts-sp:StoredProcessPath> SBIP://METASERVER/WSP2/SP2_PSR (PR Existing Instance - Workspace)(StoredProcess) </sas-alerts-sp:StoredProcessPath> <sas-alerts-sp:StoredProcessParameters> <sas-alerts-sp:Parameter> <sas-alerts-sp:ParmName>pCountry </sas-alerts-sp:ParmName> <sas-alerts-sp:ParmValue>Canada </sas-alerts-sp:ParmValue> </sas-alerts-sp:Parameter> <sas-alerts-sp:Parameter> <sas-alerts-sp:ParmName>pYear </sas-alerts-sp:ParmName> <sas-alerts-sp:ParmValue>1993 </sas-alerts-sp:ParmValue> </sas-alerts-sp:Parameter> <sas-alerts-sp:Parameter> <sas-alerts-sp:ParmName>_result </sas-alerts-sp:ParmName> <sas-alerts-sp:ParmValue>PACKAGE_TO_WEBDAV </sas-alerts-sp:ParmValue> </sas-alerts-sp:Parameter> <sas-alerts-sp:Parameter> <sas-alerts-sp:ParmName>_publish_to_pr </sas-alerts-sp:ParmName> <sas-alerts-sp:ParmValue>true </sas-alerts-sp:ParmValue> </sas-alerts-sp:Parameter> <sas-alerts-sp:Parameter> <sas-alerts-sp:ParmName>_pr_collection_path </sas-alerts-sp:ParmName> <sas-alerts-sp:ParmValue>SPResults/collection1 </sas-alerts-sp:ParmValue> </sas-alerts-sp:Parameter> </sas-alerts-sp:StoredProcessParameters> <sas-alerts-sp:Package> <sas-alerts-sp:PackageEntityKey> package+dav://RGWebDav/noname/PR/MyResults/SPResults/collection1/package </sas-alerts-sp:PackageEntityKey> <sas-publish:Package xmlns:sas-publish= "http://www.sas.com/xml/namespace/services.publish-1.1" sas-publish:version="1.0" sas-publish:description= "1993 Sales Report for Canada" sas-publish:packageUrl= "http://d14844.na.sas.com:80/DAVStuff/noname/PR/MyResults/SPResults/collection1" sas-publish:transport="webdav" category="sales" context="product"> <sas-publish:Entries> <sas-publish:Entry sas-publish:description="Sales Report: Tabular" sas-publish:type="html"> <sas-publish:Html sas-publish:name="body.htm" sas-publish:type="body" sas-publish:url="body.htm"/> </sas-publish:Entry> </sas-publish:Entries> </sas-publish:Package> </sas-alerts-sp:Package> <sas-alerts-sp:ExecutionExceptions/> </sas-alerts-sp:StoredProcessAlert> </sas-event:Body> </sas-event:Event> |
Alerts describing the execution of a stored process are placed in the MyInbox folder of the Personal Repository. The first step is to access the Personal Repository. Personal Repository documentation provides code fragments that show how to obtain a reference to MyInbox.
FolderInterface myInbox = ... get a reference to "MyInbox". // A list of all alerts can be obtained. List list = myInbox.getItemsByClass(StoredProcessAlertItem.class); // These alerts might be presented to the user. // Alternatively, a specific alert can be obtained by name. StoredProcessAlertItem alert = (StoredProcessAlertItem)myInbox.getItemByClass(alertName, StoredProcessAlertItem.class); // Various elements of the alert can be obtained as follows from the getProperty() method: // Note: Constants.NS_STOREDPROCESS_ALERT_PREFIX_COLON maps to "sas-alerts-sp:" String prefix = "//" + com.sas.services.util.Constants.NS_STOREDPROCESS_ALERT_PREFIX_COLON; String statusStr = alert.getProperty( prefix + "Status" ); String resultTypeStr = alert.getProperty( prefix + "ResultType" ); int status = Integer.parseInt(statusStr); int resultType = Integer.parseInt(resultTypeStr); if (status == ExecutionBaseInterface.STATUS_COMPLETED_WITHOUT_EXCEPTION) { if (resultType == StoredProcess2Interface.RESULT_TYPE_PACKAGE) { PackageInterface pkg = alert.getResults(); ResultPackageInterface rpkg = (ResultPackageInterface)pkg.newServiceObject(); ... process the package ... } }
sas-alerts-sp:ResultType
,
sas-alerts-sp:startTime
and sas-alerts-sp:endTime
are not backward compatible.
9.2 style prompts are converted to the pre-9.2 Entity based model using the
convertPromptGroupToEntity
convertPromptGroupToEntity method of
PromptToEntityConverter
.
Data Sources and Data Targets are added to the list of output streams and input streams supported by the Stored Process.
Pre-9.2 stored processes had different result types. 9.2 stored processes have result capabilities with the type of result being driven by the capabilities allowed and prompt values. The following describes how different combinations of capability and prompts (converted to the Entity model) in a migrated stored process map to the pre-9.2 result type of StoredProcessInterface when a StoredProcessInterface is constructed.
If the "_result"
parameter is missing or present with no value:
If the "_result"
parameter has a non-empty value:
"_result"
is set to (a case-insensitive compare is done)
"PACKAGE_TO_REQUESTER". If package capability is not specified or the server selected
is not a Workspace server an exception is thrown. Parameter "_archive_path"
should be non-empty and point to the location where the package will be created.
The presence of a non-empty "_archive_path"
parameter determines the name of the
package; if missing, a new instance is created. A
PermanentPackageResultHints is
appropriately constructed and the result type is set to
RESULT_TYPE_PERMANENT_FILE_PACKAGE"_result"
is set to (a case-insensitive compare is done)
"PACKAGE_TO_ARCHIVE". If package capability is not specified or the server selected
is not a Stored Process server an exception is thrown. Parameter "_archive_path"
should be non-empty and point to the location where the package will be created.
The presence of a non-empty "_archive_path"
parameter determines the name of the
package; if missing, a new instance is created. A
PermanentPackageResultHints is
appropriately constructed and the result type is set to
RESULT_TYPE_PERMANENT_FILE_PACKAGE"_result"
is set to (a case-insensitive compare is done)
"PACKAGE_TO_WEBDAV". If package capability is not specified an exception is thrown.
Parameter "_publish_to_pr"
determines which of the following cases applies:
"_publish_to_pr"
is present and set to (a case-insensitive compare
is done) "true". "_create_new_package_instance"
(a case-insensitive compare to
"true" is done) determines whether a new package instance is created and the value of
"_pr_collection_path"
determines where in the Personal Repository the
package is published. A
WebDAVPackagePRResultHints is
appropriately constructed and the result type is set to
RESULT_TYPE_PERMANENT_WEBDAV_PACKAGE
"_publish_to_pr"
is absent or present and not set to (a case-insensitive compare
is done) "true". "_create_new_package_instance"
(a case-insensitive compare to
"true" is done) determines whether a new package instance is created and the value of
"_collection_url"
(an exception is thrown if absent) determines the location
where in WebDAV the package is published. This location is used to find the appropriate
WebDAV server in metadata - for a match to occur, the file portion of the URL should match
a base-path of the WebDAV server. A
WebDAVPackagePRResultHints is
appropriately constructed and the result type is set to
RESULT_TYPE_PERMANENT_WEBDAV_PACKAGE.
If a proxy URL is needed, the WebDAV server needs to be configured to contain the proxy URL.
"_result"
is not one of the values described above, an exception is thrown.
Do note the above functionality is provided for compatibility purposes, so that old code can run newly migrated stored processes. The functionality is not intended for newly created stored processes to be run using old code. And, StoredProcessInterface cannot be used to execute Version 2 stored processes introduced in 9.3.
|
Foundation |
|
| |||||||||||
PREV PACKAGE NEXT PACKAGE | FRAMES NO FRAMES |