Skip to content

Integration

The Business Rules dedicated project

Activities are not a component that is exclusive to Business Rules. In fact, it is widely being implemented in several features across the suite environment. Hence, we intend to keep a clear segregation of concerns and maintain everything related to BusinessRules in its own project, where activities intended to be used by Business Rules should be contained.

Note

This approach may likely lead to some code duplication in case two activities perform a very similar task, yet only one of them has been defined as a BR activity. In order to avoid this, abstract away activities task logic into a separate service.

The client module

Defining activities and their behavior is only half the work done. We still need to provide a way for making Business Rules backend service be aware of the existence and the details of each activity and the possible events that could act as triggers.

The client module is the mechanism responsible for exposing activities and events that are spread across several Bounded Contexts to our central administration service for Business Rules.

Putting things together

The suggested approach to integrate with Business Rules is by running the template, which will create the project and provide basic scaffolding for all components:

Text Only
    dotnet new businessrules --BoundedContextName --ActivityName --EventName

Important

ALWAYS run this template from inside dotnet/ folder.

About the template command:

  • BoundedContextName is required and refers to the current BoundedContext which is being integrated with BusinessRules.
  • ActivityName is optional and will create basic scaffolding for a single activity.
  • EventName is optional and will create basic scaffolding for a single event.

Note

Following our defined conventions, always suffix activities and events with Activity and Event respectively when running the template.

This will create a new project called ITsynch.Suite.BoundedContextName.BusinessRules containing a couple directories and files, specifically:

  • Activities/
  • Extensions/
  • BoundedContextBusinessRulesModule.cs

Also, a Contracts project that includes a single file destined for declaring constants.

  • BoundedContextBusinessRulesConstants

You can add files and folders at will, but ultimately respecting this structure and the framework conventions in general. The provided module depends on BusinessRulesClientModule and provides an API for exposing both events and activities by making use of the options pattern. Yet, we propose to abstract this configuration into separate extension files in order to improve readability.

The client options includes methods for declaring both activities and events, encapsulating the logic required to expose these to Business Rules.

For each Activity and Event you are required to define a CorrelationId. These should be placed inside the BoundedContextBusinessRulesConstants file in the contracts project.

C#
1
2
3
4
5
6
public static class BoundedContextBusinessRulesConstants
{
    public static readonly Guid MyEventCorrelationId = new Guid("58260000-add4-54e1-6329-08da68c3e555");

    public static readonly Guid MyActivityCorrelationId = new Guid("08410000-add4-54e1-4613-08da68c66045");
}

More contextual data, such as DisplayName and Description can be provided as required or optional parameters.

BusinessRulesClientModuleOptions receives callbacks for both activity and event builders, which can (and should) be defined inside the Extensions folder as follows:

C#
public static class ExposedActivities
{
    public static BusinessRulesClientModuleOptions ExposeNotifyPositionAssignedActivity(this BusinessRulesClientModuleOptions opts)
    {
        opts.ExposeActivity<NotifyPositionAssignedActivity, NotifyPositionAssignedActivity.Arguments, DeconstructDepartmentActivity.Outputs>(
            PositionsBusinessRulesConstants.NotifyPositionAssignedActivityCorrelationId,
            "Notify Position assigned",
            "Notifies that a position's assignee has been changed.");
        return opts;
    }
}

An activity's arguments will automatically be discovered and mapped. In case your activity requires to define outputs, you can optionally expose them in a similar way.

Events are exposed by defining a DTO which represents the set of properties from the MassTransit message that you expect to be part of the Business Rule arguments. Note that these properties should match in name, since there is no explicit mapping between both classes.

C#
public record PositionChanged : IBusinessRulesEvent
{
    /// <summary>
    /// Gets or sets the user correlation id.
    /// </summary>
    public Guid CorrelationId { get; set; }

    /// <summary>
    /// Gets or sets the correlation id of the position assigned to the user.
    /// </summary>
    public Guid? AssignedPositionCorrelationId { get; set; }
}

Once done, we can expose this event and correlate it to a MassTransit message using the options API.

C#
public static class ExposedEvents
{
    public static BusinessRulesClientModuleOptions ExposePositionUpdatedEvent(this BusinessRulesClientModuleOptions opts)
    {
        opts.ExposeEvent<Application.PositionChanged, BusinessRules.PositionChanged>(
            PositionsBusinessRulesConstants.PositionUpdatedEventCorrelationId,
            "Position Changed",
            "Notifies that a position has been changed.");
        return opts;
    }
}

Once done, we can update the client module options configuration by calling our extension methods:

C#
public class PositionsBusinessRulesModule : SuiteModule
{
    public override void SetupModule(IModuleBuilder builder)
    {
        base.SetupModule(builder);
        builder.DependsOn<BusinessRulesClientModule, BusinessRulesClientModuleOptions>(opts =>
        {
            opts
                .ExposeNotifyPositionAssignedActivity()
                .ExposePositionUpdatedEvent();
        });
    }
}

Depending on this module from your backend service application module will automatically execute the publish process the next time you start the service.

Some considerations about the integration process:

  • Define activities following the conventions defined in Fundamentals section.
  • Keep activity and event names consistent.
  • Add a configuration method for each activity/event to be exposed.
  • Publish process can be toggled off by using the client module options. This can be profitable for integration tests.