Sunday, April 26, 2026

OIC - OCI function Java code to encrypt and decrypt using AES key

Please find the below working code:

Working Function code:

package com.test .fn;

import javax.crypto.Cipher;

import javax.crypto.spec.IvParameterSpec;

import javax.crypto.spec.SecretKeySpec;

import java.util.Base64;

import java.util.logging.*;

import java.security.SecureRandom;

public class AESEncryptDecrypt {

    private static final Logger logger = Logger.getLogger(AESEncryptDecrypt.class.getName());

    public static class Input {

        public String message;

        public String secretKeyBase64;

        public String ivBase64;

        public String aesMode; // AES/CBC/PKCS5Padding or AES/ECB/PKCS5Padding

        public String actionType; //ENCRYPT or DECRYPT

    }

    public static class Result {

        public String message;

        public String salt;

        public String wechataeskey;

        public String executionInfo;

    }

    public Result handleRequest(Input input) {

        logger.log(Level.INFO, "OIC - message:", input.message);

        logger.log(Level.INFO, "OIC - secretKeyBase64:", input.secretKeyBase64);

        logger.log(Level.INFO, "OIC - ivBase64", input.ivBase64);

        logger.log(Level.INFO, "OIC - aesMode:", input.aesMode);

        logger.log(Level.INFO, "OIC - actionType:", input.actionType);

        Result result = null;

if ("DECRYPT".equals(input.actionType)) {

    result = decryptMyMessage(input);

} else if ("ENCRYPT".equals(input.actionType)) {

    result = encryptMyMessage(input);

} else {

    result = new Result();

    result.executionInfo = "ERROR: No proper action found , possible value is ENCRYPT or DECRYPT , recieved value:" + input.actionType;

}

return result;

}

// Generate random 16-byte IV for AES/CBC

public static IvParameterSpec generateIV() {

    byte[] iv = new byte[16]; // 128-bit IV

    new SecureRandom().nextBytes(iv);

    IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);

    return ivParameterSpec;

}

public Result encryptMyMessage(Input input) {

    Result result = new Result();

    try {

        byte[] decodedKey = null;

        if (input.secretKeyBase64 == null) {

            // Generate 16-digit random numeric string

            String keyString = generateRandomDigits(16);

            //System.out.println("Generated 16-digit AES key: " + keyString);

            // Convert to byte array (each digit becomes 1 byte, 16 bytes total = 128 bits)

            result.wechataeskey = keyString;

            decodedKey = keyString.getBytes("UTF-8");

        } else {

            // Decode the base64 encoded string

            decodedKey = Base64.getDecoder().decode(input.secretKeyBase64);

        }

byte[] messageBytes = input.message.getBytes("UTF-8");

// Create a SecretKeySpec for the AES key

SecretKeySpec secretKeySpec = new SecretKeySpec(decodedKey, "AES");

// Create a Cipher instance for AES

Cipher cipher = Cipher.getInstance(input.aesMode);

if (input.aesMode.contains("CBC")) {

    //AES/CBC/PKCS5Padding required IV

    IvParameterSpec ivParameterSpec = generateIV();

    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec, ivParameterSpec);

    result.salt = Base64.getEncoder().encodeToString(ivParameterSpec.getIV());

} else {

    //AES/ECB/PKCS5Padding do not require IV

    cipher.init(Cipher.ENCRYPT_MODE, secretKeySpec);

}

// Decrypt the message

byte[] originalBytes = cipher.doFinal(messageBytes);

String encodedString = Base64.getEncoder().encodeToString(originalBytes);

result.message = encodedString;

//String originalMessage = =new String(originalBytes);

result.executionInfo = "SUCCESS";

} catch(Exception e) {

    result.executionInfo = e.getMessage();

    logger.log(Level.INFO, "Error Details:", e.getMessage());

}

return result;

}

