Business Rules

The Smart Integration Connector Capabilities introduce additional business rule APIs (BR APIs) to allow for execution and management of remote business rules inside the context of the Smart Integration Connector gateway. These rules are transported using https to the Smart Integration Connector local gateway, compiled locally, executed, and the results returned to the caller for further processing. They provide a mechanism for complex drill backs, data processing scenarios or to invoke remote webAPIs hosted in your network.

NOTE: Gateways must have a local data source defined to invoke remote business rules.

There are two ways business rules can be used with the Smart Integration Connector Gateway:

  • OneStream BRAPIs interact with a specific local gateway and run on OneStream application servers.

  • Business rules that reference DLLs that are only accessible by the Local Gateway Server. These BRs are compiled and executed on the local gateway (Remote Business Rules when creating them in the Windows Desktop Client).

In these scenarios, the local gateway must have the allowRemoteCodeExec setting configured to True to enable remote execution.

The BR APIs are outlined below:

ExecRemoteGatewayRequest
ExecRemoteGatewayCachedBusinessRule
ExecRemoteGatewayJob
ExecRemoteGatewayBusinessRule
GetRemoteDataSourceConnection
GetRemoteGatewayJobStatus
GetSmartIntegrationConfigValue
GetGatewayConnectionInfo
Check OneStream Version
BRApi.Utilities.IsGatewayOnline(gwName)
Business Rules Compatibility

ExecRemoteGatewayRequest

Initiates a request to a local gateway as specified in the remote request object. This request is dispatched to the Smart Integration Connector local gateway connection data source with the specified command remote invoked.

NOTE: This method is used for request and response type interactions to a remote endpoint that runs for three or less minutes. The default execution timeout is 90 seconds and can be overridden by setting the CommandTimeout property on the RemoteRequestDTO instance provided.

Parameter details:

  • RemoteRequestDTO: Remote request object populated with the remote command and endpoint

  • Returns: RemoteRequestResultDto - Result of execution including the status and any exceptions which may have occurred on the remote endpoint

Following is an example connector business rule that would run on the OneStream application server sending a remote request and block of code to a Local Gateway Connection:

Copy
// ExecRemoteGatewayRequest for arbitrary code execution returning a DataTable
string GatewayName = "";
RemoteRequestResultDto objxfRemoteRequestResultDto;
RemoteCodeRequestDto objxfRemoteRequest = new RemoteCodeRequestDto();
// Indication the desire is to run a remote block of code
objxfRemoteRequest.ConnectionType = RemoteCommandType.RemoteCodeExec;
// Name of the remote host to pass to
objxfRemoteRequest.GatewayHostForRequest = GatewayName;
var strCode = "using System;...."; // Valid block of C# or VB.NET code
objxfRemoteRequest.LanguageType = RemoteCodeLanguageType.CSHARP;
objxfRemoteRequest.RemoteCodeBlock = strCode;
objxfRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayRequest(objxfRemoteRequest);
var xfDT = new XFDataTable(si, objxfRemoteRequestResultDto.ResultSet, null, 1000);

Here is the example in VB:

Copy
' ExecRemoteGatewayRequest for arbitrary code execution returning a DataTable
Dim GatewayName As String = ""
Dim objxfRemoteRequestResultDto As RemoteRequestResultDto
Dim objxfRemoteRequest As New RemoteCodeRequestDto
' Indication the desire is to run a remote block of code
objxfRemoteRequest.connectionType = RemoteCommandType.RemoteCodeExec
' Name of the remote host to pass to
objxfRemoteRequest.gatewayHostforRequest = GatewayName
Dim strCode As String = "using System;...." ' Valid block of C# or VB.NET code
objxfRemoteRequest.LanguageType = RemoteCodeLanguageType.CSHARP
objxfRemoteRequest.remoteCodeBlock = strCode
objxfRemoteRequestResultDto=BRApi.Utilities.ExecRemoteGatewayRequest(objxfRemoteRequest)
Dim xfDT = New XFDataTable(si, objxfRemoteRequestResultDto.ResultSet, Nothing, 1000)

This BR API can also be used to invoke arbitrary SQL commands against a Smart Integration Connector local gateway connection data source at your site:

Copy
/ ExecRemoteGatewayRequest for arbitrary SQL returning a DataTable
string SQL = ""; // SQL SELECT statement goes here
RemoteRequestResultDto objxfRemoteRequestResultDto;
RemoteRequestDto objxfRemoteRequest = new RemoteRequestDto();
// Indicate this is a remote SQL command request
objxfRemoteRequest.ConnectionType = RemoteCommandType.SQLCommand;
objxfRemoteRequest.RelayRemoteDBConnection = ""; // Name of the connection defined in the remote endpoint
objxfRemoteRequest.GatewayHostForRequest = ""; // Name of the remote host to pass to
objxfRemoteRequest.RemoteCommand = SQL;
objxfRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayRequest(objxfRemoteRequest);
// Evaulate the results to determine if it was successful
if (objxfRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.Success)
{
 // Logic to use results in `objxfRemoteRequestResultDto.ResultSet`
}
else
{
 // Query failed. Add additional logic here to handle this case.
}

Here is the example in VB:

Copy
' ExecRemoteGatewayRequest for arbitrary SQL returning a DataTable
Dim SQL As String = "" ' SQL SELECT statement goes here
Dim objxfRemoteRequestResultDto As RemoteRequestResultDto
Dim objxfRemoteRequest As New RemoteRequestDto
' Indicate this is a remote SQL command request
objxfRemoteRequest.connectionType = RemoteCommandType.SQLCommand
objxfRemoteRequest.RelayRemoteDBConnection = "" ' Name of the connection defined in the remote endpoint
objxfRemoteRequest.GatewayHostforRequest = "" ' Name of the remote host to pass to
objxfRemoteRequest.RemoteCommand = SQL
objxfRemoteRequestResultDto=BRApi.Utilities.ExecRemoteGatewayRequest(objxfRemoteRequest)
' Evaulate the results to determine if it was successful
If (objxfRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.Success) Then
 ' Logic to use results in `objxfRemoteRequestResultDto.ResultSet`
Else
 ' Query failed. Add additional logic here to handle this case.
End If

Remote function returning a datatable (C#) without parameters:

Copy
// ExecRemoteGatewayBusinessRule
var GatewayName = ""; // Name of the Gateway
var SICFunctionName = ""; // Name of the SIC Function to run
var RemoteMethodName = ""; // Name of the method inside the SIC Function that will be called
var objRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, GatewayName, null, SICFunctionName, RemoteMethodName);
if (objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.Success && !(objRemoteRequestResultDto.ResultSet is null))
{
 if (objRemoteRequestResultDto.ResultType == RemoteResultType.DataTable)
 {
 BRApi.ErrorLog.LogMessage(si, "Data Returned: " + objRemoteRequestResultDto.ResultSet.Rows.Count);
 }
}
else
{
 if (!(objRemoteRequestResultDto.RemoteException is null))
 {
 throw ErrorHandler.LogWrite(si, new XFException(si, objRemoteRequestResultDto.RemoteException));
 }
}

