🚀Speed up implementation with hands-on, face-to-face training from the developer.
Inline Scripts
Models inside Jube are extensible via the use of Inline Scripts. Inline Scripts use the processing context after preparation of model invocation headers, Request XPath and Inline Functions. Inline Scripts exist as a means to integrate external systems and enrich payload values.
Inline Scripts once registered in the database are available for all models, however they must be registered in a model for the payload to be populated in the same manner as Request XPath (i.e. it is available for the rules in the Payload collection).
The system wide Inline Script (which can be added only through direct entry to the database table EntityAnalysisInlineScript as follows) is as per the following specification, and is intended to showcase the following functionality:
- The required signatures for the invocation method, implementring IInlineScript required interface.
- The exposure of public properties to make data available to context payload and processing.
- The availability of attributes to allow for similar functionality to that available in Request XPath on public properties.
- The implementation of the ExecuteAsync() method from IInlineScript interface.
select * from EntityAnalysisInlineScript
The EntityAnalysisInlineScript table in the database contais the following fields:
| Field | Example | Description |
|---|---|---|
| Code | As below. | The Inline Script source code, likely validated externally using the Jube.Sandbox project. |
| Dependency | IPTO.World.dll | Any third party DLL’s required are declared here, separated with ;. The DLL must be copied to the same directory as the Jube.Engine binary. |
| Name | Example Inline Script | The name of the InlineScript, and available in model configuration. |
| LanguageId | 2 | 1 for Visual Basic, 2 for C#. |