public Result decryptMyMessage(Input input) {

    Result result = new Result();

    generateIV();

    try {

        // Decode the base64 encoded string

        byte[] decodedKey = Base64.getDecoder().decode(input.secretKeyBase64);

        byte[] encryptedBytes = Base64.getDecoder().decode(input.message);

        // Create a SecretKeySpec for the AES key

        SecretKeySpec secretKeySpec = new SecretKeySpec(decodedKey, "AES");

        // Create a Cipher instance for AES

        Cipher cipher = Cipher.getInstance(input.aesMode);

        if (input.aesMode.contains("CBC")) {

            //AES/CBC/PKCS5Padding required IV

            byte[] decodedIV = Base64.getDecoder().decode(input.ivBase64);

            IvParameterSpec ivParameterSpec = new IvParameterSpec(decodedIV);

            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, ivParameterSpec);

        } else {

            //AES/ECB/PKCS5Padding do not require IV

            cipher.init(Cipher.DECRYPT_MODE, secretKeySpec);

        }

        // Decrypt the message

        byte[] originalBytes = cipher.doFinal(encryptedBytes);

        String encodedString = Base64.getEncoder().encodeToString(originalBytes);

        result.message = encodedString;

        //String originalMessage = =new String(originalBytes);

        result.executionInfo = "SUCCESS";

    } catch(Exception e) {

        result.executionInfo = e.getMessage();

        logger.log(Level.INFO, "Error Details:", e.getMessage());

    }

    return result;

}

// Wechat, Generate a random string of digits for AES Key

public static String generateRandomDigits(int length) {

    SecureRandom random = new SecureRandom();

    StringBuilder sb = new StringBuilder(length);

    for (int i = 0; i < length; i++) {

        sb.append(random.nextInt(10)); // 0-9

    }

    return sb.toString();

}

public static void main(String[] args) {

    AESEncryptDecrypt service = new AESEncryptDecrypt();

    Input input = new Input();

    input.message = "put encrypted cyper message";

    // Base64 for "1234567890123456"

    input.secretKeyBase64 = "Put base64 encoded secret key";

    input.ivBase64 = "base63 encode salt ot IV";

    input.aesMode = "AES/CBC/PKCS5Padding";

    input.actionType = "DECRYPT";

    Result result = service.handleRequest(input);

    // Print output

    System.out.println("=== RESULT ===");

    System.out.println("Message: " + result.message);

    System.out.println("Salt: " + result.salt);

    System.out.println("WeChat AES Key: " + result.wechataeskey);

    System.out.println("Execution Info: " + result.executionInfo);

}

}

Screenshots:






Test online tool :

https://www.onlinegdb.com/online_java_compiler#



OIC - Secure Payload Handling in OIC using OCI Vault & Functions (AES + RSA)

Work in progress...

Overview

This blog covers a secure and scalable design pattern in Oracle Integration Cloud (OIC) where:

  • Incoming payload is AES encrypted and RSA signed
  • Keys are fetched from OCI Vault
  • Cryptographic operations are handled via OCI Functions
  • Response is encrypted before sending back

Updated Architecture

We use a modular integration design:

Main Integration
        ↓
Crypto Integration -encrypt and decrypt
        ↓
OCI Functions
   - Function 1: AES Encrypt/Decrypt
   - Function 2: RSA Sign/Verify

End-to-End Flow

Step 1: Receive Request (Main Integration - 1)

  • Expose REST API
  • Input contains:
    • Encrypted payload (Base64)
    • Signature
    • Salt or IV

➡️ Call Crypto Integration (2) for processing


Step 2: Crypto Processing (Integration - 2)

This integration acts as a central reusable crypto layer.

2.1 Fetch Keys from OCI Vault

  • Retrieve:
    • AES Secret Key
    • RSA Private/Public Keys
  • Use secure REST call / OCI SDK

Ensures no key is hardcoded in OIC


2.2 Call OCI Function – Decrypt

  • Pass encrypted payload + key reference
  • Function performs:
    • Base64 decode
    • AES decryption

Returns: Plain payload

For function code , use below link:

https://soalicious.blogspot.com/2026/04/oic-oci-function-code-to-encrypt-and.html


2.3 Call OCI Function – RSA Verify

  • Pass payload + signature + public key
  • Function validates signature

Condition:

  • Valid → proceed
  • Invalid → throw fault

Step 3: Return Decrypted Data to Main Integration

  • Crypto Integration sends verified plain payload back

Step 4: Business Processing (Main Integration - 1)

  • Transform data
  • Call target system
  • Receive response

Step 5: Encrypt Response

Main Integration again calls Crypto Integration (2)

5.1 Call OCI Function – AES Encrypt

  • Encrypt response payload
  • Base64 encode

No RSA signing required for response


Step 6: Send Response

  • Return encrypted response to source system

OCI Functions Design