Here is the example in VB:

Copy
' ExecRemoteGatewayBusinessRule
 
' Call a remote Smart Integration Function
Dim GatewayName As String = "" ' Name of the Gateway
Dim SICFunctionName As String = "" ' Name of the SIC Function to run
Dim RemoteMethodName As String = "" ' Name of the method inside the SIC Function that will be called
Dim objRemoteRequestResultDto As RemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, GatewayName, Nothing, SICFunctionName, RemoteMethodName)
If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.Success AndAlso objRemoteRequestResultDto.ResultSet IsNot Nothing) Then
 If (objRemoteRequestResultDto.ResultType = RemoteResultType.DataTable) Then
 BRApi.ErrorLog.LogMessage(si, "Data Returned: " & objRemoteRequestResultDto.ResultSet.Rows.Count)
 End If
Else
 If (Not (objRemoteRequestResultDto.RemoteException Is Nothing)) Then
 Throw ErrorHandler.LogWrite(si, New XFException(si, objRemoteRequestResultDto.RemoteException))
 End If
End If

ExecRemoteGatewayCachedBusinessRule

When a cache flag and key is provided to the ExecRemoteGatewayBusinessRule BR API, this method is used to invoke a previously cached method. This is intended to be used for high-frequency remote business rules to avoid the performance impact of recompiling a remote method on each invocation.

NOTE: Requires allowRemoteCodeExec = True on Smart Integration Connector local gateway. If the previously cached method is not invoked after 60 minutes, the remote cached method is purged.

Parameter details:

  • si: SessionInfo object used to create connection objects

  • cachedFunctionKey: Key of previously cached remote function to invoke

  • functionArguments: Array of objects aligning to function / method parameters. Null / Nothing if there are none required

  • remoteHost: Name of remote host to invoke operation. (Smart Integration Connector Local Gateway Name)

  • executionTimeOut: Timeout (in seconds) on the remote job

  • Returns: RemoteRequestResultDto - Result of execution including the status and any exceptions which may have occurred on the remote endpoint

Here is the rule in C#:

Copy
// ExecRemoteGatewayCachedBusinessRule
 
// Execute and cache a remote SIC Function for later use
var GatewayName = ""; // Name of the Gateway
var SICFunctionName = ""; // Name of the SIC Function to run 
var RemoteMethodName = ""; // Name of the method inside the SIC Function that will be called
var SICCachedFunctionName = ""; // Name of the cache key for this SIC Function, which can be called on subsequent requests
RemoteRequestResultDto objRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, SICFunctionName, null, GatewayName, RemoteMethodName, SICCachedFunctionName, false, 90);
 
if (objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.Success
 && !(objRemoteRequestResultDto.ResultSet is null)
 && objRemoteRequestResultDto.ResultType == RemoteResultType.DataTable)
{
 BRApi.ErrorLog.LogMessage(si, "Data Returned - Rows:" + objRemoteRequestResultDto.ResultSet.Rows.Count);
}
else
{
 if (objRemoteRequestResultDto.RemoteException != null)
 {
 throw ErrorHandler.LogWrite(si, new XFException(si, objRemoteRequestResultDto.RemoteException));
 }
 else
 {
 BRApi.ErrorLog.LogMessage(si, "Remote Smart Integration Function Succeeded - no data/datatable returned");
 }
}
 
// Subsequent invocations of the remote BR can be run by specifying the endpoint and the cached key name
RemoteRequestResultDto objRemoteRequestResultDtoCached = BRApi.Utilities.ExecRemoteGatewayCachedBusinessRule(si, SICCachedFunctionName , null, GatewayName, 90);

Here is the rule in VB.NET:

Copy
' ExecRemoteGatewayCachedBusinessRule
 
' Execute and cache a remote SIC Function for later use
Dim GatewayName As String = "" ' Name of the Gateway
Dim SICFunctionName As String = "" ' Name of the SIC Function to run 
Dim RemoteMethodName As String = "" ' Name of the method inside the SIC Function that will be called
Dim SICCachedFunctionName As String = "" ' Name of the cache key for this SIC Function, which can be called on subsequent requests
Dim objRemoteRequestResultDto As RemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, SICFunctionName, Nothing, GatewayName, RemoteMethodName, SICCachedFunctionName, False, 90)
 
If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.Success AndAlso objRemoteRequestResultDto.ResultSet IsNot Nothing AndAlso objRemoteRequestResultDto.ResultType = RemoteResultType.DataTable) Then
 BRApi.ErrorLog.LogMessage(si, "Data Returned - Rows:" + objRemoteRequestResultDto.ResultSet.Rows.Count)
Else
 If (objRemoteRequestResultDto.RemoteException IsNot Nothing) Then
 Throw ErrorHandler.LogWrite(si, New XFException(si, objRemoteRequestResultDto.RemoteException))
 Else
 BRApi.ErrorLog.LogMessage(si, "Remote Smart Integration Function Succeeded - no data/datatable returned")
 End If
End If
 
' Subsequent invocations of the remote BR can be run by specifying the endpoint and the cached key name
Dim objRemoteRequestResultDtoCached As RemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayCachedBusinessRule(si, SICCachedFunctionName, Nothing, GatewayName, 90)

ExecRemoteGatewayJob

There may be instances where a remote operation on the Smart Integration Connector Local Gateway host would need to process and assemble data that may take several minutes to run. In this situation, you could use this BR API to queue and run a remote business rule in an asynchronous manner where the remote Smart Integration Connector Local Gateway host returns a Job ID (GUID) that can later be used to obtain the job’s status or the results if the job is complete. When invoking this method, if the RemoteMessageResultStatus is returned as JobRunning (as shown in the example below), the RequestJobID is populated with the ID of the queued job that can later be used to obtain status.

NOTE: Requires allowRemoteCodeExec = True on Smart Integration Connector Local Gateway. There is a defined default limit of 30 minutes for remote jobs to execute before the job is cancelled, and an overloaded version of ExecremoteGatewayJob exists allowing the timeout to be provided, but can never exceed 4 hours. This is not configurable and if this timeout is reached, the status returned shows the timeout. If the result is not obtained within five minutes after the job completes (using the GetRemoteGatewayJobStatus BR API), the remote results are purged to ensure that result objects reclaim server memory on the Smart Integration Service host.

NOTE: This is required to call back into GetRemoteJobStatus with the returned ID to obtain the result:

Here is a basic overview of invoking a remote job and displaying the returned remote Job ID in C#.

Copy
// ExecRemoteGatewayJob basic example
 
var GatewayName = ""; // Name of the Gateway
var SICFunctionName = ""; // Name of the SIC Function to run
var argTest = new object[2];
argTest[0] = 100; // Example first argument to SIC Function
argTest[1] = "test"; // Example second argument to SIC Function
 
// Invoking a OneStream SIC Function Business Rule as a remote job
var objRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayJob(si, SICFunctionName, argTest, GatewayName, String.Empty);
if (objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.JobRunning)
{
 // Logic to wait for job to complete
}

Here is the basic example in VB:

Copy
' ExecRemoteGatewayJob basic example
 
