Getting Started

This page will describe how to build a Scheduled Payment solution.

Architecture

One consideration required for building out the Scheduled Payment solution is how the IPF Core components will communicate. You must decide if the they will be embedded into one application, or will they communicate over the network (i.e. via HTTP)?

Each component has the option to expose a HTTP API and a client library to interact with that HTTP API.

Once decided, you can start building out your application(s). To build each component into your application(s) the best place to start is the respective 'getting started' documentation:

Implementation

Aside from the getting-started guides, there are other implementation considerations.

Scheduler

Register a Scheduling Helper

You’ll need to define a SchedulingCommand and a SchedulingHelper. Both the application calling the Scheduler and the Scheduler itself will need to be aware of the SchedulingCommand.

package com.iconsolutions.ipf.sample.scheduler.config;

import com.iconsolutions.ipf.core.shared.scheduling.SchedulingCommand;
import lombok.Getter;
import lombok.RequiredArgsConstructor;

@Getter
@RequiredArgsConstructor
public class ReleaseBatchCommand implements SchedulingCommand {
    private final String unitOfWorkID;
}

The SchedulingHelper should call the Payment Releaser when the command is executed.

import com.iconsolutions.ipf.core.releaser.PaymentReleaser;
import com.iconsolutions.ipf.core.shared.domain.context.UnitOfWorkId;
import com.iconsolutions.ipf.core.shared.scheduling.SchedulingCommand;
import com.iconsolutions.ipf.core.shared.scheduling.SchedulingHelper;
import lombok.RequiredArgsConstructor;

import java.util.concurrent.CompletionStage;

@RequiredArgsConstructor
public class ReleaseBatchSchedulerHelper implements SchedulingHelper {

    private final PaymentReleaser paymentReleaser;

    @Override
    public CompletionStage<Void> execute(String id, SchedulingCommand schedulingCommand) {
        var releaseBatchCommand = (ReleaseBatchCommand) schedulingCommand;
        var unitOfWorkID = releaseBatchCommand.getUnitOfWorkID();

        return paymentReleaser
                .releaseInstruction(UnitOfWorkId.of(unitOfWorkID))
                .thenApply(unused -> null);
    }

    @Override
    public boolean supports(SchedulingCommand request) {
        return request instanceof ReleaseBatchCommand;
    }
}

Of course, if you are integrating with the Payment Releaser via HTTP you will need to use the Client Library instead.

import com.iconsolutions.ipf.core.releaser.model.SupportingBusinessDataMapForReleaseOperation;
import com.iconsolutions.ipf.core.shared.domain.context.propagation.ContextPropagation;
import com.iconsolutions.ipf.core.shared.scheduling.SchedulingCommand;
import com.iconsolutions.ipf.core.shared.scheduling.SchedulingHelper;
import com.iconsolutions.ipf.releaser.api.client.port.ReleaseInstructionClientPort;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.concurrent.CompletionStage;

@Slf4j
@RequiredArgsConstructor
public class ReleaseBatchViaHttpSchedulerHelper implements SchedulingHelper {

    private final ReleaseInstructionClientPort paymentReleaserAdapter;

    @Override
    public CompletionStage<Void> execute(String id, SchedulingCommand schedulingCommand) {
        var releaseBatchCommand = (ReleaseBatchCommand) schedulingCommand;
        var unitOfWorkID = releaseBatchCommand.getUnitOfWorkID();

        return paymentReleaserAdapter
                .releaseInstruction(
                        ContextPropagation.getProcessingContext(),
                        unitOfWorkID,
                        new SupportingBusinessDataMapForReleaseOperation())
                .thenApply(unused -> null);
    }

    @Override
    public boolean supports(SchedulingCommand request) {
        return request instanceof ReleaseBatchCommand;
    }
}
The examples above call the releaseInstruction methods, however you may choose to first prepareInstruction. If you are using the default Payment Releaser implementation then this will subsequently trigger the releaseInstruction operation.

Payment Releaser

Default implementation

For the purpose of getting started, we recommend using the default implementation. More information can be found in the Payment Entries Processor documentation.

The default Payment Releaser integrates with the Payment Warehouse as an embedded solution. If you want the Payment Releaser to interact with the Payment Warehouse over HTTP you will have to customise your Payment Releaser implementation.

Schedule and Release Your First Batch/Instruction

Once you have built your application(s) by following the respective getting-started guides you can schedule and release your first batch/instruction.

The step taken by each component in the solution are outlined in the contextual diagram on the home page.

The list below details the operations your calling application (e.g. Initiation application) has to execute to schedule payments. The steps use an example of a BULK payment that consists of one BATCH payment, and that BATCH payment consists of two TRANSACTION payments:

  1. Save the BULK, BATCH and two TRANSACTION payment entries to the Payment Warehouse.

    1. HTTP client library solution: via the PaymentWarehouseClientPort interface (see Save a Payment Entry via Client Library)

    2. Embedded solution: via the PaymentWarehouse interface (see Save Your First Payment Entry)

  2. Schedule the BATCH to be released for 1 minute into the future by calling the Persistent Scheduler

    1. HTTP client library solution: via the SchedulingModuleInterface interface (see Scheduling Your First Job (via HTTP Client Library))

    2. Embedded solution: via the SchedulerConnectorInterface interface (see Schedule the job)

  3. Observe results! Your execution service should received 2 Transactions from the Payment Releaser

Configuration

There is no specific configuration required over and above that which is described in the individual component documentation.