View source | Discuss this page | Page history | Printable version   

How to Create a Hook To Extend SEPA Framework Functionalities module



Hooks provide an easy mechanism to extend functionality from external modules. It basically consists on a lightweight mechanism (build using WELD) that allows to inject dependencies from third party modules. Since 1.0.100 version of SEPA Framework and Utilities module it's possible to extend the SEPA XML file generation from external modules using hooks. These hooks allow to easily develop customizations required by concrete countries or banks without affecting the original module, this way it's possible to modify, add or even delete any node or tag of the XML generated by the base process.

The main purpose of this how-to is to explain the way of make these customizations in external modules.


In this article we will explain a detailed example of how to create and package an external module that extends current SEPA functionalities using hooks. We are going to do a customization that fulfills the following requirements:

In next sections of this how-to, necessary steps to implement this kinds of hooks will be described. Specifically, we are going to explain how to extend the SEPA XML files according to the requirements described above.

Recommended articles

Before reading this howto it is important to have a clear understanding about the Modularity Concepts, specially the process of creating and packing modules.

As in this how-to we are extending functionalities of SEPA modules, will be necessary to set up and know concepts of SEPA Credit Transfer and SEPA Direct Debit modules.

Also we are going to create a dataset including two new parameters to the Remittance Types defined in the SEPA datasets, which will be used inside the hook to add the new nodes to the XML, that’s why it is recommended to read the How to create a Dataset article to get a general idea before doing in our example.

Creating the Module

The first step in this development process is to create a new module. From the Application menu, select Application Dictionary || Module.


In our case it's important to highlight the Java Package we are using should be a unique identifier of your module and has to match the Java package naming rules as described in the Java Naming Conventions (names and package names). Package used in this example will be org.openbravo.sepa.iso20022.extension.

We are going to extend functionalities of SEPA Credit Transfer and Direct Debit modules, so we need to add them as dependencies of our module. Also we will provide extra functionality to the base one existing in SEPA Framework.


Important note: Hooks were included in SEPA Framework module since 1.0.100 version, so you need to create a Major version dependency enforcement to this version to implement and extend functionality using hooks.

Creating a Source Directory

To develop manual Java code you need a src directory inside your specific module:


The Java package in the source directory should start with the Java package of the module. So for this case org.openbravo.sepa.iso20022.extension.hook is a valid package and will be used to create our implementation of the hook.

If using Eclipse, add the newly created module's src folder to the build path of the Eclipse project (Java Build Path):


Implementing the Hook

To create a hook, you just need to create a new class (for instance SEPA_RemittanceHook) implementing the SEPA_RemittanceProcessHook interface provided in the 1.0.100 version of SEPA Freamework module to extend the SEPA XML generated file:

public class SEPA_RemittanceHook implements SEPA_RemittanceProcessHook {
  private static final String PARAM_PMTINF_CTRLSUM = "PmtInf_CtrlSum";
  private static final String PARAM_PMTINF_NBOFTXS = "PmtInf_NbOfTxs";

You need to override the exec() method to implement your logic inside the hook. This method receives the remittance to be processed and the XML representation of the document according the schema definition used in the remittance type. According this representation and the instance of the document you will know the necessary API to use for a correct processing of the XML schema definition and your development requirements.

The @ApplicationScoped annotation will inject this class implementation of the hook when SEPA XML file is processed.