The database contains the following Visual Basic code to provide a “straight through”, No IO, demonstration in the default environment, while also showing a minimal VB.net example (which is to say LanguageId = 1):
Imports System
Imports System.Net.Http
Imports System.Threading
Imports System.Threading.Tasks
Imports Newtonsoft.Json.Linq
Imports Jube.Engine.Attributes
Imports Jube.Engine.EntityAnalysisModelInvoke.Context
Imports Jube.Engine.Interfaces
Public Class IssueOTP
Implements IInlineScript
Public Property OTP As String
Public Async Function ExecuteAsync(context As Context) As Task Implements IInlineScript.ExecuteAsync
OTP = RandomDigits(6)
End Function
Private Function RandomDigits(ByVal length As Integer) As String
Dim random = New Random()
Dim s As String = String.Empty
For i As Integer = 0 To length - 1
s = String.Concat(s, random.[Next](10).ToString())
Next
Return s
End Function
End Class
The Jube.Sandbox project meanwhile contains the following code C# (which is to say LanguageId = 2):
//The following are the minimum .Net libraries to make this work, however, if using the Jube.Sandbox, this will be shown, as the project file is set to not default any assemblies and will be a like for like compile.
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
//All assemblies are passed on the basis of what the Jube.App context is using, so nearly all libraries are supported.
using Newtonsoft.Json.Linq;
//The following are Jube libraries that contain the context and Inline Script attributes.
using Jube.Engine.Attributes;
using Jube.Engine.EntityAnalysisModelInvoke.Context;
using Jube.Engine.Interfaces;
public class Example : IInlineScript //Class entry point is the first implementation of IInlineScript found in reflection
{
//Attributes overlap with the same options available in Request XPath
[ReportTable] //ReportTable is evaluated on recall.
[ResponsePayload]//ResponsePayload is evaluated in model synchronization and used in model response preparation.
[Latitude] //Latitude is evaluated in model synchronization and is used during model activation watcher dispatch.
[Longitude] //Longitude is evaluated in model synchronization and is used during model activation watcher dispatch.
[SearchKey(SearchKeyTtlInterval = "h",
SearchKeyTtlIntervalValue = 1,
SearchKeyFetchLimit = 100,
SearchKeyCache = false,
SearchKeyCacheInterval = "d",
SearchKeyCacheValue = 1,
SearchKeyCacheSample = true,
SearchKeyCacheFetchLimit = 100,
SearchKeyCacheTtlInterval = "h",
SearchKeyCacheTtlValue = 1)] //SearchKey ensures that this is exposed in for aggregation in both the background engine.
public string? UserAgent { get; set; }//Public properties are available for processing, being analogous, when taken together with attributes, to a Request XPath entry
public async Task ExecuteAsync(Context context)//Method entry point. The Context object gives access to all resources that would otherwise be available during invocation.
{
//Example HTTP Call with the fetching of data from the context.
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
client.DefaultRequestHeaders.Add("IP", context.EntityAnalysisModelInstanceEntryPayload.Payload["IP"]);//Here we are looking at the context, and while we are only extracting data here, full access to all application resources are available in this context, such as logging.
var response = await client.GetStringAsync("https://postman-echo.com/get"); //Get the data from remote using the standard HTTP client.
//Example Parse and transpose to payload.
var jObject = JObject.Parse(response);//The response stream is processed using Newtonsoft
var userAgent = (string)jObject["headers"]?["user-agent"] ?? "Unknown";
UserAgent = userAgent;//Set the property. The data is now read from the property using reflection.
}
}
The Jube.Sandbox code, which is a project under the Jube solution, will provide the basis for further explanation as follows. C# is the recomended Inline Script language.
The Jube.Sandbox is a project in the Jube solution and is configured to diasslow implicit usings, and hence represents a tight representation of the codes runtime environment. The Jube.Sandbox has a program and main application entry point which allows for the creation of mock context:
using Jube.Dictionary;
using Jube.Engine.EntityAnalysisModelInvoke.Context;
using Jube.Engine.EntityAnalysisModelInvoke.Models.Payload.EntityAnalysisModelInstanceEntry;
var context = new Context {
EntityAnalysisModelInstanceEntryPayload = new EntityAnalysisModelInstanceEntryPayload
{
Payload = new DictionaryNoBoxing
{
{
"IP", "123.123.123.123"
}
}
}
};
var exampleInlineScript = new Example();
await exampleInlineScript.ExecuteAsync(context);
Therafter invoking the script set out above.
An InlineScript is a complete .NET class written in VB.net or C#, and starts out with all of the required using statements at the top of the class:
using System;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
using Jube.Engine.Attributes;
using Jube.Engine.EntityAnalysisModelInvoke.Context;
using Jube.Engine.Interfaces;
After the using statements, the class can be declared, implementing the IInlineScript interface, and named as desired ( it can be anything that is not a reserved C# token):
public class Example : IInlineScript
{
}
During syncronisation the IInlineScript interface implementation is inspected and the class taken to be the application entry point.
The class at a minimum must contain one method conforming to the following signature, and otherwise enforced as per the IInlineScript interface:
public async Task ExecuteAsync(Context context)
{
}
The ExecuteAsync() method is called on each and every invocation, taking the invocation context as a parameter.
The invocation context is a reference, hence updates to the context will be available in subsequent invocation pipeline processing, the same process calling the class upstream. To return values from the ExecuteAsync() method, simply set the value of a public property, as can be seen in the setting of UserAgent string as below:
public async Task ExecuteAsync(Context context)
{
using var client = new HttpClient();
client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
client.DefaultRequestHeaders.Add("IP", context.EntityAnalysisModelInstanceEntryPayload.Payload["IP"]);
var response = await client.GetStringAsync("https://postman-echo.com/get");
var jObject = JObject.Parse(response);
var userAgent = (string)jObject["headers"]?["user-agent"] ?? "Unknown";
UserAgent = userAgent;
Payload is exposed as a public property in the class with certain attribute decoration to emulate configuration available in Request XPath (keeping in mind that Inline Scripts serve much the same function, the aggregation of payload data before processing):
[ReportTable]
[ResponsePayload]
[Latitude]
[Longitude]
[SearchKey(SearchKeyTtlInterval = "h",
SearchKeyTtlIntervalValue = 1,
SearchKeyFetchLimit = 100,
SearchKeyCache = false,
SearchKeyCacheInterval = "d",
SearchKeyCacheValue = 1,
SearchKeyCacheSample = true,
SearchKeyCacheFetchLimit = 100,
SearchKeyCacheTtlInterval = "h",
SearchKeyCacheTtlValue = 1)]
public string? UserAgent { get; set; }
As a property declared with a type (e.g. Public Property Hello as String) the data type will be taken from the property type, supporting the following types only:
- String.
- Integer.
- Double.
- Date.
- Boolean.
Note that attribute decoration is available to achieve similar functionality as Request XPath documentation definitions, given that attributes are intended to emulate that functionality:
- ResponsePayload.
- ReportTable.
- Latitude
- Longitude
- SearchKey.
The existence of the ResponsePayload or ReportTable attribute is boolean inference, the existence of which will be taken to be true (inserting records into the ArchiveKey table), the absence is false. The SearchKey has more parameters available in the attribute:
| Value | Example |
|---|---|
| SearchKeyTtlInterval | h |
| SearchKeyTtlIntervalValue | 1 |
| SearchKeyFetchLimit | 100 |
| SearchKeyCache | false |
| SearchKeyCacheInterval | d |
| SearchKeyCacheValue | 1 |
| SearchKeyCacheSample | true |
| SearchKeyCacheFetchLimit | 100 |
| SearchKeyCacheTtlInterval | h |
| SearchKeyCacheTtlValue | 1 |
For each public property post invocation of the Inline Script, the public property value will be added to the context (in the same manner as Request XPath would be), and it does not need to be added manually (although it can be if for any reason the value needs to be silent).
In the event that the Inline Script fails to compile, a log entry will be written out with the compile errors at the ERROR level. It is advisable to compile the class as part of a separate project before promoting in the database, and the Jube.Sandbox project is made available for this purpose.
To promote an InlineScript to Jube, it is a question of inserting the class to a table in the database titled InlineScript:
insert into InlineScript
(Code,
Name,
Dependency,
Name,
LanguageId)
Values (@TheInlineScriptAsAbove,
@TheNameAvailableToEndUsers,
@AnyDLLsRequired,
@VisualBasicOrC#);
The Inline Script page exists to facilitate the registration of Inline Scripts for a model. The page is available by navigating through the menu as Models » References » Inline Scripts:

Add a new Inline Script by clicking an Entity Model entry in the tree towards the left hand side:

The parameters available to Inline Script allocation in the model are:
| Value | Description | Example |
|---|---|---|
| Inline Script | The Inline Script to be invoked on each request being made to the model. | Issue OTP |
Complete the page as above parameter and as follows:

Click Add to create the first version of this Inline Script allocation in the model:

Synchronise the model via Entity » Synchronisation and repeat the HTTP POST to endpoint https://localhost:5001/api/invoke/EntityAnalysisModel/90c425fd-101a-420b-91d1-cb7a24a969cc for response as follows:

Notice a field added as “OTP” in the response, which was also exposed by the Inline Script as being a property such that it is available in the rule builder and coder. Keep in mind that an Inline Script can expose many properties and add many elements, hence the name of the inline script itself has limited relevance.
Although the inline script set out above is basic, simply appending a value to the payload as if it had been passed originally in the request JSON, Inline Scripts can be used for far more complex integration and data processing.