General Architecture - Where to store handlers, pipelines, and plugins PDF
Document Details
Uploaded by SupportedAstatine4145
Tags
Summary
This document describes the general architecture of Optimizely Configured Commerce, focusing on handlers, and pipelines. It details how handlers process requests, part of a handler chain, and how pipelines execute reusable business logic. It also explains adding and replacing pipelines.
Full Transcript
Handlers Describes handlers in Optimizely Configured Commerce. Suggest Edits Handlers are objects that are responsible for the heavy lifting of objects and processing of business logic. In the Configured Commerce architecture, handlers take control right after the REST API receives...
Handlers Describes handlers in Optimizely Configured Commerce. Suggest Edits Handlers are objects that are responsible for the heavy lifting of objects and processing of business logic. In the Configured Commerce architecture, handlers take control right after the REST API receives and initially processes the request. Each handler is part of a larger handler chain that operates on specific objects. When a handler chain is executed, each handler in the chain is executed in a configured order until no more handlers are available in the chain. Below are some existing handler chains that showcase just some of the use cases for handlers. GetCartHandler chain – This chain retrieves and returns the cart object for the currently authenticated user or using a specific cart identifier. This chain also includes handlers that retrieve cart-related data, like cart lines, shipping costs, taxes, and available carriers. This chain is executed indirectly throughout the Storefront, including when a user visits the Cart page, navigates to the Checkout Address page, and proceeds to the Review and Pay page. GetProductHandler chain – This chain retrieves a product given a product identifier. This chain is executed when a user visits the Product Detail page or searches for a product on the Quick Order page. Handler chains make it possible to add new handlers and insert new business logic into the chain. See Work with handlers to add a new handler to a handler chain. Add and replace pipelines Describes how to add and replace pipelines. Suggest Edits Pipelines are similar to handler chains. They are made up of one or more classes, called pipes. Pipelines are reusable portions of business logic that are not transactional. In previous versions of Configured Commerce, the logic now in pipelines used to exist in handler helpers and utilities. However, the helpers and utilities did not offer an easy way to modify the logic without affecting backwards compatibility. Future service packs and releases could more easily break any custom logic you had managed to inject. Pipelines are a better answer to this problem. Some handler chains need to use the same logic, so pipelines accommodate that need. For example, the catalog pipeline named "CreateProductDtos" is responsible for creating ProductDto objects from a collection of Product data objects. The pipes within a pipeline are executed in order and execution automatically proceeds to the next pipe. Unlike handler chains, pipelines can be executed wherever the logic is needed. Individual pipes within a pipeline can choose to halt execution of the rest of the pipeline by returning an error code or exiting the pipeline. Just like handler chains, the design of pipelines allows you to inject your own logic into the pipeline. Add a pipe to a pipeline For a pipe to be used within a pipeline, it must do the following: Implement the IPipe interface Return a result from the "Execute" method Specify an order via the "Order" property The IPipe interface requires the pipe to implement the "Execute" method, specify pipe order using the "Order" property, and associate the pipe with a pipeline. The "Execute" method is the sole entry point into a pipe. This method also contains all of the business logic used by the pipe to complete it's work. The "Order" property is used to specify the ordering of the pipe within the pipeline. Pipes are ordered in ascending order within a pipeline using the values specified by each pipe in the "Order" property. Pipes within pipelines start with the pipe with the lowest order value. By default, all pipelines have at least one pipe with an order value of 100. From there, additional pipes usually increment the order by 100. For example, if a pipeline has three pipes, the order values would be 100, 200, and 300. This ordering scheme allows you to both insert a new pipe in between existing pipes or add a new pipe to the start or end of a pipeline. To insert a new pipe into the second position in the pipeline, the pipe could be given an order value between 101 and 199. To add the pipe to the start or end of the pipeline, the pipe should be given an order less than 100 or greater than 300, respectively. C# // A pipe is associated with a pipeline according to the parameter and result object types (TIn and TOut). // All pipes with the same object types will be executed within the same pipeline. // Below is a code sample explaining the association further. // These two pipes are part of the same pipeline because they both declare the same parameter and result object types. public class CalculateOrderLines : IPipe public class CalculateOrderTotal : IPipe // This pipe is part of a different pipeline because // it declares different parameter and result object types than the two pipes above. public class GetRoles : IPipe Once you have configured the new pipe, you can build the solution and run the application. The next time the pipeline executes, your new pipe should be included in the pipeline. To help explain the pipeline further, the following section walks through adding a new pipe to a pipeline. Add a pipe to the FormatLabel pipeline The following section adds a new pipe to the FormatLabel customer pipeline. This new pipe will add the customer's zip code to the label. Prerequisite Configured Commerce SDK installed 1. In your Extensions project, create a new pipe class named AddCustomerZipCode. C# public class AddCustomerZipCode { } 2. Implement the IPipe interface. For the TIn and TOut parameter and result object types, specify FormatLabelParameter and FormatLabelResult, respectively. Remember, this is how a pipe is associated with a pipeline. It's important to specify the correct types. C# public class AddCustomerZipCode : IPipe { } 3. Specify a value for the "Order" property. Remember, all pipelines start with a pipe that has an order of 100. Within the pipeline, all pipes provided by Configured Commerce Cloud increment the order by 100. The FormatLabel pipeline has only one pipe with an order value of 100. Specifying an order of 3000 for the new pipe is overkill, but it ensures that this new pipe comes after all of the original pipes. C# public int Order => 3000; 4. Implement the "Execute" method. Remember, this is the sole entry point to the pipe. Additionally, this method must either continue the pipeline or exit it. These methods are explained in the sample below. C# public FormatLabelResult Execute(IUnitOfWork unitOfWork, FormatLabelParameter parameter, FormatLabelResult result) { if (parameter.Customer == null) { // If you set the ResultCode to the ResultCode.Error value, // the pipeline will exit. You should also specify a more accurate // SubCode and error message. The pipe should immediately return // to avoid performing unnecessary work. result.ResultCode = ResultCode.Error; result.SubCode = SubCode.NotFound; result.Messages.Add(new ResultMessage { Message = "A customer is required to format the label." }); return result; } if (!parameter.Customer.PostalCode.IsEmpty()) { result.Label += parameter.Customer.PostalCode; } // If you want to exit the pipeline, but there is no // need to indicate an error, you can set the result.ExitPipeline // flag to true. The pipe should immediately return to // avoid performing unnecessary work. //result.ExitPipeline = true; // Returning the result without flagging the ExitPipeline property // or indicating an error continues execution of the pipeline. // Control is handed over to the next pipe. return result; } For reference, below is the completed pipe class. C# public class AddCustomerZipCode : IPipe { public int Order => 3000; public FormatLabelResult Execute(IUnitOfWork unitOfWork, FormatLabelParameter parameter, FormatLabelResult result) { if (parameter.Customer == null) { // If you set the ResultCode to the ResultCode.Error value, // the pipeline will exit. You should also specify a more accurate // SubCode and error message. The pipe should immediately return // to avoid performing unnecessary work. result.ResultCode = ResultCode.Error; result.SubCode = SubCode.NotFound; result.Messages.Add(new ResultMessage { Message = "A customer is required to format the label." }); return result; } if (!parameter.Customer.PostalCode.IsEmpty()) { result.Label += parameter.Customer.PostalCode; } // If you want to exit the pipeline, but there is no // need to indicate an error, you can set the result.ExitPipeline // flag to true. The pipe should immediately return to // avoid performing unnecessary work. //result.ExitPipeline = true; // Returning the result without flagging the ExitPipeline property // or indicating an error continues execution of the pipeline. // Control is handed over to the next pipe. return result; } } 5. Build your solution. If the rest of your application is set up correctly, the next time you select a customer, you should see that the postal code was added to the customer label. The customer label can be viewed in the customer dropdown when selecting a customer or in the header after you log in if you click your username. While adding a new pipe may work for most use cases, you may find a time where you need to replace an existing pipe. Replace a pipe in a pipeline If you find a pipeline that requires additional business logic and inserting a pipe before or after an existing pipe is not sufficient, you may choose to replace the existing pipe. In order to do this, you must configure the new pipe correctly. To replace an existing pipe, the new pipe must: Implement the IPipe interface Return a result from the "Execute" method Specify an order via the "Order" property Be named the same as the pipe being replaced. This is an additional requirement compared to adding a new pipe. Using the FormatLabel customer pipeline as an example again, the following pipe will replace the existing FormatLabel pipe. C# public class FormatLabel : IPipe { // The order value does not need to match the pipe // that is being replaced, but it is best practice // to match the order value. In this configuration, // the pipe has been completely replaced and more // pipes can be added to the pipeline. public int Order => 100; public FormatLabelResult Execute(IUnitOfWork unitOfWork, FormatLabelParameter parameter, FormatLabelResult result) { result.Label = "new format"; return result; } } When this pipe is implemented, the application will display the text "new format" instead of the customer's name, address, city, and state. Note You cannot "remove" a pipe, but you can create an implementation of it that does nothing. Download WIS Download the Windows Integration Service installer for Configured Commerce. Suggest Edits If you do not see the WindowsIntegrationService folder in your local copy of Configured Commerce, download and unzip the following folder into your Configured Commerce project folder and follow the installation instructions: WindowsIntegrationService