  public <T> void exec(Remittance remittance, JAXBElement<T> doc) throws Exception {
    if (doc.getValue() instanceof org.openbravo.sepa.iso20022.coredirectdebit.customertobank.pain.x008.x001.x02.Document) {
      processCoreDirectDebitx008x001x002(remittance, doc);
    } else if (doc.getValue() instanceof org.openbravo.sepa.iso20022.coredirectdebit.customertobank.pain.x008.x001.x03.Document) {
      processCoreDirectDebitx008x001x003(remittance, doc);
    } else if (doc.getValue() instanceof org.openbravo.sepa.iso20022.credittransfer.customertobank.pain.x001.x001.x03.Document) {
      processCreditTransferx001x001x003(remittance, doc);
    } else if (doc.getValue() instanceof org.openbravo.sepa.iso20022.credittransfer.customertobank.pain.x001.x001.x04.Document) {
      processCreditTransferx001x001x004(remittance, doc);

In this concrete example, our logic will be: If the remittance type of the document being processed has the PmtInf_CtrlSum or NbOfTxs parameters active and with value = Y then we add the <CtrlSum> and <NbOfTxs> tags to every payment information of the XML file.

We will use two methods to know if parameters are active or not:

   * Get if PmtInf_CrtrlSum PARAM is defined in the remittance type used in the remittance param
   * @param remittance
   *          Remittance being processed
   * @return TRUE if parameter is defined, is active and has value = 'Y'
  private boolean getPmtInf_CrtrlSum(final Remittance remittance) {
    return SEPAUtil.getBooleanPropertyValue(remittance, PARAM_PMTINF_CTRLSUM);
   * Get if PmtInf_NbOfTxs PARAM is defined in the remittance type used in the remittance param
   * @param remittance
   *          Remittance being processed
   * @return TRUE if parameter is defined, is active and has value = 'Y'
  private boolean getPmtInf_NbOfTxs(final Remittance remittance) {
    return SEPAUtil.getBooleanPropertyValue(remittance, PARAM_PMTINF_NBOFTXS);

Taking into account the document type being processed we will process the XML according to the schema defined for this type of document.

private <T> void processCoreDirectDebitx008x001x002(Remittance remittance, JAXBElement<T> doc) {
    boolean pmtInf_CtrlSum = getPmtInf_CrtrlSum(remittance);
    boolean pmtInf_NbOfTxs = getPmtInf_NbOfTxs(remittance);
    // 2.4 Número de transacciones y 2.5 Control de la suma por información de pago - Number of
    // transactions and ControlSum per Payment Information
    // Not mandatory
    // If any of the pmtInf_CtrlSum || pmtInf_NbOfTxs parameters are defined in AD, are active and
    // has value = Y then:
    // Iterate and add NbOfTxs and CtrlSum tags to all payment instructions nodes
    if (pmtInf_CtrlSum || pmtInf_NbOfTxs) {
      org.openbravo.sepa.iso20022.coredirectdebit.customertobank.pain.x008.x001.x02.Document document = (org.openbravo.sepa.iso20022.coredirectdebit.customertobank.pain.x008.x001.x02.Document) doc
      // Iterates all payment instructions (pmtInf nodes)
      for (PaymentInstructionInformation4 paymentInstruction : document.getCstmrDrctDbtInitn()
          .getPmtInf()) {
        if (pmtInf_CtrlSum) {
          BigDecimal totalAmtInf = BigDecimal.ZERO;
          // Per each pmtInf node, calculate the total amount of credits related to the current
          // payment instruction
          for (DirectDebitTransactionInformation9 dbtTrfTxInf : paymentInstruction
              .getDrctDbtTxInf()) {
            totalAmtInf = totalAmtInf.add(dbtTrfTxInf.getInstdAmt().getValue());
          // Update the CtrlSum of the payment instruction
        if (pmtInf_NbOfTxs) {
          // Update the number of credit transactions related to the payment instruction
          int nbOfTxs = paymentInstruction.getDrctDbtTxInf().size();

It is important to highlight that any exception thrown by the hook, will make the XML to be not generated. You must take this into account when implementing your solutions.

Executing the Hook

When a remittance is created related with any of the Remittance types used in our example, the hook will be injected by Weld into SEPA Framework and the XML will be generated with changes applied by our hook.

For example, with PmtInf_CtrlSum and PmtInf_NbOfTxs parameters set as Y, we will generate an XML file like this:


Creating the dataset

As a requirement of developed hook, it checks for PmtInf_CtrlSum and PmtInf_NbOfTxs parameters values to add respectively nodes to the Payment Information nodes when generating the SEPA XML file. Due that we are going to include these new parameters into module dataset to make them available for environments using this hook.

This section describes necessary steps to create and export the dataset.

Adding new parameters to existing remittance types

Now we are going to add the new parameters to all Remittance types we are processing in our hook. To do that, go to Remittance Type window. Select all SEPA Core Direct Debit and SEPA Credit Transfer remittance types and add two new parameters to all of them, like in the screenshot below .


Exporting the dataset

Before creating and exporting our dataset, we must make sure that our module is marked as Has reference data.


Next step is to create the dataset in our module. To do that, go to Dataset window and create new one as shown below:


You must take into account that:

The dataset definition is ready, so we just need to export it to a file pressing the Export Reference Data button. This process queries the previous tables and gets all the records that fulfill the HQL/SQL Where clause, generating a XML file inside the module's referencedata/standard directory. As a fast check, you can open this file using any plain text editor and you can verify that it contains a total of 2 entries for each remittance type treated inside the hook.

In case the file is empty, you should double check the dataset definition, specially the HQL/SQL Where clause used for each table.

Example of external module

You can find a complete example of the external module created in this how-to article in the following link:

With provided sources you should be able to adapt it (or use it as basis) to implement your own solution, adding new nodes or updating the information of the existing ones to get a customized SEPA XML file.

Retrieved from ""

This page has been accessed 1,911 times. This page was last modified on 21 June 2017, at 16:24. Content is available under Creative Commons Attribution-ShareAlike 2.5 Spain License.