Dim GatewayName As String = "" ' Name of the Gateway
Dim SICFunctionName As String = "" ' Name of the SIC Function to run
Dim argTest(1) As Object
argTest(0) = 100 ' Example first argument to SIC Function
argTest(1) = "test" ' Example second argument to SIC Function
 
' Invoking a OneStream SIC Function Business Rule as a remote job
Dim objRemoteRequestResultDto As RemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayJob(si, SICFunctionName, argTest, GatewayName, String.Empty)
If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.JobRunning) Then
 ' Logic to wait for job to complete
End If

Here is the rule in C# to invoke a job, obtain the job ID, and 'poll' until completion:

Copy
// ExecRemoteGatewayJob with polling
 
var jobID = new Guid();
var GatewayName = ""; // Name of the Gateway
var SICFunctionName = ""; // Name of the SIC Function to run
 
// Invoke a long-running Job with a Smart Integration Function
var objRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayJob(si, GatewayName, null, SICFunctionName, String.Empty);
 
// If Successful, the status is retuned indicating the job is running with the job ID. Use this ID to interrogate if the job is compleed.
if (objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.JobRunning)
{
 jobID = objRemoteRequestResultDto.RequestJobID;
 BRApi.ErrorLog.LogMessage(si, "Remote Job Queued and Running - JobID: " + jobID.ToString());
 // Example waiting 20 seconds for job to complete
 for (var loopControl = 0; loopControl < 10; loopControl++)
 { 
 System.Threading.Thread.Sleep(2000);
 var objJobStatus = BRApi.Utilities.GetRemoteGatewayJobStatus(si, jobID, GatewayName);
 
 if (objJobStatus.RemoteJobState == RemoteJobState.Running)
 {
 BRApi.ErrorLog.LogMessage(si, "Remote Job Still running - JobID: " + jobID.ToString());
 } 
 else if (objJobStatus.RemoteJobState == RemoteJobState.Completed)
 { 
 // Checking the return type from the remote job
 if (!(objJobStatus.RemoteJobResult.ResultSet is null))
 { 
 var xfDT = new XFDataTable(si, objJobStatus.RemoteJobResult.ResultSet, null, 1000); 
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Datatable Returned - JobID: " + jobID.ToString());
 return null;
 }
 else if (!(objJobStatus.RemoteJobResult.ResultDataSet is null))
 {
 var xfDT = new XFDataTable(si, objJobStatus.RemoteJobResult.ResultDataSet.Tables[0], null, 1000); 
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Dataset Returned - JobID: " + jobID.ToString());
 return null
 } 
 else if (!(objJobStatus.RemoteJobResult.ResultDataCompressed is null))
 { 
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Object Returned - JobID: " + jobID.ToString());
 var value = CompressionHelper.InflateJsonObject<String>(si, objJobStatus.RemoteJobResult.ResultDataCompressed);
 BRApi.ErrorLog.LogMessage(si, value);
 return null;
 }
 }
 else if (objJobStatus.RemoteJobState == RemoteJobState.JobNotFound)
 {
 BRApi.ErrorLog.LogMessage(si, "Remote Job Not Found - JobID: " + jobID.ToString());
 return null;
 }
 else if (objJobStatus.RemoteJobState == RemoteJobState.RequestTimeOut)
 {
 BRApi.ErrorLog.LogMessage(si, "Remote Job Timed Out - JobID: " + jobID.ToString());
 return null;
 }
 else if (objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.Exception)
 {
 BRApi.ErrorLog.LogMessage(si, "Exception During Execution of Job: " + objRemoteRequestResultDto.RemoteException.ToString());
 }
 }
}
else
{
 // Exception occurred immediately during compile/initial run
 if (objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.Exception)
 {
 BRApi.ErrorLog.LogMessage(si, "Exception Executing Job: " + objRemoteRequestResultDto.RemoteException.ToString());
 }
 else
 {
 BRApi.ErrorLog.LogMessage(si, "General Job Execution Error - State: " + objRemoteRequestResultDto.RemoteResultStatus.ToString());
 }
}
 
return null;

Here is the rule in VB.NET to invoke a job, obtain the job ID, and 'poll' until completion:

Copy
' ExecRemoteGatewayJob with polling
 
Dim jobID As Guid
Dim GatewayName As String = "" ' Name of the Gateway
Dim SICFunctionName As String = "" ' Name of the SIC Function to run
 
' Invoke a long-running Job with a Smart Integration Function
Dim objRemoteRequestResultDto As RemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayJob(si, GatewayName, Nothing, SICFunctionName, String.Empty)
 
' If Successful, the status is retuned indicating the job is running with the job ID. Use this ID to interrogate if the job is compleed.
If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.JobRunning) Then
 jobID = objRemoteRequestResultDto.RequestJobID
 BRApi.ErrorLog.LogMessage(si, "Remote Job Queued and Running - JobID: " & jobID.ToString())
 ' Example waiting 20 seconds for job to complete
 For loopControl = 0 To 10
 System.Threading.Thread.Sleep(2000)
 Dim objJobStatus As RemoteJobStatusResultDto = BRApi.Utilities.GetRemoteGatewayJobStatus(si, JobID, GatewayName)
 
 If (objJobStatus.RemoteJobState = RemoteJobState.Running) Then
 BRApi.ErrorLog.LogMessage(si, "Remote Job Still running - JobID: " & jobID.ToString()) 
 Else If (objJobStatus.RemoteJobState = RemoteJobState.Completed) 
 ' Checking the return type from the remote job
 If (objJobStatus.RemoteJobResult.ResultSet IsNot Nothing) Then
 Dim xfDT As XFDataTable = New XFDataTable(si, objJobStatus.RemoteJobResult.ResultSet, Nothing, 1000) 
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Datatable Returned - JobID: " & jobID.ToString())
 Return Nothing
 Else If (Not objJobStatus.RemoteJobResult.ResultDataSet Is Nothing) Then
 Dim xfDT As XFDataTable = New XFDataTable(si,objJobStatus.RemoteJobResult.ResultDataSet.Tables(0), Nothing, 1000) 
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Dataset Returned - JobID: " & jobID.ToString())
 Return Nothing 
 Else If objJobStatus.RemoteJobResult.ResultDataCompressed IsNot Nothing Then 
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Object Returned - JobID: " & jobID.ToString())
 Dim value As String = CompressionHelper.InflateJsonObject(Of String)(si, objJobStatus.RemoteJobResult.ResultDataCompressed)
 Brapi.ErrorLog.LogMessage(si, value)
 Return Nothing
 End If
 Else If (objJobStatus.RemoteJobState = RemoteJobState.JobNotFound) Then
 BRApi.ErrorLog.LogMessage(si, "Remote Job Not Found - JobID: " & jobID.ToString())
 Return Nothing
 Else If (objJobStatus.RemoteJobState = RemoteJobState.RequestTimeOut) Then
 BRApi.ErrorLog.LogMessage(si, "Remote Job Timed Out - JobID: " & jobID.ToString())
 Return Nothing
 Else If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.Exception) Then
 BRApi.ErrorLog.LogMessage(si, "Exception During Exeuction of Job: " & objRemoteRequestResultDto.RemoteException.ToString())
 End If
 Next
