<jupyter_start><jupyter_text>Table of Contents1&nbsp;&nbsp;Forum Issue 85231.1&nbsp;&nbsp;Prerequisites1.2&nbsp;&nbsp;Initialization1.2.1&nbsp;&nbsp;Ensure database is running1.2.2&nbsp;&nbsp;Download and install additional components.1.3&nbsp;&nbsp;Connect to database and populate test data1.4&nbsp;&nbsp;Open a Terminal Tab2&nbsp;&nbsp;The Problem: No Error for Non-Existent UDF3&nbsp;&nbsp;Create UDF4&nbsp;&nbsp;Register UDF5&nbsp;&nbsp;Execute UDF (Works as Expected)6&nbsp;&nbsp;Register Again - Without Change7&nbsp;&nbsp;Register Again - With Change8&nbsp;&nbsp;Clean up9&nbsp;&nbsp;Further Exploration and Resources10&nbsp;&nbsp;Next steps  Forum Issue 8523Here is the link to the [Forum Issue](https://discuss.aerospike.com/t/calling-non-existent-udf-module-doesnt-throw-error/8523).This notebook requires Aerospike datbase running on localhost. Visit [Aerospike notebooks repo](https://github.com/aerospike-examples/interactive-notebooks) for additional details and the docker container.  PrerequisitesThis tutorial assumes familiarity with the following topics:- [Aerospike Notebooks - Readme and Tips](../readme_tips.ipynb)- [Hello World](hello_world.ipynb)  Initialization  Ensure database is runningThis notebook requires that Aerospike datbase is running.<jupyter_code>import io.github.spencerpark.ijava.IJava;
import io.github.spencerpark.jupyter.kernel.magic.common.Shell;
IJava.getKernelInstance().getMagics().registerMagics(Shell.class);
%sh asd<jupyter_output><empty_output><jupyter_text>Download and install additional components.Install the Java client.<jupyter_code>%%loadFromPOM
<dependencies>
  <dependency>
    <groupId>com.aerospike</groupId>
    <artifactId>aerospike-client</artifactId>
    <version>5.0.0</version>
  </dependency>
</dependencies><jupyter_output><empty_output><jupyter_text>Connect to database and populate test dataThe test data has 10 records with user-key "id-1" through "id-10", two bins (fields) "bin1" (1-10) and "bin2" ("1001"-"1010") in the namespace "test" and set "forum-8523".<jupyter_code>import com.aerospike.client.AerospikeClient;
import com.aerospike.client.Bin;
import com.aerospike.client.Key;
import com.aerospike.client.policy.WritePolicy;

AerospikeClient client = new AerospikeClient("localhost", 3000);
System.out.println("Initialized the client and connected to the cluster.");

String Namespace = "test";
String Set = "forum-8523";

WritePolicy wpolicy = new WritePolicy();
wpolicy.sendKey = true;
for (int i = 1; i <= 10; i++) {
    Key key = new Key(Namespace, Set, "id-"+i);
    Bin bin1 = new Bin(new String("bin1"), i);
    Bin bin2 = new Bin(new String("bin2"), 1000+i);
    Bin bin3 = new Bin(new String("bin3"), Integer.toString(1000+i));
    client.put(wpolicy, key, bin1, bin2, bin3);
}
System.out.format("Inserted 10 records in ns=%s set=%s.\n", Namespace, Set);<jupyter_output>Initialized the client and connected to the cluster.
Inserted 10 records in ns=test set=forum-8523.<jupyter_text>Open a Terminal TabIn this tutorial, you will be executing many shell commands including Aerospike tools like adadm and aql in a terminal. Open a terminal tab by selecting File->Open from the notebook menu, and then New->Terminal.  The Problem: No Error for Non-Existent UDF No exception is generated for a non-existent UDF.<jupyter_code>import com.aerospike.client.query.Statement;
import com.aerospike.client.query.Filter;
import com.aerospike.client.exp.Exp;
import com.aerospike.client.task.ExecuteTask;
import com.aerospike.client.Value;
import com.aerospike.client.lua.LuaCache;

Statement stmt = new Statement();
stmt.setNamespace(Namespace);
stmt.setSetName(Set);
WritePolicy policy = new WritePolicy();
policy.filterExp = Exp.build(
    Exp.and(
        Exp.ge(Exp.intBin("bin1"), Exp.val(4)),
        Exp.le(Exp.intBin("bin1"), Exp.val(7))));
policy.maxRetries = 0;

ExecuteTask task = client.execute(policy, stmt, "NonExistent", "doesnt_exist",
                                 Value.get("bin2"), Value.get(1), Value.get("bin3"), Value.get("xo")); 
task.waitTillComplete(3000, 3000);<jupyter_output><empty_output><jupyter_text>Examine the logs in the terminal tab. No error is logged.tail -20 /opt/aerospike/aerospike.log  Create UDFExamine the following Lua code that updates two bins by adding and appending the values provided. -- update the specified bins by adding and appending the values providedfunction add_append(rec, binName1, addVal, binName2, appendVal)    rec[binName1] = rec[binName1] + addVal    rec[binName2] = rec[binName2] .. appendVal    aerospike:update(rec)end  Register UDFNote, the UDF function is expected to be in "update_example.lua" file under "udf" directory.Register the UDF with the server by executing the following code cell. The function invalidates the cache, removes the currently registered module, and registers the latest version.<jupyter_code>import com.aerospike.client.policy.Policy;
import com.aerospike.client.task.RegisterTask;
import com.aerospike.client.Language;
import com.aerospike.client.lua.LuaConfig;
import com.aerospike.client.lua.LuaCache;

LuaConfig.SourceDirectory = "../udf";
String UDFModule = "update_example";
String UDFFile = "update_example.lua";

void registerUDF() {
    // clear the lua cache
    LuaCache.clearPackages();
    Policy policy = new Policy();
    // remove the current module, if any
    client.removeUdf(null, UDFFile);
    RegisterTask task = client.register(policy, LuaConfig.SourceDirectory+"/"+UDFFile, 
                                        UDFFile, Language.LUA);
    task.waitTillComplete();
    System.out.format("Registered the UDF module %s.", UDFFile);;
}

registerUDF();<jupyter_output>Registered the UDF module update_example.lua.<jupyter_text>Execute UDF (Works as Expected)Run the UDF on multiple records using an expression filter to specify records with bin1 values in the range 4-7 (both inclusive).<jupyter_code>import com.aerospike.client.query.Statement;
import com.aerospike.client.query.Filter;
import com.aerospike.client.exp.Exp;
import com.aerospike.client.task.ExecuteTask;
import com.aerospike.client.Value;

Statement stmt = new Statement();
stmt.setNamespace(Namespace);
stmt.setSetName(Set);
WritePolicy policy = new WritePolicy();
policy.filterExp = Exp.build(
    Exp.and(
        Exp.ge(Exp.intBin("bin1"), Exp.val(4)),
        Exp.le(Exp.intBin("bin1"), Exp.val(7))));
policy.maxRetries = 0;

ExecuteTask task = client.execute(policy, stmt, UDFModule, "add_append",
                                 Value.get("bin2"), Value.get(1), Value.get("bin3"), Value.get("xo")); 
task.waitTillComplete(3000, 3000);<jupyter_output><empty_output><jupyter_text>Examine the logs in the terminal tab. No error (as expected)tail -20 /opt/aerospike/aerospike.logExamine the database content in the terminal window. The bin values should be changed.aql -c "select * from test.forum-8523"  Register Again - Without ChangeRe-register without removing the existing UDF first. Note there is no exception or error.Executing the UDF works as expected.<jupyter_code>RegisterTask task = client.register(policy, LuaConfig.SourceDirectory+"/"+UDFFile, 
                                    UDFFile, Language.LUA);
task.waitTillComplete();
System.out.format("Registered the UDF module %s.", UDFFile);;

Statement stmt = new Statement();
stmt.setNamespace(Namespace);
stmt.setSetName(Set);
WritePolicy policy = new WritePolicy();
policy.filterExp = Exp.build(
    Exp.and(
        Exp.ge(Exp.intBin("bin1"), Exp.val(4)),
        Exp.le(Exp.intBin("bin1"), Exp.val(7))));
policy.maxRetries = 0;

ExecuteTask task = client.execute(policy, stmt, UDFModule, "add_append",
                                 Value.get("bin2"), Value.get(1), Value.get("bin3"), Value.get("xo")); 
task.waitTillComplete();<jupyter_output>Registered the UDF module update_example.lua.<jupyter_text>Examine the database content in the terminal window. The bin values should be changed.aql -c "select * from test.forum-8523"  Register Again - With ChangeChange the UDF as follows, save, and then register without removing the existing UDF. -- update the specified bins by adding and appending the values providedfunction add_append(rec, binName1, addVal, binName2, appendVal)    rec[binName1] = rec[binName1] + addVal    rec[binName2] = rec[binName2] .. appendVal .. addVal    aerospike:update(rec)endExecute the UDF and note the new version is in effect.<jupyter_code>RegisterTask task = client.register(policy, LuaConfig.SourceDirectory+"/"+UDFFile, 
                                    UDFFile, Language.LUA);
task.waitTillComplete();
System.out.format("Registered the UDF module %s.", UDFFile);;

Statement stmt = new Statement();
stmt.setNamespace(Namespace);
stmt.setSetName(Set);
WritePolicy policy = new WritePolicy();
policy.filterExp = Exp.build(
    Exp.and(
        Exp.ge(Exp.intBin("bin1"), Exp.val(4)),
        Exp.le(Exp.intBin("bin1"), Exp.val(7))));
policy.maxRetries = 0;

ExecuteTask task = client.execute(policy, stmt, UDFModule, "add_append",
                                 Value.get("bin2"), Value.get(1), Value.get("bin3"), Value.get("xo")); 
task.waitTillComplete();<jupyter_output>Registered the UDF module update_example.lua.<jupyter_text>Examine the database content in the terminal window. The bin values should be changed.aql -c "select * from test.forum-8523"  Clean upRemove tutorial data and close connection.<jupyter_code>client.truncate(null, Namespace, null, null);
client.close();
System.out.println("Removed tutorial data and closed server connection.");<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.11892569756505382, 'fraction_numerical': 0.018497230640610304, 'mean_word_length': 4.835365853658536, 'pattern_counts': {'":': 0, '<': 44, '<?xml version=': 0, '>': 45, 'https://': 2, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 9, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '378927', 'license': 'Apache-2.0', 'n_tokens_mistral': 3102, 'n_tokens_neox': 2945, 'n_words': 790, 'path': 'notebooks/java/forum-8523.ipynb', 'repo_name': 'artanderson/experiments', 'size': '9569'}