Customizing method flow using entrypoints

Using entrypoints you can apply business logic that cannot be achieved with out-of-the-box OL HUB flows.

You can customize the OL HUB project flow by changing the code to reflect the business logic that you want. For example, defining a new authentication process or applying a complex mapping process that the automatic project flow does not support.

The project customization is done by adding an entrypoint to the existing flow. This is done manually in the code. Adding an entrypoint can be implemented on an entire flow, a step within the flow, or an exception.

You can add an entrypoint before the flow/step/exception, after, or both, as follows:

  • type: EntrypointType defines if the entrypoint is executed on a flow, a step, or an exception.
  • target: String is the name of the step/flow/exception that the entrypoint is executed on. 
  • global: Boolean indicates if the entrypoint is executed on a specific flow/step/exception or globally on every flow/step/exception.

To add a new entrypoint:

  1. Generate a project on the OL Hub (link to the procedure).

  2. In your files system, open the project zip file.

  3. Add a new class that implements one of the following Interfaces:

  • FlowEntrypoint to execute an entrypoint on a flow
  • StepEntrypoint to execute an entrypoint on step
  • ExceptionEntrypoint to execute an entrypoint on exception
  1. Find the name of the flow/step/exception that you want to customize in the metadata folder and then perform the required code changes.

Example:

The goal: To change the output response service of the insurance company’s oracle-db. 

The output that automatically comes from the API is:

{
   "policyObj": {
       "accountPolicyNumber": "123-45-6789",
       "customerId": "9876-54-321",
       "customerName": "Eli Israeli",
       "customerAddress": "32 Vernon Parkway",
       "customerCountry": "USA",
       "customerState": "New York",
       "customerZip": "1234",
       "customerBirthDate": "2021-01-31T12:30:48.000+0000",
       "policyEndDate": "2021-01-31T12:30:48.000+0000",
       "policyType": "Delta Juliett India",
       "typeDescription": "Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.",
       "monthlyPayment": "50000",
       "quarteryPayment": "500000",
       "yearlyPayment": "40000",
       "currency": "USD",
       "createdDate": "2021-03-15T16:15:15.000+0000",
       "lastUpdate": "2021-03-15T16:15:29.628+0000",
       "locked": "N"
   }
}

The automatic output returns the following fields with customer address details:

"customerAddress": "32 Vernon Parkway",

"customerCountry": "USA",

"customerState": "New York",

This form of data presentation is not suitable for the new interface that this insurance company uses and they need to present these values in the same line. In order to present all three values in the same line, you need to use an entrypoint to apply complex mapping that merges three values into one, as follows:

To merge three address values into one after the Mapping step, add a new class and perform the required changes, as follows:

@Component
public class FullAddressStepEntrypoint implements StepEntrypoint {

 private static final String STEP_NAME = "output-mapping-step-200";
 //step name will be unique in the future.

 @Override
 public String getTarget() {
  return STEP_NAME;
 }