Else
 ' Exception occurred immediately during compile/initial run
 If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.Exception) Then
 BRApi.ErrorLog.LogMessage(si, "Exception Executing Job: " & objRemoteRequestResultDto.RemoteException.ToString())
 Else
 BRApi.ErrorLog.LogMessage(si, "General Job Execution Error - State: " & objRemoteRequestResultDto.RemoteResultStatus.ToString()) 
 End If
End If
 
Return Nothing

ExecRemoteGatewayBusinessRule

This is a core BR API that can be used to remotely invoke Smart Integration functions on a specified remote Smart Integration Connector Local Gateway host. The Smart Integration Connector Local Gateway must have allowRemoteCodeExec set to True for this BR API to invoke an operation successfully, otherwise the Smart Integration Connector Local Gateway host returns a result indicating that remote code execution is disabled.

This method takes a previously authored Smart Integration function, written in VB.NET or C#, in the OneStream application and passes it to the remote host for execution. With this BR API, it is expected that remote calls should take no more than 2-3 minutes to return a result to the caller as this BR API will block until a result is returned. If longer running or sync operations are needed, consider using the execRemoteGatewayJob BR API.

NOTE: Requires allowRemoteCodeExec = True on Smart Integration Service

Parameter details:

  • si: SessionInfo object used to create connection objects

  • brName: Name of the locally defined (within the OneStream Application scope) Smart Integration function

  • functionArguments: Array of objects aligning to function / method parameters. Null / Nothing if there are none required.

  • remoteHost: Name of remote host to invoke operation. (Smart Integration Connector name)

  • functionName: Name of the function in the Smart Integration function to invoke. If null or empty, a function/method with the name RunOperation is expected to exist within the authored code.

  • (Optional) cachedFunctionKey: Name used to cache the remote function to avoid recompiling the function on a subsequent call. This is optional and if missing or null the function will not be cached.

  • (Optional) forceCacheUpdate: Option indicating if a previously cached function should be replaced with this version. When true, and an existing function is found with a name specified in the cachedFunctionKey parameter, the BR is recompiled and recached. This is useful for situations where a remote function is cached and a change was made.

  • executionTimeOut: Timeout (in seconds) on the remote job (In 7.4, this is now an optional parameter and defaults to 90 seconds if the parameter is missing.)

Here is a C# drill-back example:

Copy
// ExecRemoteGatewayBusinessRule displaying results in drillback
var GatewayName = ""; // Name of the Gateway
var SICFunctionName = ""; // Name of the SIC Function to run
DrillBackResultInfo drillBackInfo = new DrillBackResultInfo();
DataTable dtf = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, SICFunctionName, null, GatewayName, string.Empty).ResultSet;
var xfDT = new XFDataTable(si, dtf, null, 1000);
drillBackInfo.DataTable = xfDT;
drillBackInfo.DisplayType = ConnectorDrillBackDisplayTypes.DataGrid;
return drillBackInfo;

Here is a VB example:

Copy
' ExecRemoteGatewayBusinessRule displaying results in drillback
Dim GatewayName As String = "" ' Name of the Gateway
Dim SICFunctionName As String = "" ' Name of the SIC Function to run
Dim drillBackInfo As DrillBackResultInfo = new DrillBackResultInfo()
Dim dtf As DataTable = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, SICFunctionName, Nothing, GatewayName, String.Empty).ResultSet
Dim xfDT As XFDataTable = new XFDataTable(si, dtf, Nothing, 1000)
drillBackInfo.DataTable = xfDT
drillBackInfo.DisplayType = ConnectorDrillBackDisplayTypes.DataGrid
Return drillBackInfo

Here is a C# drill-back example that invokes a remote business rule accepting 2 parameters:

Copy
// ExecRemoteGatewayBusinessRule Drillback example
var GatewayName = ""; // Name of the Gateway
var SICFunctionName = ""; // Name of the SIC Function to run
var RemoteMethodName = ""; // Name of the method inside the SIC Function that will be called.
var drillBackInfo = new DrillBackResultInfo();
object[] argTest = new object[2]; // Creating an object array to package the method parameters
argTest[0] = 12; // First parameter is an integer
argTest[1] = "test"; // Second parameter is a string
 
// Remote Smart Integration Function Signature: ' Public Shared Function RunOperation2(testval As Integer, teststr As String) As ArrayList
// Invoking method RunOperation2 on endpoint testConnection passing in user defined parameters as an array
 
var objRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, SICFunctionName, argTest, GatewayName, RemoteMethodName);
 
if (objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.RunOperationReturnObject)
{
 var returnVal = objRemoteRequestResultDto.ObjectResultValue as ArrayList;
 // Simple demonstration without error checking to look at the first element of the arraylist
 drillBackInfo.TextMessage = "Completed! " + returnVal[0].ToString(); 
 drillBackInfo.DisplayType = ConnectorDrillBackDisplayTypes.TextMessage;
 return drillBackInfo;
}
else if (objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.Success)
{
 // Demonstrating a 'pattern' whereby the caller can verify what the type is that's returned and handle properly.
 var xfDT = new XFDataTable(si, objRemoteRequestResultDto.ResultSet, null, 1000);
 drillBackInfo.DataTable = xfDT;
 drillBackInfo.DisplayType = ConnectorDrillBackDisplayTypes.DataGrid;
 return drillBackInfo;
}
else if (!(objRemoteRequestResultDto.RemoteException is null))
{
 throw ErrorHandler.LogWrite(si, new XFException(si, objRemoteRequestResultDto.RemoteException));
}

Here is a VB.NET drill-back example that invokes a remote business rule accepting 2 parameters:

Copy
' ExecRemoteGatewayBusinessRule Drillback example
Dim GatewayName As String = "" ' Name of the Gateway
Dim SICFunctionName As String = "" ' Name of the SIC Function to run
Dim RemoteMethodName As String = "" ' Name of the method inside the SIC Function that will be called.
Dim drillBackInfo As New DrillBackResultInfo
Dim argTest(1) As Object ' Creating an object array to package the method parameters
argTest(0) = 12 ' First parameter is an integer
argTest(1) = "test" ' Second parameter is a string
 
' Remote Smart Integration Function Signature: ' Public Shared Function RunOperation2(testval As Integer, teststr As String) As ArrayList
 
' Invoking method RunOperation2 on endpoint testConnection passing in user defined parameters as an array
 
Dim objRemoteRequestResultDto As RemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, SICFunctionName, argTest, GatewayName, RemoteMethodName)
 
If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.RunOperationReturnObject) Then
 Dim returnVal As ArrayList = objRemoteRequestResultDto.ObjectResultValue
 'Simple demonstration without error checking to look at the first element of the arraylist
 drillBackInfo.TextMessage = "Completed! " & returnVal(0).ToString() 
 drillBackInfo.DisplayType = ConnectorDrillBackDisplayTypes.TextMessage
 Return drillBackInfo
