Documentation for a newer release is available. View Latest

Migration Steps for IPF-2025.2.0

Migration for Connectors

Any classes that have previously implemented com.iconsolutions.ipf.core.connector.receive.deadletter.DeadletterAppender will have a compilation failure. To fix, change the return type of the append method from CompletableFuture<Void> to CompletionStage<Void>.

Migration for Kafka Connectors

akka.kafka.consumer.restart-settings is now defaulted to ipf.connector.default-transport-settings.restart-settings. Since all Kafka consumer settings now inherit from this default configuration, specifying restart-settings when declaring a Kafka consumer transport is no longer a necessary requirement.

If you used to set your restart-settings to akka.kafka.consumer.health-check-settings.restart-settings or ipf.connector.default-transport-settings.restart-settings, feel free to now remove those lines from your HOCON.

Migration for HTTP Connectors

The internal com.iconsolutions.ipf.core.connector.transport.HttpErrors.HttpStatusErrorException exceptions now have a stronger encapsulation, and their constructors can no longer be accessed publicly. If you need to create an instance for your testing purposes, please use com.iconsolutions.ipf.core.connector.transport.HttpErrors#from(StatusCode,TransportMessage).

Migration for Bulker

It is recommended to discontinue use of the following dependencies:

  • ipf-bulker-output-stream-api

  • ipf-bulker-output-stream-local

  • ipf-bulker-output-stream-s3

ipf-file-manager now provides equivalent functionality to the above dependencies via a new write method that accepts a reactor.core.publisher.Flux<ByteBuffer>. A new method has also been added to ipf-file-manager that enables reading file content into a reactor.core.publisher.Flux<ByteBuffer>. For more details, refer to the File Manager API Reference.

Remove the following configuration parameters if they are defined in your configuration:

ipf.bulker.outputstream.local.enabled
ipf.bulker.outputstream.s3.enabled

Previously, configuring the output file system required disabling the one not in use. This has now been simplified with a single property ipf.bulker.output.file-system which enables specifying the target file system for output explicitly. See Bulk Producer for additional details

Migration for IPF Persistent Scheduler

HTTP API

The triggerCommand field in the request body of POST /api/v1/schedule-job and POST /api/v1/update-job endpoints, as well as in the responses of all four HTTP API operations, has changed.

Whereas previously it was an API model of SchedulingCommand with an @class field, it is now an API model of ExternalTriggerCommand. This model no longer has the @class field and has additional fields required for scheduling the release of payments.

SchedulerConnectorInterface

If you use SchedulerConnectorInterface to interact with the HTTP RequestReplySendConnectors in the scheduler-client-connector-http artefact, you will need to migrate the models passed as method arguments and used as return types. The models are now from the HTTP API specification as opposed to 'core' models.

Migration for IPF Scheduler Floclient

Scheduler FloClient Commands

If you previously used PaymentAsyncScheduleCompletedCommand from the Scheduler Floclient commands, you should now use the SchedulePaymentReleaseCommand object. This extends the ExternalTriggerCommand from the HTTP API models, which in turn implements the existing SchedulingCommand interface.

priority and scheduleDate fields are no longer included in the PaymentAsyncScheduleCompletedCommand object (which has been refactored to SchedulePaymentReleaseCommand). These fields were, and remain, unused by the Scheduler API, Floclient and Core.

IPF Persistent Scheduler External Domain

The external domain IPF Persistent Scheduler requests Schedule Instruction Release and Schedule Transaction Release can now return the responses Scheduled Instruction Release Completion and Scheduled Transaction Release Completion respectively. These new responses are notifications that the scheduled instruction/transaction release has been triggered for execution. These responses differ from the existing Scheduled Instruction Release Response and Scheduled Transaction Release Response, which inform the flow that the instruction/transaction release has been scheduled (but not triggered for execution).

