ExecRemoteGatewayBusinessRule

This is a core BRAPI 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 BRAPI 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 BRAPI, it is expected that remote calls should take no more than 2-3 minutes to return a result to the caller as this BRAPI will block until a result is returned. If longer running or sync operations are needed, consider using the ExecRemoteGatewayJobAndWait BRAPI.

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