Else If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.Success)
 ' Demonstrating a 'pattern' whereby the caller can verify what the type is that's returned and handle properly.
 Dim xfDT = New XFDataTable(si, objRemoteRequestResultDto.ResultSet, Nothing, 1000)
 drillBackInfo.DataTable = xfDT
 drillBackInfo.DisplayType = ConnectorDrillBackDisplayTypes.DataGrid
 Return drillBackInfo
Else If (Not (objRemoteRequestResultDto.remoteException Is Nothing))
 Throw ErrorHandler.LogWrite(si, New XFException(si, objRemoteRequestResultDto.RemoteException))
End If

Below is a TestFileRead Remote Business Rule function in C# Referenced by Examples Below.

Here it is in C#:

Copy
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.Common;
using System.Globalization;
using System.IO;
using System.Linq;
 
namespace OneStream.BusinessRule.SmartIntegrationFunction.TestFileRead
{
 public class MainClass
 {
 public byte[] RunOperation(string year)
 {
 string fname = @"c:\temp\hw_" + year + ".csv";
 byte[] buffer = System.IO.File.ReadAllBytes(fname);
 return buffer;
 }
 
 public byte[] GetOtherFileData(string year)
 {
 string fname = @"c:\temp\zw_" + year + ".csv";
 byte[] buffer = System.IO.File.ReadAllBytes(fname);
 return buffer;
 }
 
 public bool DeleteOldFileData(string year)
 {
 string fname = @"c:\temp\zw_" + year + ".csv";
 try
 {
 System.IO.File.Delete(fname);
 return true;
 }
 catch (IOException ex)
 {
 return false;
 }
 }
 }
}

Here it is in VB:

Copy
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Data.Common
Imports System.Globalization
Imports System.IO
Imports System.Linq
 
Namespace OneStream.BusinessRule.SmartIntegrationFunction.TestFileRead
 Public Class MainClass
 Public Function RunOperation(ByVal year As String) As Byte()
 Dim fname As String = "c:\temp\hw_" & year & ".csv"
 Dim buffer As Byte() = System.IO.File.ReadAllBytes(fname)
 Return buffer
 End Function
 
 Public Function GetOtherFileData(ByVal year As String) As Byte()
 Dim fname As String = "c:\temp\zw_" & year & ".csv"
 Dim buffer As Byte() = System.IO.File.ReadAllBytes(fname)
 Return buffer
 End Function
 
 Public Function DeleteOldFileData(ByVal year As String) As Boolean
 Dim fname As String = "c:\temp\zw_" & year & ".csv"
 
 Try
 System.IO.File.Delete(fname)
 Return True
 Catch ex As IOException
 Return False
 End Try
 End Function
 End Class
End Namespace

Below is a remote business rule that queries a database and returns a datatable.

Here is the rule in C#:

Copy
// SIC Function referenced by other examples here
namespace OneStream.BusinessRule.SmartIntegrationFunction.GetDataFromDB
{
 public class MainClass
 {
 private const string DataSourceName = "";
 public DataTable RunOperation() 
 {
 DataTable dataTableResults = new DataTable();
 string connectionString, sql;
 
 connectionString = OneStreamGatewayService.APILibrary.GetRemoteDataSourceConnection(DataSourceName);
 
 SqlConnection conn;
 conn = new SqlConnection(connectionStringconn.Open());
 sql = ""; // Enter SQL Query here
 SqlCommand cmd = new SqlCommand(sql, conn);
 var dbreader = cmd.ExecuteReader();
 dataTableResults.Load(dbreader);
 return dataTableResults;
 }
 }
}

Here is the rule in VB:

Copy
' SIC Function referenced by other examples here
Namespace OneStream.BusinessRule.SmartIntegrationFunction.GetDataFromDB
 Public Class MainClass
 Private Const DataSourceName As String = ""
 
 Public Function RunOperation() As DataTable
 Dim dataTableResults As DataTable = New DataTable()
 Dim connectionString, sql As String
 connectionString = APILibrary.GetRemoteDataSourceConnection(DataSourceName)
 Dim conn As SqlConnection
 conn = New SqlConnection(connectionStringconn.Open())
 sql = "" ' Enter SQL Query here
 Dim cmd As SqlCommand = New SqlCommand(sql, conn)
 Dim dbreader = cmd.ExecuteReader()
 dataTableResults.Load(dbreader)
 Return dataTableResults
 End Function
 End Class
End Namespace

Here is an example of calling a TestFileRead remote business rule in C#.

Copy
// Here we are telling it to specifically call a remote Smart Integration Function called TestFileRead at SIC Gateway
// called TestConnection with a method called DeleteOldFileData
var GatewayName = ""; // Name of the Gateway
var SICFunctionName = "TestFileRead"; // Name of the SIC Function from above example
var RemoteMethodName = "DeleteOldFileData"; // Name of the method inside the SIC Function that will be called.
RemoteRequestResultDto objRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, SICFunctionName, new object[] {"2024"}, GatewayName, RemoteMethodName);
 
if (objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.RunOperationReturnObject && !(objRemoteRequestResultDto.ObjectResultValue is null))
{
 bool result;
 if (bool.TryParse(objRemoteRequestResultDto.ObjectResultValue.ToString(), out result))
 {
 BRApi.ErrorLog.LogMessage(si, "File Deleted: " + result.ToString()); 
 }
 else
 {
 BRApi.ErrorLog.LogMessage(si, "Returned a non-boolean value");
 }

else
{
 if (objRemoteRequestResultDto.RemoteException != null
 {
 throw ErrorHandler.LogWrite(si, new XFException(si, objRemoteRequestResultDto.RemoteException));
 }
 
}
 
return null;

Here is an example of calling a TestFileRead remote business rule in VB.NET.

Copy
'Here we are telling it to specifically call a remote Smart Integration Function called TestFileRead at SIC Gateway 
'called TestConnection with a method called DeleteOldFileData
Dim GatewayName As String = "" ' Name of the Gateway
Dim SICFunctionName As String = "TestFileRead" ' Name of the SIC Function from above example
Dim RemoteMethodName As String = "DeleteOldFileData" ' Name of the method inside the SIC Function that will be called.
Dim argTest(0) As Object ' Creating an object array to package the method parameters
argTest(0) = "2024" ' First parameter is an integer
 
Dim objRemoteRequestResultDto As RemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, SICFunctionName, argTest, GatewayName, RemoteMethodName)
If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.RunOperationReturnObject) Then
 'The delete method returns a true/false return type
 Dim result As Boolean
 'ObjectResultValue introduced in v7.4 to simplify obtaining the return 
 'value from a method that doesn't return a Dataset/Datatable
 result = objRemoteRequestResultDto.ObjectResultValue
 BRApi.ErrorLog.LogMessage(si, "File Deleted: " & result)
Else
 If (Not (objRemoteRequestResultDto.remoteException Is Nothing)) Then
 Throw ErrorHandler.LogWrite(si, New XFException(si, objRemoteRequestResultDto.remoteException))
 End If
End if

Here's an example to call the remote BR called "GetDataFromDB" (C#):