Function 1: AES Encrypt/Decrypt

Handles:

  • AES Decryption (incoming)
  • AES Encryption (outgoing)

Function 2: RSA Sign/Verify

Handles:

  • Signature verification (incoming)
  • (Optional signing if future needed)

Key Benefits

  • ๐Ÿ” High Security – Keys stored in OCI Vault
  • ๐Ÿ” Reusable Design – Crypto logic centralized
  • Scalable – Functions handle heavy crypto processing
  • ๐Ÿงฉ Loose Coupling – Business logic separated from security

Error Handling

  • Vault access failure → Security error
  • Decryption failure → Invalid payload
  • Signature failure → Reject request
  • Function failure → Retry / fault

Best Practices

  • Use OCI Vault for all secrets
  • Restrict access via IAM policies
  • Avoid logging sensitive payloads
  • Enable tracing only for metadata
  • Reuse crypto integration across projects

Final Flow Summary

Source
 ↓ (AES Encrypted + RSA Signed)
Main Integration (1)
 ↓
Crypto Integration (2)
   → Fetch keys from OCI Vault
   → Call Function (AES Decrypt)
   → Call Function (RSA Verify)
 ↓
Main Integration
   → Call Target
   ← Response
 ↓
Crypto Integration
   → Call Function (AES Encrypt)
 ↓
Source (Encrypted Response)

Conclusion

This approach provides a clean, secure, and enterprise-ready pattern in OIC by combining:

  • OCI Vault for secure key management
  • OCI Functions for cryptographic operations
  • Reusable integrations for maintainability

A perfect design for handling sensitive real-time integrations at scale.


Thursday, April 23, 2026

OIC File Handling – Removing .pgp and Preserving .csv (Dynamic File Name Logic) | use of ast-index-within-string() function

๐Ÿ“Œ Problem Statement

In Oracle Integration Cloud (OIC), while working with Stage File, we often receive source files like:

a.b.c.csv.pgp ๐Ÿ” (encrypted file)

a.b.c.csv ๐Ÿ“„ (plain file)

๐ŸŽฏ Requirement

If file = a.b.c.csv.pgp → Target should be a.b.c.csv

If file = a.b.c.csv → Keep as a.b.c.csv

⚠️ Challenge

Handling multiple dots (.) in file names:

Simple logic may break

Functions like last-index-of() (or OIC equivalent) may not always behave as expected in mapper

Approach 1: Nested substring-before/after (Working & Stable).

๐Ÿ’ป Code Snippet

XML

fn:concat(

  fn:substring-before($FileName, '.'),

  '.',

  fn:substring-before(fn:substring-after($FileName, '.'), '.'),

  '.',

  fn:substring-before(fn:substring-after(fn:substring-after($FileName, '.'), '.'), '.'),

  '.csv'

)


✔️ Behavior

Extracts each part between dots

Reconstructs filename ending with .csv

๐Ÿ‘ Advantages

Works consistently in OIC mapper

No dependency on special functions

๐Ÿ‘Ž Disadvantages

Not dynamic (hardcoded for 3 segments like a.b.c)

Breaks if file structure changes (e.g., a.b.c.d.csv.pgp)

Approach 2: Using oraext:last-index-within-string (Dynamic but Risky)

๐Ÿ’ป Code Snippet

XML

substring(

  $filename,

  1,

  oraext:last-index-within-string($filename, '.')

)


✔️ Behavior

Dynamically trims extension

Works for any filename length

๐Ÿ‘ Advantages

Fully dynamic

Handles multiple dots easily

๐Ÿ‘Ž Disadvantages

❌ In OIC mapper, sometimes does not evaluate correctly

Can fail depending on context (Stage File / namespaces)

Less predictable compared to substring chaining

๐Ÿง  Recommended Hybrid Logic

๐Ÿ‘‰ Best practical approach:

Use substring logic when:

File pattern is fixed (like a.b.c.csv.pgp)

Use last-index logic when:

File pattern is dynamic

Tested properly in your integration

๐Ÿš€ Pro Tip

If your only goal is to remove .pgp, a simpler and safer approach:

XML

fn:replace($filename, '.pgp', '')

✔️ Works for both cases:

a.b.c.csv.pgp → a.b.c.csv

a.b.c.csv → unchanged

๐Ÿงพ Conclusion

OIC file handling becomes tricky with multiple dots