 public void after(@NotNull FlowContext ctx) {

   JsonObject data = ctx.extractFromContextData(STEP_NAME);
   String Address = (String) ctx.getStepFieldValue(STEP_NAME, "/policyObj/customerAddress");
   String country = (String) ctx.getStepFieldValue(STEP_NAME, "/policyObj/customerCountry");
   String state = (String) ctx.getStepFieldValue(STEP_NAME, "/policyObj/customerState");
   JsonObject policyObj = (JsonObject) ctx.getStepFieldValue(STEP_NAME, "/policyObj");
   policyObj.put("full_address", Address + ", " + state + ", " + country);
   policyObj.remove("customerCountry");
   policyObj.remove("customerState");
   policyObj.remove("customerAddress");
   data.put("policyObj", policyObj)

The new output returns presenting all tree values in the same line, as follows:

{
   "policyObj": {
       "accountPolicyNumber": "123-45-6789",
       "customerId": "9876-54-321",
       "customerName": "Eli Israeli",
       "customerZip": "1234",
       "customerBirthDate": "2021-01-31T12:30:48.000+0000",
       "policyEndDate": "2021-01-31T12:30:48.000+0000",
       "policyType": "Delta Juliett India",
       "typeDescription": "Quisque arcu libero, rutrum ac, lobortis vel, dapibus at, diam.",
       "monthlyPayment": "50000",
       "quarteryPayment": "500000",
       "yearlyPayment": "40000",
       "currency": "USD",
       "createdDate": "2021-03-11T14:23:04.000+0000",
       "lastUpdate": "2021-03-11T14:23:59.407+0000",
       "locked": "N",
       "full_address": "32 Vernon Parkway, New York, USA"

Please Note!

Starting from OpenLegacy Core version 5.0.59, Entrypoint declarations must be updated due to changes in how Spring Boot 3.4.x loads conditional beans.

The core change is that an explicit generic type declaration is now required for all Entrypoint implementations. This means you must specify the FlowContext type for all entrypoints, and the exception type when implementing ExceptionEntrypoint.

Before (No Generic Types)

@Component
public class TestExceptionEntrypoint implements ExceptionEntrypoint {
  @Override
  public void handle(@NotNull Exception e, @NotNull FlowContext ctx) {
    ExceptionEntrypoint.super.handle(e, ctx);
  }

  @Nullable
  @Override
  public Object handleAwait(@NotNull Exception e, @NotNull FlowContext ctx, @NotNull Continuation $completion) {
    return ExceptionEntrypoint.super.handleAwait(e, ctx, $completion);
  }

  @Nullable
  @Override
  public Object handleInternal(@NotNull Exception e, @NotNull FlowContext ctx, @NotNull Continuation $completion) {

  

    throw new RuntimeException(e);
  }

  @NotNull
  @Override
  public Class getClazz() {
    return Exception.class;
  }
}

After (with explicit generic types) For RPC

@Component
public class TestExceptionEntrypoint implements ExceptionEntrypoint<RpcFlowContext, Exception> {
  @Override
  public void handle(@NotNull Exception e, @NotNull RpcFlowContext ctx) {
    ExceptionEntrypoint.super.handle(e, ctx);
  }

  @Nullable
  @Override
  public Object handleAwait(@NotNull Exception e, @NotNull RpcFlowContext ctx, @NotNull Continuation $completion) {
    System.out.println("blabla\n\n\nblalba");

    return ExceptionEntrypoint.super.handleAwait(e, ctx, $completion);
  }

  @Nullable
  @Override
  public Object handleInternal(@NotNull Exception e, @NotNull RpcFlowContext ctx, @NotNull Continuation $completion) {
    System.out.println("blabla\n\n\nblalba");

  

    throw new RuntimeException(e);
  }

  @NotNull
  @Override
  public Class getClazz() {
    return Exception.class;
  }
}

After (with explicit generic types) For Screens

@Component
public class TestExceptionEntrypoint implements ExceptionEntrypoint<GreenScreenFlowContext, Exception> {
  @Override
  public void handle(@NotNull Exception e, @NotNull GreenScreenFlowContext ctx) {
    System.out.println("blabla\n\n\nblalba");
    ExceptionEntrypoint.super.handle(e, ctx);
  }

  @Nullable
  @Override
  public Object handleAwait(@NotNull Exception e, @NotNull GreenScreenFlowContext ctx, @NotNull Continuation $completion) {
    System.out.println("blabla\n\n\nblalba");

    return ExceptionEntrypoint.super.handleAwait(e, ctx, $completion);
  }

  @Nullable
  @Override
  public Object handleInternal(@NotNull Exception e, @NotNull GreenScreenFlowContext ctx, @NotNull Continuation $completion) {
    System.out.println("blabla\n\n\nblalba");

  

    throw new RuntimeException(e);
  }

  @NotNull
  @Override
  public Class getClazz() {
    return Exception.class;
  }
}

Note that the change is setting the type of FlowContext.

Please apply these adjustments when upgrading your projects to avoid issues with bean loading and class compatibility.