Copy
// Here we are telling it to specifically call a remote Smart Integration Function called GetDataFromDB at SIC Gateway called TestConnection with a method called RunOperation
var GatewayName = ""; // Name of the Gateway
var SICFunctionName = "GetDataFromDB"; // Name of the SIC Function from above example
var RemoteMethodName = "RunOperation"; // Name of the method inside the SIC Function that will be called.
var objRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, SICFunctionName, null, GatewayName, RemoteMethodName);
 
if (objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.Success
 && objRemoteRequestResultDto.ResultSet != null
 && objRemoteRequestResultDto.ResultType == RemoteResultType.DataTable)

 BRApi.ErrorLog.LogMessage(si, "Data Returned - Rows:" + objRemoteRequestResultDto.ResultSet.Rows.Count);
}
else
{
 if (objRemoteRequestResultDto.RemoteException != null)
 {
 throw ErrorHandler.LogWrite(si, new XFException(si, objRemoteRequestResultDto.RemoteException));
 }
 else
 {
 BRApi.ErrorLog.LogMessage(si, "Remote Smart Integration Function Succeeded - no data/datatable returned");
 }
}

Here's an example to call the remote BR called "GetDataFromDB" (VB):

Copy
' Here we are telling it to specifically call a remote Smart Integration Function called GetDataFromDB at SIC Gateway called TestConnection with a method called RunOperation
Dim GatewayName As String = "" ' Name of the Gateway
Dim SICFunctionName As String = "GetDataFromDB" ' Name of the SIC Function from above example
Dim RemoteMethodName As String = "RunOperation" ' Name of the method inside the SIC Function that will be called.
Dim objRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayBusinessRule(si, SICFunctionName, Nothing, GatewayName, RemoteMethodName)
 
If objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.Success AndAlso objRemoteRequestResultDto.ResultSet IsNot Nothing AndAlso objRemoteRequestResultDto.ResultType = RemoteResultType.DataTable Then
 BRApi.ErrorLog.LogMessage(si, "Data Returned - Rows:" & objRemoteRequestResultDto.ResultSet.Rows.Count)
Else
 If objRemoteRequestResultDto.RemoteException IsNot Nothing Then
 Throw ErrorHandler.LogWrite(si, New XFException(si, objRemoteRequestResultDto.RemoteException))
 Else
 BRApi.ErrorLog.LogMessage(si, "Remote Smart Integration Function Succeeded - no data/datatable returned")
 End If
End If

GetRemoteDataSourceConnection

This remote business rule will return the connection string associated with a Local Gateway Configuration Data Source.

NOTE: Requires allowRemoteCodeExec = True on Smart Integration Local Gateway.

Parameter details:

  • Data Source: The name of the Local Gateway Configuration Data Source.

Here is the rule in C#:

Copy
// SIC Function to get configured connection string from SIC Gateway
namespace OneStream.BusinessRule.SmartIntegrationFunction.GetRemoteDataSourceSample
{
 public class MainClass
 {
 public DataTable RunOperation()
 {
 DataTable dataTableResults = new DataTable();
             // Get the remotely defined connection string
 string connectionString = OneStreamGatewayService.APILibrary.GetRemoteDataSourceConnection(""); // enter name of DB Connection
 SqlConnection conn = new SqlConnection(connectionString);
            // Insert custom code
 return dataTableResults;
 }
 }
}

Here is the rule in VB.NET :

Copy
' SIC Function to get configured connection string from SIC Gateway
Namespace OneStream.BusinessRule.SmartIntegrationFunction.GetRemoteDataSource_VB
 Public Class MainClass
 Public Shared Function RunOperation() As DataTable
 Dim dataTableResults As New DataTable 
 ' Get the remotely defined connection String
 Dim connectionString As String = OneStreamGatewayService.APILibrary.GetRemoteDataSourceConnection("") ' enter name of DB Connection
 Dim conn As SqlConnection = New SqlConnection(connectionString)
 ' Insert custom code
 
 Return dataTableResults
 End Function
 End Class
End Namespace

GetRemoteGatewayJobStatus

This BR API returns the status or the results of a previously remotely queued job invoked against a specified Smart Integration Connector Local Gateway host.

NOTE: Requires allowRemoteCodeExec = true on Smart Integration Service.

Parameter details:

  • si: SessionInfo object used to create connection objects

  • JobID: GUID of remote job ID returned upon successful call to ExecRemoteGatewayJob

  • remoteHost: Name of remote host to invoke operation (Smart Integration Connector Name)

The sample below invokes a job as part of a data management job inside a OneStream extender rule. The example demonstrates a simple Smart Integration Function that sleeps 2 seconds 1000 times in a loop simulating a long running task. The corresponding extender rule illustrates how this long running function can be invoked as a job, returning a job ID and subsequently polled until it's completed.

It would be typical to invoke long running jobs as part of a Data management/Extender Rule and the code below is an example on how this could be accomplished in C#:

Copy
[6:53 PM] Connor Shields
// Invoke long running job as part of a Data management/Extender rule
public object Main(SessionInfo si, BRGlobals globals, object api, ExtenderArgs args)
{
 Guid jobID;
 RemoteRequestResultDto objRemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayJob(si, "LongRunningTest", null/* TODO Change to default(_) if this is not a reference type */, "testConnection", string.Empty);
 
 if ((objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.JobRunning))
 {
 jobID = objRemoteRequestResultDto.RequestJobID;
 BRApi.ErrorLog.LogMessage(si, "Remote Job Queued and Running - JobID: " + jobID.ToString());
 
 for (var loopControl = 0; loopControl <= 10; loopControl++)
 {
 System.Threading.Thread.Sleep(2000);
 RemoteJobStatusResultDto objJobStatus = BRApi.Utilities.GetRemoteGatewayJobStatus(si, jobID, "testconnection2");
 if ((objJobStatus.RemoteJobState == RemoteJobState.Running))
 BRApi.ErrorLog.LogMessage(si, "Remote Job Still running - JobID: " + jobID.ToString());
 else if ((objJobStatus.RemoteJobState == RemoteJobState.Completed)
 )
 {
 // Checking the return type from the remote job
 if (!(objJobStatus.RemoteJobResult.ResultSet == null))
 {
 var xfDT = new XFDataTable(si, objJobStatus.RemoteJobResult.ResultSet, null, 1000);
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Datatable Returned - JobID: " + jobID.ToString());
 return null;
 }
 else if (!(objJobStatus.RemoteJobResult.ResultDataSet == null))
 {
 var xfDT = new XFDataTable(si, objJobStatus.RemoteJobResult.ResultDataSet.Tables[0], null, 1000);
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Dataset Returned - JobID: " + jobID.ToString());
 }
 else if (!(objJobStatus.RemoteJobResult.ObjectResultValue == null))
 {
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Object Returned - JobID: " + jobID.ToString());
 return null;
 }
 }
 else if ((objJobStatus.RemoteJobState == RemoteJobState.JobNotFound))
 {
 BRApi.ErrorLog.LogMessage(si, "Remote Job Not Found - JobID: " + jobID.ToString());
 return null;
 }
 else if ((objJobStatus.RemoteJobState == RemoteJobState.RequestTimeOut))
 {
 BRApi.ErrorLog.LogMessage(si, "Remote Job Timed Out - JobID: " + jobID.ToString());
 return null;
 }
 else if ((objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.Exception))
 BRApi.ErrorLog.LogMessage(si, "Exception During Exeuction of Job: " + objRemoteRequestResultDto.RemoteException.ToString());
 }
 }
 else if ((objRemoteRequestResultDto.RemoteResultStatus == RemoteMessageResultType.Exception))
 BRApi.ErrorLog.LogMessage(si, "Exception Executing Job: " + objRemoteRequestResultDto.RemoteException.ToString());
 else
 BRApi.ErrorLog.LogMessage(si, "General Job Execution Error - State: " + objRemoteRequestResultDto.RemoteResultStatus.ToString());
 return null;
}
 

