We will be creating a .NET Core Console application and an integration that requests GUID's from an external webservice when requested by the user. Data will be stored in a SQL LocalDB.
Create a .NET Core 3.1 Console application
We need a bunch of packages, first we get the Nebol packages:
Install-Package NebolIntegration Install-Package NebolIntegration.EntityFramework
And then the additional ones:
Install-Package SharpRepository.EfCoreRepository # EF Core support for SharpRepository Install-Package Microsoft.EntityFrameworkCore.SqlServer # MS SQL support for Entity Framework Install-Package SharpRepository.Ioc.Microsoft.DependencyInjection # MS dependency injection support for SharpRepository Install-Package NewtonSoft.Json # needed for some JSON converting later
SharpRepository.EfCoreRepository is needed for EF Core support for SharpRepository Microsoft.EntityFrameworkCore.SqlServer is needed for MS SQL support for Entity Framework SharpRepository.Ioc.Microsoft.DependencyInjection is needed for MS dependency injection support for SharpRepository NewtonSoft.Json is needed for some JSON converting later on
The SharpRepository.EfCoreRepository installation will add a default settings file to your project named repository.efCore.json file, it's for the configuration of SharpRepository. Set the “Copy to Output Directory” property of the file to “Copy if newer”.
Replace the dbContextType line with:
"dbContextType": "NebolIntegration.EntityFramework.NebolIntegrationDbContext, NebolIntegration.EntityFramework"
The connection string will look something like this for SQL LocalDB:
"Data Source=(LocalDb)\MSSQLLocalDB;Initial Catalog=integration;AttachDBFilename=E:\NebolIntegrationSample.mdf";
or something like this for MS SQL Server:
"Server=mssql;user id=myuser;password=sdfsf4rerweew;database=test_integrations";
You can add it to the repository.efCore.json file or use DI to add it in code in a way you prefer.
Now let's get coding.
First, the actual integration. We'll use a public webservice that just returns a UUID. Very simple.
We create a class derived from SystemIntegration. We supply it with a few parameters that specifies how the integration is managed (will be discussed later), and we override the ProcessRequest() and ProcessResponse() methods. The ProcessRequest() method is called when a new task is found in the queue. It does what needs to be done, in this case call a simple webservice. The ProcessResponse() handles the response recieved from the webservice, in this case it just outputs the UUID that is fetched.
// Representation of a successful response public class FetchedUUID { public string UUID { get; set; } } // Our integration class public class FetchUUID : SystemIntegration { // this name is used to uniquely identify this integration public static readonly new string TechnicalName = "FETCH_UUID"; public FetchUUID(ISharpRepositoryConfiguration config) : base(config, TechnicalName) { Name = "UUID Fetcher"; // friendly name Description = "Fetches a new UUID from httpbin.org"; RetryScheme = "30sx3"; CleaningScheme = "?"; // ignore for now Direction = DirectionEnum.Outgoing; ExpectedSecondsToComplete = 10; PollingIntervalSeconds = 60 * 3; // three minutes ReferenceDescription = string.Empty; // no reference in this integration InitiateIntegration(); } public override IntegrationResponse ProcessRequest(IntegrationQueue iqueue) { IntegrationResponse resp = new IntegrationResponse(); // any exception will be caught by caller so this is fine using (var wc = new System.Net.WebClient()) resp.Response = wc.DownloadString("https://httpbin.org/uuid"); resp.Status = StatusEnum.Success; return (resp); } public override IntegrationResponse ProcessResponse(IntegrationQueue iqueue, IntegrationResponse response) { var fuuid = JsonConvert.DeserializeObject<FetchedUUID>(response.Response); Console.WriteLine("UUID: " + fuuid.UUID); return (response); } }
Now let's set everything up.
A couple of static variables in the Program class:
static Engine engine; static ServiceCollection services;
static void SetupIntegration() { var config = new ConfigurationBuilder() .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) .AddJsonFile("repository.efCore.json") .Build(); var section = config.GetSection("sharpRepository"); ISharpRepositoryConfiguration sharpConfig = RepositoryFactory.BuildSharpRepositoryConfiguation(section); // roundabout way to get connection string from the config section var connection_string = sharpConfig.Repositories.Where(item => item.Name.Equals("efCore")).First() .Attributes.Where(item => item.Key.Equals("connectionString")).First().Value; // create an instance of the DB context so we can create the schema (if it doesn't exist) var optionsBuilder = new DbContextOptionsBuilder<NebolIntegrationDbContext>(); optionsBuilder.UseSqlServer(connection_string); using (var db = new NebolIntegrationDbContext(optionsBuilder.Options)) db.Database.EnsureCreated(); // setup dependency injection services = new ServiceCollection(); services.AddDbContext<NebolIntegrationDbContext>(options => options.UseSqlServer(connection_string), ServiceLifetime.Transient); services.UseSharpRepository(section); var serviceProvider = services.BuildServiceProvider(true); // create integration engine engine = new Engine(sharpConfig); // create instance of our integration class var fetchuuid = new FetchUUID(sharpConfig); // add it to the engine engine.SystemIntegrations.Add(fetchuuid); }
NebolIntegration takes advantage of NebolLogger, so we will set that up as well. In this case we'll just use the color-coded console logger:
protected static void InitLoggingFramework() { Destination cc = new Destination_ColorConsole(); Logger.Instance.Destinations.Add(cc); }
Now let's start the integration engine:
engine.StartIntegrations();
And we'll add a simple console input loop:
string command; Console.WriteLine("Press ENTER to submit request to integration engine. Q to quit."); do { command = Console.ReadLine(); if (command.ToLower() != "q") engine.Submit(FetchUUID.TechnicalName); } while (command.ToLower() != "q");
(In a real-world scenario, the submit “engine.Submit(FetchUUID.TechnicalName)” will likely be made in a different application, on a different computer, for example a webserver where the user clicks a button on a webpage, but for the sake of simplicity we're doing it here in the same sample application.)
Finally, the cleanup:
engine.StopIntegrations();
This will shutdown the engine NICELY. It will not abort a running integration job. If you have multiple integrations it will signal them all that it's time to shutdown then wait nicely until they are all done.
When run, the program should output this:
(include logger & output)
As instructed, press ENTER to submit a request to the engine.
Congrats! A call was made to the webservice and the response processed. Your integration is up and running!
Next: NebolIntegration_Database_and_Flow - So what happened?