substring-before → stable but rigid

last-index-within-string → flexible but unreliable in some cases

๐ŸŽฏ Best solution depends on your file pattern stability

OIC CCS Utility Adapter – Misleading “Client ID Wrong” Error (Actual Issue: Catalog Not Configured)

๐Ÿ“Œ Overview

While configuring a CCS (Customer Cloud Service) / Utilities Adapter connection in Oracle Integration Cloud (OIC) using Client Credentials, you might encounter an error stating:

❌ “Client ID is invalid” or “Client credentials are incorrect”

At first glance, this looks like an authentication issue—but that’s not always the case.

This blog explains a real scenario where the credentials were correct, but the actual issue was missing Web Service Catalog configuration in CCS.

⚠️ The Problem Statement

You create an OIC connection using:

Security Policy: OAuth Client Credentials

Correct Client ID & Secret

While testing the connection:

❌ Error: Invalid Client ID / Authentication Failed

Even after rechecking:

Credentials ✔️

Token URL ✔️

Scope ✔️

Still failing.

๐Ÿง  Root Cause (Hidden Issue)

The actual issue was:

๐Ÿšจ Web Service Catalog was NOT configured in the CCS (Utilities) portal

Without this configuration:

OIC cannot discover or invoke backend services

The adapter fails internally

And misleadingly throws authentication-related errors

๐Ÿ“– What is Web Service Catalog?

The Web Service Catalog in Oracle Utilities defines:

Which REST services are exposed

Which services OIC can access via the Utilities Adapter

Without it, even valid credentials won’t help.

๐Ÿ› ️ Fix: Configure Catalog in CCS

Follow these steps:

1️⃣ Login to CCS / Utilities Portal

2️⃣ Navigate to: Admin → Integration / W → Web Service Catalog

3️⃣ Select: REST Web Service Class

4️⃣ Add Required Services:

W1-ServiceCall → Service Call Maintenance

W1-Communication → Communication Maintenance


๐Ÿ‘‰ These are essential inbound services for OIC communication.

๐Ÿ” Retest in OIC

After configuring the catalog:

Go back to OIC Connection

Click Test

✅ Connection should now succeed

๐Ÿ’ก Key Takeaways

❌ Don’t trust error messages blindly in OIC

๐Ÿ” “Invalid Client ID” ≠ Always authentication issue

⚙️ Always verify:

Catalog configuration in CCS

Required REST services availability

๐Ÿš€ Pro Tip

When working with Oracle Utilities Adapter:

Always validate backend readiness (Catalog + Services) before debugging authentication

If error feels misleading → check service exposure first

๐Ÿงพ Conclusion

This issue is a classic example where:

Everything looks like a security problem

But turns out to be a configuration gap in backend

Fixing the Web Service Catalog resolved the issue completely—without changing any credentials.

Reference:

https://docs.oracle.com/en/industries/energy-water/cloud-integrations/24b/ccs-wacs-configuration-guide/CCS-WACS-CONFIGURATION-GUIDE/




Friday, April 17, 2026

OIC XSLT: Execute Only When At Least One Field Has Value and None Are Blank

๐Ÿ”ท OIC XSLT: Validate Fields Before Executing Logic

๐Ÿ”น Requirement

Fields: field1, field2, field3, field4, field5

✔ Execute only when: At least one field has a value

AND no provided field is empty (including spaces)

๐Ÿ”น Final XSLT

XML

<xsl:if test="

(

  string-length(normalize-space(field1)) &gt; 0 or

  string-length(normalize-space(field2)) &gt; 0 or

  string-length(normalize-space(field3)) &gt; 0 or

  string-length(normalize-space(field4)) &gt; 0 or

  string-length(normalize-space(field5)) &gt; 0

)

and

(

  (not(field1) or string-length(normalize-space(field1)) &gt; 0) and

  (not(field2) or string-length(normalize-space(field2)) &gt; 0) and

  (not(field3) or string-length(normalize-space(field3)) &gt; 0) and

  (not(field4) or string-length(normalize-space(field4)) &gt; 0) and

  (not(field5) or string-length(normalize-space(field5)) &gt; 0)

)

">

   <!-- Execute logic -->

</xsl:if>

๐Ÿ”น Key Idea (1 Line)

๐Ÿ‘‰ Run only if:

At least one field has non-space value AND no field is empty/blank