Here is the example in VB:

Copy
' Invoke long running job as part of a Data management/Extender rule
Public Function Main(ByVal si As SessionInfo, ByVal globals As BRGlobals, ByVal api As Object, ByVal args As ExtenderArgs) As Object
 Dim jobID As Guid
 Dim objRemoteRequestResultDto As RemoteRequestResultDto = BRApi.Utilities.ExecRemoteGatewayJob(si, "LongRunningTest", Nothing, "testConnection",String.Empty)
 
 If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.JobRunning) Then
 jobID = objRemoteRequestResultDto.RequestJobID
 BRApi.ErrorLog.LogMessage(si, "Remote Job Queued and Running - JobID: " & jobID.ToString())
 'Example waiting 20 seconds for job to complete
 For loopControl = 0 To 10
 System.Threading.Thread.Sleep(2000)
 Dim objJobStatus As RemoteJobStatusResultDto = BRApi.Utilities.GetRemoteGatewayJobStatus(si, JobID, "testconnection2")
 If (objJobStatus.RemoteJobState = RemoteJobState.Running)
 BRApi.ErrorLog.LogMessage(si, "Remote Job Still running - JobID: " & jobID.ToString())
 Else If (objJobStatus.RemoteJobState = RemoteJobState.Completed)
 ' Checking the return type from the remote job
 If (Not objJobStatus.RemoteJobResult.ResultSet Is Nothing) Then
 Dim xfDT = New XFDataTable(si,objJobStatus.RemoteJobResult.ResultSet,Nothing,1000)
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Datatable Returned - JobID: " & jobID.ToString())
 Return Nothing
 Else If (Not objJobStatus.RemoteJobResult.ResultDataSet Is Nothing) Then
 Dim xfDT = New XFDataTable(si,objJobStatus.RemoteJobResult.ResultDataSet.Tables(0),Nothing,1000)
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Dataset Returned - JobID: " & jobID.ToString())
 Return Nothing
 Else If (Not objJobStatus.RemoteJobResult.ObjectResultValue Is Nothing) Then
 BRApi.ErrorLog.LogMessage(si, "Remote Job Completed - Object Returned - JobID: " & jobID.ToString())
 Return Nothing
 End If
 Else If (objJobStatus.RemoteJobState = RemoteJobState.JobNotFound)
 BRApi.ErrorLog.LogMessage(si, "Remote Job Not Found - JobID: " & jobID.ToString())
 Return Nothing
 Else If (objJobStatus.RemoteJobState = RemoteJobState.RequestTimeOut)
 BRApi.ErrorLog.LogMessage(si, "Remote Job Timed Out - JobID: " & jobID.ToString())
 Return Nothing
 Else If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.Exception)
 BRApi.ErrorLog.LogMessage(si, "Exception During Exeuction of Job: " & objRemoteRequestResultDto.RemoteException.ToString())
 End If
 Next
 Else ' Exception occuring immediately during compile/initial run
 If (objRemoteRequestResultDto.RemoteResultStatus = RemoteMessageResultType.Exception)
 BRApi.ErrorLog.LogMessage(si, "Exception Executing Job: " & objRemoteRequestResultDto.RemoteException.ToString())
 Else
 BRApi.ErrorLog.LogMessage(si, "General Job Execution Error - State: " & objRemoteRequestResultDto.RemoteResultStatus.ToString())
 End If
 End If
 Return Nothing
End Function

GetSmartIntegrationConfigValue

This BR API allows access to the Local Gateway Local Application Data Settings. Accessing the remotely stored secret or customer-defined configuration values is done using a new "Remote" equivalent of the BR API namespace. This feature can be used to:

  • Reference configuration parameters in a remote business rule running on a Smart Integration Connector Local Gateway Server

  • Store credentials to network resources allowing the developer of remote business rules to reference values stored in the configuration file instead of having them hard-coded and viewable by anyone with permission to edit a business rule.

These configuration values are defined and edited using the Smart Integration Connector Local Gateway Configuration Utility. The API used to obtain these values is demonstrated in the full business rule example below:

NOTE: Requires allowRemoteCodeExec = True on Smart Integration Local Gateway.

Here is the rule in C#:

Copy
// SIC Function demonstrating GetSmartIntegrationConfigValue
namespace TestProject.OneStream.BusinessRule.SmartIntegrationFunction.SecretTester
{
 public class MainClass
 {
 public static @bool RunOperation()
 {
 string result;
 // APILibrary is the class containing new remote BRAPI methods
 // GetSmartIntegrationConfigValue returns the string value of a found configuration
 // element -- returns empty string if the specified key is not found
 result = APILibrary.GetSmartIntegrationConfigValue(""); //Enter config value name
 return true;
 }
 }
}

Here is another example in VB.NET:

Copy
' SIC Function demonstrating GetSmartIntegrationConfigValue
 
Namespace OneStream.BusinessRule.SmartIntegrationFunction.SecretTester
 
Public Class MainClass
 Public Shared Function RunOperation() as bool
 Dim result As String
 ' APILibrary is the class containing new remote BRAPI methods
 ' GetSmartIntegrationConfigValue returns the string value of a found configuration
 ' element -- returns empty string if the specified key is not found
 result = APILibrary.GetSmartIntegrationConfigValue("") ' Enter config value name
 Return True
 End Function
 End Class
End NameSpace

GetGatewayConnectionInfo

From a OneStream business rule, you can invoke this API to obtain gateway details such as:

  • GatewayName: Name of the remote gateway

  • GatewayVersion: Version of the Smart Integration Connector Gateway Service running on the remote host

  • RemoteGatewayPortNumber: Bound Port at Gateway, the port of the remote service this direct connection is associated with.

  • RemoteGatewayHost: Name of the remote host associated with the direct connection.

  • OneStreamPortNumber: Bound Port in OneStream, the port number defined within OneStream that refers/maps to the specified direct connection.

  • SmartIntegrationGatewayType: Type of the Smart Integration Connection (0=Database Connection, 1=Direct Connection)

This API is useful for direct connections where the port number is required before connecting to remote services such as sFTP or remote Web APIs because each endpoint defined in OneStream to Smart Integration Connector Local Gateways has a different port number and would need to be known by the business rule developer at design time. This API makes it easy to look up the remote port by knowing the name of the direct connection defined in OneStream. It returns other useful information outlined below:

