User Tools

Site Tools


Sidebar

Nebol Software Projects:

.NET Class Libraries

Contact info:

johan@nebol.se

nebolintegration_basic_integration

NebolIntegration: Basic Integration - Creating your first integration

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.

NOT DONE! WORK IN PROGRESS!

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?

nebolintegration_basic_integration.txt · Last modified: 2021/11/03 17:24 by nebol