These new commands are automatically wired-in if you are using the scheduler-external-trigger-kafka module in your Scheduler application (described in release/IPF-2025-2-0/release-IPF-2025-2-0-core.adoc#_ipf_persistent_scheduler_added section). If you are not using the scheduler-external-trigger-kafka module, you can emit these responses by modifying your existing SchedulingHelper implementations to call the IPFPaymentSchedulerInputPort.handle(ScheduledInstructionReleaseCompletionInput scheduledInstructionReleaseCompletion) method (or transaction equivalent) in the execute method.

Migration for Payment Releaser (Payment Entries Processor)

Refactoring Payment Releaser to become generic Payment Entries Processor

The existing releasing implementation should make the following adjustments to make it work with the new generic processor:

Configuration changes

  • Config root path should be changed from ipf.core.payment-releaser to ipf.core.payment-entry-processor

  • Payment Entry processor now uses a new executionInfos database collection, requiring a new compound unitOfWorkId_1_actionType_1 index to be added. The releaseExecutionInfos collection is no longer used and can be removed, unless its contents are required for historical data, in which case it can be archived somewhere prior to removal

Renaming references

  • All PaymentReleaser references should be replaced with PaymentEntriesProcessor reference

  • All ReleaserExecutor references should be replaced with InstructionExecutorActor reference

  • All PaymentRequestCreator references should be replaced with ProcessingRequestCreator reference

  • All PaymentRequestSender references should be replaced with RequestProcessor reference

  • All ReleaserStore references should be replaced with ExecutionInfoStore reference

  • All TransactionReleaseService references should be replaced with PaymentEntriesProcessingService reference

  • All ReleaserExecutorProperties references should be replaced with PaymentEntryProcessorProperties reference

  • All InstructionReleaseCompletionService references should be replaced with InstructionProcessingCompletionService reference

Bean definition changes

TransactionReleaserService bean definition should be replaced with a PaymentEntriesProcessingServiceImpl bean definition. This class now depends on processingStrategyProvider — this bean is already being defined in core PaymentEntriesProcessor, it just needs to be wired in here.

Implementing processing strategy

You need to create an implementation of the ProcessingStrategy interface, and wire it as a bean. Your implementation should use ProcessingActionTypes.RELEASE action type to specify releasing action, and return your existing ProcessingRequestCreator and RequestProcessor interface implementations. For more details about Processing Strategies, refer to the Processing Strategy docs.

Adding SupportingContext to processInstruction and processTransaction

Across the PaymentEntriesProcessor (renamed from PaymentReleaser) interface, PaymentReleaserController and the ClientPort interfaces (e.g. ReleaseInstructionClientPort) and their implementing HTTP Send Connectors (e.g. ReleaseInstructionConnector) the processInstruction and processTransaction methods need to be updated to include a SupportingContext. These methods across these classes have an additional argument of SupportingContext to pass additional data from the calling service to the target execution service. If you have no use for this field during the migration you can pass it null or SupportingContext.empty(). In the case of the PaymentReleaserController, it is wrapped in a Mono as Mono<SupportingContext>, so you can pass a Mono.empty() if this field is not required in your migration. The options above (null or empty) will be handled gracefully.

PaymentRequestCreator

Your implementation of the ProcessingRequestCreator (renamed from PaymentRequestCreator) interface will now include a SupportingContext method argument in the create method. This is to enable providing additional data to the target execution service.

In your migration, you may choose to use or ignore the provided SupportingContext when creating your payment request.

Migration for Future Dated Payments

Payment Releaser

Change to the initationAggregatorFunction, supplied to BasePaymentWarehouseDataSource would mean when the response is processed, an Optional.empty should be returned if no initationAggregatorFunction is supplied.

Migration for Verification of Payee (VoP)

Account Management API

  • Update your service implementing this API to now return 'RetrievePartyDetailsResponse.names', which is now a list of names. This replaces the 'RetrievePartyDetailsResponse.nm' field.

Verification of Payee Responder

  • Previously, match thresholds were defined per account type only. In this release match thresholds must be defined per processing entity and account type.

Pre 2025.2.0:

ipf.verification-of-payee.responder {
  name-match {
    thresholds = [
      {type: "default", score-lowerbound = 0.40, score-upperbound = 0.90}
      {type: "individual", score-lowerbound = 0.85, score-upperbound = 0.95}
      {type: "corporate", score-lowerbound = 0.75, score-upperbound = 0.85}
    ]
  }
}

Post 2025.2.0 equivalent:

ipf.verification-of-payee.responder.name-match {
  thresholds = [
    {
      processing-entity: "default", (1)
      scorings: [ (2)
        { type: "default", lowerbound = 0.40, upperbound = 0.90 } (3) (4)
        { type: "individual", lowerbound = 0.85, upperbound = 0.95 }
        { type: "corporate", lowerbound = 0.75, upperbound = 0.85 }
      ]
    },
    {
      processing-entity: "Processing Entity A",
      scorings: [
        { type: "default", lowerbound = 0.70, upperbound = 0.80 }
        { type: "individual", lowerbound = 0.75, upperbound = 0.85 }
        { type: "corporate", lowerbound = 0.65, upperbound = 0.75 }
      ]
    }
  ]
}
1 A default processing entity must be defined
2 Configuration structure changed to include scoring in hierarchy
3 score-lowerbound renamed to lowerbound
4 score-upperbound renamed to upperbound

Verification of Payee Requester

  • Configuration ipf.verification-of-payee.requester.scheme-membership-ids has been removed from the hierarchy. Clients overriding values (e.g. processing-entities) underneath this path should remove scheme-membership-ids from the path.

  • Default processing-entity-code was previously "". This has been updated to default instead of empty string, consistent with VoP Responder

  • rvm parameter should be specified in addition to name for scheme configuration

Pre 2025.2.0:

ipf.verification-of-payee.requester {
  scheme-membership-ids { (1)
    schemes = [
      {
        name: "EPC"
        processing-entities = [
          {processing-entity-code: "", scheme-membership-id: "ICONUK00XXX"} (2)
          {processing-entity-code: "001", scheme-membership-id: "ICONUK01XXX"}
        ]
      }
    ]
  }
}
1 This is removed in 2025.2.0
2 "" has been replaced with default in 2025.2.0 to denote the default processing entity

Post 2025.2.0 equivalent:

ipf.verification-of-payee.requester {
   schemes = [
     {
       name: EPC (1)
       rvm: FPAD (2)
       processing-entities = [
         {processing-entity-code: "default", scheme-membership-id: "ICONUK00XXX"} (3)
         {processing-entity-code: "001", scheme-membership-id: "ICONUK01XXX"}
       ]
     }
   ]
}
1 Now defined as an Enum instead of String
2 Previously, EPC using FPAD as an RVM was configured with just the name config parameter. Now rvm: FPAD must also be specified, and is defined as an Enum
3 Default processing entity is now identified by "default"

Migration for Dynamic Processing Settings (DPS)

As part of IPF release 2025.2, CSM Reachability service is being integrated with DPS V2 library (as compared to integrated with DPS V2 before).

Dynamic configuration record structures differ between DPS V1 and DPS V2. This does not affect the payload of the dynamic configuration. From backward compatibility point of view, both DPS V1 and DPS V2 formatted records can co-exist at the same time as DPS V2 can interact with the records created using DPS V1.

However, when dealing with large volume dynamic configurations, if the records on the collection all follow DPS V1 format, this may affect the performance slightly. For this reason, it is recommended that such dynamic configurations on CSM Reachability (e.g. industry data dynamic configurations), are refreshed to follow DPS V2 format.

The main benefit of this migration is improved database query performance.

Steps for migration

  1. It is recommended that client implementation ingest FULL files to industry data dynamic configurations after absorbing DPS V2 integrated CSM Reachability:

    • Party Entity Directory (Bank Directory Plus, Bank Master 3.0)

    • IBAN Plus, Exclusion List, IBAN Structure

  2. The next set of files to be ingested into CSM Participant after absorbing DPS V2 integrated CSM Reachability must be FULL files.

    • STEP2 CST, RT1, TIPS, SicInst

  3. For each DPS collection verify if there is any data that is not updated using following script

db.[<collection-name>].find({
  "_class": {
    $regex: "^com.iconsolutions.ipf.dynamicsettings.repository"
  }
})
  1. If there are documents that haven’t been updated, please raise a support ticket.

Migration for Test Framework

As a result of the JUnit 5 migration, if you are including either JUnit 4 Rules using the @ClassRule annotation in your tests, or running test suites using the @Suite annotation, please migrate these to JUnit Jupiter Extensions and Suites, respectively.

The table below shows common JUnit 4 usages in the test framework, and their JUnit 5 equivalent:

Feature Test Framework JUnit 4 snippet JUnit 5 Equivalent

Suites

import org.junit.runner.RunWith;
import org.junit.runners.Suite;

@RunWith(Suite.class)
@Suite.SuiteClasses({MyTest1.class, MyTest2.class})
import org.junit.platform.suite.api.SelectClasses;
import org.junit.platform.suite.api.Suite;

@Suite
@SelectClasses({MyTest1.class, MyTest2.class})

Rules (Extensions)

import com.palantir.docker.compose.DockerComposeRule;
import org.junit.ClassRule;

@ClassRule
public static DockerComposeRule dockerComposeRule = getRule();

private static DockerComposeRule getRule() {
    DockerComposeRule dockerComposeRule = new AppComposeLauncher().getComposeRule();
    //...
}
import com.palantir.docker.compose.DockerComposeExtension;
import org.junit.jupiter.api.extension.RegisterExtension;

@RegisterExtension
public static DockerComposeExtension dockerComposeRule = getRule();

private static DockerComposeExtension getExtension() {
    var dockerComposeRule = new AppComposeLauncher().getComposeRule();
    //...
}
You may be using other JUnit 4 Rules not listed above. Consult the documentation for the libraries you are using for their JUnit 5 equivalents.