Here is the rule in C#:

Copy
// GetGatewayConnectionInfo
var GatewayName = "" //Name of the Gateway
GatewayDetails gatewayDetailInformation = BRApi.Utilities.GetGatewayConnectionInfo(si, GatewayName);
int oneStreamPortNumber = gatewayDetailInformation.OneStreamPortNumber;

Here is the rule in VB:

Copy
' GetGatewayConnectionInfo
Dim GatewayName As String = "" ' Name of the Gateway
Dim objGatewayDetails As GatewayDetails = BRApi.Utilities.GetGatewayConnectionInfo(si, GatewayName)
Dim oneStreamPortNumber As Integer = objGatewayDetails.OneStreamPortNumber

Check OneStream Version

Remote business rules have the ability to provide logic based on the OneStream Version.

Here is the example rule in C#:

Copy
namespace OneStream.BusinessRule.SmartIntegrationFunction.version_test_csharp
{
    public class MainClass
    {
        public string RunOperation() 
        {
            #if ONESTREAM8_4_0_OR_GREATER
                // Code if true
            #else
                // Code if false
            #endif
        }
    }
}

Here is the example rule in VB:

Copy
Namespace OneStream.BusinessRule.SmartIntegrationFunction.version_test_vb
    Public Class MainClass
        Public Shared Function RunOperation() As String
            #If ONESTREAM8_4_0_OR_GREATER
                ' Code if true
            #Else
                ' Code if false
            #End If
        End Function
    End Class
End Namespace

BRApi.Utilities.IsGatewayOnline

The following business rule can check the status of Smart Integration Connector. You will need to replace "gateway-name" with the name of the gateway to be tested.

Here is the rule in C#:

Copy
// IsGatewayOnline
 
namespace OneStream.BusinessRule.Extender.TestHealthCheck
{
 public class MainClass
 {
 public const string GatewayName = "";
 
 public object Main(SessionInfo si, BRGlobals globals, object api, ExtenderArgs args)
 {
 try
 { 
 TestGatewayConnection(si, GatewayName);
 return null;
 }
 catch (Exception ex)
 {
 throw ErrorHandler.LogWrite(si, new XFException(si, ex));
 }
 }
 
 public void TestGatewayConnection(SessionInfo si, string gwName)
 {
 bool response = BRApi.Utilities.IsGatewayOnline(gwName);
 
 if (response)
 {
 BRApi.ErrorLog.LogMessage(si, $"Health Check Successful for {gwName}");
 }
 else
 {
 BRApi.ErrorLog.LogMessage(si, $"Health Check Failed for {gwName}");
 } 
 }
 }
}

Here is the rule in VB:

Copy
Namespace OneStream.BusinessRule.Extender.TestHealthCheck
 Public Class MainClass
 Public Const GatewayName As String = ""
 
 Public Function Main(ByVal si As SessionInfo, ByVal globals As BRGlobals, ByVal api As Object, ByVal args As ExtenderArgs) As Object
 Try
 TestGatewayConnection(si, GatewayName)
 Return Nothing
 Catch ex As Exception
 Throw ErrorHandler.LogWrite(si, New XFException(si, ex))
 End Try
 End Function
 
 Public Sub TestGatewayConnection(ByVal si As SessionInfo, ByVal gwName As String)
 Dim response As Boolean = BRApi.Utilities.IsGatewayOnline(gwName)
 
 If response Then
 BRApi.ErrorLog.LogMessage(si, $"Health Check Successful for {gwName}")
 Else
 BRApi.ErrorLog.LogMessage(si, $"Health Check Failed for {gwName}")
 End If
 End Sub
 End Class
End Namespace

Business Rules Compatibility

There are some business rules that are not compatible with Smart Integration Connector. If you attempt certain rules, you will run into the following error: This BR API is not compatible with Smart Integration Connector. Refer to Smart Integration Connector Remote BRs.

The following business rules are not compatible with Smart Integration Connector:

BRApi.Database.SaveCustomDataTable

Although, this business rule is not supported, the functionality can be achieved through a remote business rule. You can call this business rule using BRApi.Utilities.ExecRemoteGatewayBusinessRule.

Here is the rule in C#:

Copy
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Data.Common;
using System.Globalization;
using System.IO;
using System.Linq;
 
namespace OneStream.BusinessRule.SmartIntegrationFunction.SaveCustomDataTable
{
    public class MainClass
    {
        public void RunOperation()
        {
            var tableName = "";         // Enter the name of the table to update
            var connectionName = "";     // Enter the name of the configured database connection
            var connString = OneStreamGatewayService.APILibrary.GetRemoteDataSourceConnection(connectionName);
            var dataTable = new DataTable();
            using (var connection = new SqlConnection(connString))
            {
                connection.Open();
                var sql = $"SELECT * FROM {tableName}";
                var cmd = new SqlCommand(sql, connection);
                var adapter = new SqlDataAdapter();
                adapter.SelectCommand = cmd;    
                var commandBuilder = new SqlCommandBuilder(adapter);
                adapter.Fill(dataTable);
                // Add logic here to update values in DataTable                
                // Update database with changes to the DataTable
                adapter.UpdateCommand = commandBuilder.GetUpdateCommand();
                adapter.Update(dataTable);
            }
        }
    }
}

Here is the same rule VB:

Copy
Imports System
Imports System.Collections.Generic
Imports System.Data
Imports System.Data.Common
Imports System.Globalization
Imports System.IO
Imports System.Linq
Namespace OneStream.BusinessRule.SmartIntegrationFunction.SaveCustomDataTableVB
    Public Class MainClass
        Public Sub RunOperation()
         Dim tableName = ""            ' Enter the name of the table to update
         Dim connectionName = ""        ' Enter the name of the configured database connection
         Dim connString = OneStreamGatewayService.APILibrary.GetRemoteDataSourceConnection(connectionName)
         Dim dataTable = New DataTable()
         Using connection = New SqlConnection(connString)
         connection.Open()
         Dim sql = $"SELECT * FROM {tableName}"
         Dim cmd = New SqlCommand(sql, connection)
         Dim adapter = New SqlDataAdapter()
         adapter.SelectCommand = cmd
         Dim commandBuilder = New SqlCommandBuilder(adapter)
         adapter.Fill(dataTable)
                ' Add logic here to update values in DataTable
                ' Update database with changes to the DataTable
         adapter.UpdateCommand = commandBuilder.GetUpdateCommand()
         adapter.Update(dataTable)
         End Using
        End Sub
    End Class
End Namespace

BRApi.Database.InsertOrUpdateRow
BRApi.Database.DeleteRows

Although, these business rules are not supported, inserting, deleting and updating rows can be accomplished through the same remote business rule referenced above. You can call this business rule using BRApi.Utilities.ExecRemoteGatewayBusinessRule. You will insert your logic at the specific comment in the remote business rule.

SQL Bulk Copy

Use of the SQL Bulk Copy class is not supported to copy to and from databases accessed over Smart Integration Connector. Currently, there is not a workaround available.

SQL Transactions

Use of the SqlTransaction class is currently only supported in Smart Integration Connector Functions / remote business rules.