๐Ÿ”น Why normalize-space() Matters

Converts "   " → ""

Prevents false positives from whitespace

Ensures clean validation in OIC payloads

๐Ÿ”น Quick Examples

Input == Result

<root/>❌ Skip

<field1>   </field1> ❌ Skip

<field1>ABC</field1> ✅ Execute

<field1>ABC</field1><field2> </field2> ❌ Skip


Wednesday, April 15, 2026

OIC - Handling Base64 Encoded JSON NXSD Parsing Issue in Oracle Integration Cloud (OIC)

๐Ÿ“Œ Problem Statement

In a Real-Time REST integration in Oracle Integration Cloud, the source system sends Base64 encoded JSON.

Flow:

Receive Base64 payload

Decode using oraext:decodeBase64()

Pass to Stage File → Read as JSON

Issue Faced

After decoding, the JSON becomes invalid because:

The closing curly brace } is missing

This causes NXSD parsing errors in Stage File

๐Ÿ” Root Cause

During decoding or transformation:

Extra whitespace / formatting issues

Improper encoding at source

OIC string handling edge cases

๐Ÿ‘‰ Result: JSON becomes malformed, especially missing }

๐Ÿ’ก Solution Approach

Instead of directly parsing decoded JSON:

✅ Step 1: Decode Base64

✅ Step 2: Clean the JSON string

✅ Step 3: Validate & fix missing closing brace

✅ Step 4: Re-encode to Base64

✅ Step 5: Pass as Opaque to Stage File

๐Ÿ› ️ Implementation (XSLT Logic)

Step 1: Decode Base64

Xslt

<xsl:variable name="decoded"

 select="oraext:decodeBase64(/nssrcmpr:execute/ns16:request-wrapper/ns16:message)"/>

Step 2: Clean unwanted whitespace

Xslt

<xsl:variable name="cleaned"

  select="replace($decoded, '(:\s*&quot;)\s+', '$1')"/>

๐Ÿ‘‰ Removes unnecessary spaces after : in JSON

Step 3: Fix Missing Closing Brace

Xslt

<xsl:variable name="finalJson">

  <xsl:choose>

    <xsl:when test="contains($cleaned, '}')">

      <xsl:value-of select="$cleaned"/>

    </xsl:when>

    <xsl:otherwise>

      <xsl:value-of select="concat($cleaned, '}')"/>

    </xsl:otherwise>

  </xsl:choose>

</xsl:variable>

๐Ÿ‘‰ Ensures JSON is always valid

Step 4: Encode Back to Base64

Xslt

<xsl:value-of select="oraext:encodeBase64($finalJson)"/>

๐Ÿ”„ Integration Flow Design

๐Ÿงฉ OIC Flow Steps

REST Trigger

Stage File (Write File)

Write as Opaque

Use above XSLT

Stage File (Read File)

Now JSON is valid

Parse using NXSD schema

Continue processing…

๐ŸŽฏ Why Opaque Handling Works

Using opaque avoids:

Early validation failures

NXSD parsing errors on invalid JSON

๐Ÿ‘‰ You fix JSON before parsing

⚠️ Best Practices

Always validate decoded payload:

Use contains() or ends-with() for }

Log decoded payload (for debugging)

Avoid direct parsing of decoded Base64 without validation

๐Ÿ Conclusion

Handling Base64 JSON in OIC can be tricky due to:

Encoding inconsistencies

Transformation side effects

๐Ÿ‘‰ The decode → clean → fix → re-encode → stage as opaque pattern is a reliable solution.

Code screenshots:

Stage write:




Code xslt:
Read json:




Code snippet:

<xsl:template match="/" xml:id="id_11">

  <nstrgmpr:Write xml:id="id_12">

    <ns31:opaqueElement>

      <!-- Step 1: Decode -->

      <xsl:variable name="decoded"     select="oraext:decodeBase64(/nssrcmpr:execute/ns16:request-wrapper/ns16:message)"/>

      <!-- Step 2: Clean whitespace after ":" -->

      <xsl:variable name="cleaned"

        select="replace($decoded, '(:\s*&quot;)\s+', '$1')"/>

      <!-- Step 3: Check and fix closing brace -->

      <xsl:variable name="finalJson">

        <xsl:choose>

          <xsl:when test="contains($cleaned, '}')">

            <xsl:value-of select="$cleaned"/>

          </xsl:when>

          <xsl:otherwise>

            <xsl:value-of select="concat($cleaned, '}')"/>

          </xsl:otherwise>

        </xsl:choose>

      </xsl:variable>

      <!-- Step 4: Encode back -->

      <xsl:value-of select="oraext:encodeBase64($finalJson)"/>

    </ns31:opaqueElement>

  </nstrgmpr:Write>

