'Issues calling Java from Ballerina

This code below for ballerina Java interop is failing to generate the data signature. Can you spot why it is failing on the following line?

The code is run with Ballerina slalpha5. Java version: openjdk version "15.0.1" 2020-10-20

I have checked the signature of the java classes and methods, all seems correct to me.

`var signedDataHandle = check generateSignature(signature);`

    import ballerina/jballerina.java;
    import ballerina/jballerina.java.arrays;
    import ballerina/io;
    
    public function main() returns error? {
    
        var data = "Test data!".toBytes();
        var { encodedPublicKey, encodedPrivateKey } = check generateKeyTestPair();
        var signedData = check signData(data, encodedPrivateKey);
    
        io:println(signedData.length());
    }
    
    function signData(byte[] data, byte[] encodedPrivateKey) returns byte[]|error {
    
        var pkcs8EncodedKeySpec = newPKCS8EncodedKeySpec(check arrays:toHandle(encodedPrivateKey, "byte"));
        var keyFactory = check getKeyFactoryInstance(java:fromString("RSA"));
        var privateKey = check generatePrivateKey(keyFactory, pkcs8EncodedKeySpec);
        var signature = check getSignatureInstance(java:fromString("SHA256withRSA"));
    
        check initDataSigning(signature, privateKey);
        check updateSignatureData(signature, check arrays:toHandle(data, "byte"));
    
        // The line below is failing
        var signedDataHandle = check generateSignature(signature);
        var signedData = <byte[]> check arrays:fromHandle(signedDataHandle, "byte");
    
        return signedData;
    }
    
    function generateKeyTestPair() returns record { byte[] 'encodedPublicKey; byte[] 'encodedPrivateKey; }|error {
    
        var keyPairGenerator = check getKeyPairGeneratorInstance(java:fromString("RSA"));
    
        initializeKeyPairGenerator(keyPairGenerator, 1024);
        
        var keyPair = generateKeyPair(keyPairGenerator);
        var privateKey = getPrivateKeyFromKeyPair(keyPair);
        var publicKey = getPublicKeyFromKeyPair(keyPair);
    
        return {
            encodedPublicKey: <byte[]> check arrays:fromHandle(getEncodedPublicKey(publicKey), "byte"),
            encodedPrivateKey: <byte[]> check arrays:fromHandle(getEncodedPrivateKey(privateKey), "byte")
        };
    }
    
    isolated function getKeyFactoryInstance(handle algorithm) returns handle|error = @java:Method {
        'class: "java.security.KeyFactory",
        name: "getInstance"
    } external;
    
    isolated function newPKCS8EncodedKeySpec(handle encodedKey) returns handle = @java:Constructor {
        'class: "java.security.spec.PKCS8EncodedKeySpec"
    } external;
    
    isolated function generatePrivateKey(handle receiver, handle keySpec) returns handle|error = @java:Method {
        'class: "java.security.KeyFactory",
        name: "generatePrivate"
    } external;
    
    isolated function getSignatureInstance(handle algorithm) returns handle|error = @java:Method {
        'class: "java.security.Signature",
        name: "getInstance",
        paramTypes: ["java.lang.String"]
    } external;
    
    isolated function initDataSigning(handle receiver, handle privateKey) returns error? = @java:Method {
        'class: "java.security.Signature",
        name: "initSign",
        paramTypes: ["java.security.PrivateKey"]
    } external;
    
    isolated function updateSignatureData(handle receiver, handle data) returns error? = @java:Method {
        'class: "java.security.Signature",
        name: "update",
        paramTypes: [{ 'class: "byte", dimensions: 1 }]
    } external;
    
    isolated function generateSignature(handle receiver) returns handle|error = @java:Method {
        'class: "java.security.Signature",
        name: "sign"
    } external;
    
    isolated function getKeyPairGeneratorInstance(handle algorithm) returns handle|error = @java:Method {
        'class: "java.security.KeyPairGenerator",
        name: "getInstance"
    } external;
    
    isolated function initializeKeyPairGenerator(handle receiver, int keySize) = @java:Method {
        'class: "java.security.KeyPairGenerator",
        name: "initialize",
        paramTypes: ["int"]
    } external;
    
    isolated function generateKeyPair(handle receiver) returns handle = @java:Method {
        'class: "java.security.KeyPairGenerator",
        name: "generateKeyPair"
    } external;
    
    isolated function getPrivateKeyFromKeyPair(handle receiver) returns handle = @java:Method {
        'class: "java.security.KeyPair",
        name: "getPrivate"
    } external;
    
    isolated function getPublicKeyFromKeyPair(handle receiver) returns handle = @java:Method {
        'class: "java.security.KeyPair",
        name: "getPublic"
    } external;
    
    
    isolated function getEncodedPrivateKey(handle receiver) returns handle = @java:Method {
        'class: "java.security.Key",
        name: "getEncoded"
    } external;
    
    isolated function getEncodedPublicKey(handle receiver) returns handle = @java:Method {
        'class: "java.security.PublicKey",
        name: "getEncoded"
    } external;



Solution 1:[1]

This looks like a bug in Ballerina. Issue created to get this fixed: https://github.com/ballerina-platform/ballerina-lang/issues/30949

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Dhananjaya