</xsl:template>


Monday, April 13, 2026

OIC - Handling Multiple Stub & Payment Matching in XSLT (OIC Optimization)

๐Ÿš€ Handling Multiple Stub & Payment Matching in XSLT (OIC Optimization)

๐Ÿ“Œ Problem Context

We receive:

Multiple StubRecords

Multiple PaymentRecords

Same Transaction Number across records

๐Ÿ‘‰ Goal:

Correctly match multiple stubs with multiple payments

Ensure accurate mapping

Avoid 120 sec XSLT timeout

⚠️ Issue with Traditional Matching

XML

//ns25:PaymentRecord[ns25:TransactionNumber = $txn]

❌ Fetches all records

❌ Incorrect matching

❌ Slow → Timeout

✅ Optimized Steps Using xsl:key

๐Ÿ”‘ Step 1: Define Keys

XML

<xsl:key name="stubKey"

         match="ns25:StubRecord"

         use="concat(ns25:TransactionNumber,'|',ns25:OperatorID)"/>


<xsl:key name="payKey"

         match="ns25:PaymentRecord"

         use="concat(ns25:TransactionNumber,'|',normalize-space(ns25:Filler3))"/>


<xsl:key name="payKeyExact"

         match="ns25:PaymentRecord"

         use="concat(ns25:TransactionNumber,'|',normalize-space(ns25:Filler3),'|',ns25:PaymentAmount)"/>

๐Ÿ”„ Step 2: Loop Through Stub Records

XML

<xsl:for-each select="$ReadSourceFile/.../ns25:StubRecord">

๐Ÿงฎ Step 3: Extract Values

XML

<xsl:variable name="txn" select="ns25:TransactionNumber"/>

<xsl:variable name="op" select="ns25:OperatorID"/>

<xsl:variable name="amt" select="ns25:PaidAmount"/>

๐Ÿ”— Step 4: Build Composite Keys

XML

<xsl:variable name="stubKeyVal" select="concat($txn,'|',$op)"/>

<xsl:variable name="payKeyVal" select="concat($txn,'|',$op)"/>

<xsl:variable name="payKeyExactVal" select="concat($txn,'|',$op,'|',$amt)"/>

Step 5: Fetch Using Key

XML

<xsl:variable name="sameStub" select="key('stubKey',$stubKeyVal)"/>

<xsl:variable name="payments" select="key('payKey',$payKeyVal)"/>

<xsl:variable name="paymentsExact" select="key('payKeyExact',$payKeyExactVal)"/>

๐Ÿ” Step 6: Handle Multiple Stub Records

XML

<xsl:if test="count($sameStub) > 1">

๐Ÿ‘‰ Ensures:

Only process when multiple stubs exist for same transaction + operator

Avoid incorrect or duplicate mapping

๐ŸŽฏ Step 7: Choose Best Payment Match

XML

<xsl:variable name="finalPayments"

    select="if (exists($paymentsExact)) then $paymentsExact else $payments"/>

๐Ÿ‘‰ Prefer:

Exact match (txn + operator + amount)

Else fallback

๐Ÿ”„ Step 8: Map & Merge Data

XML

<xsl:value-of select="normalize-space(ns25:StubAccountNumber)"/>


<xsl:value-of select="oraext:create-delimited-string($finalPayments/ns25:ChequeNumber,'|')"/>

๐Ÿ“ค Step 9: Generate Output

๐Ÿ‘‰ One output per valid stub, enriched with matched payments

๐ŸŽฏ Final One-Line Summary

๐Ÿ‘‰ “Use xsl:key with composite keys to accurately match multiple stub and payment records for the same transaction, handle multi-stub scenarios using count logic, and ensure optimized performance to avoid XSLT timeout in OIC.”

Code Screenshots:





Featured Post

OIC - OCI function Java code to encrypt and decrypt using AES key

Please find the below working code: Working Function code: package com.test .fn; import javax.crypto.Cipher; import javax.crypto.spec.IvPara...