*** Considering verify_or_die() and the Middleware *** It all started with an icky bug in NetDB_Network.location()... In early 2015 Highwire Press was leaving the university and they were considering using their own copy of NetDB. We created a set of RMI scripts to copy Highwire Press data from the production NetDB to a new instance of NetDB. The script to copy networks should have been trivial: for each highwire network { Network.load(source,network).unlink().bind(destination).commit() } But it failed, throwing the exception "Record handle or ID must be supplied." That's because the database NetDB_Network.location() procedure only accepts an ID to identify the location: procedure location ( p_action in varchar, -- { add, remove } p_op_uid in int, p_lock in timestamp, p_network_id in int, p_location_id in int ) as v_net_id int := verify_or_die (p_network_id); v_loc_id int := NetDB_Location.verify_or_die (p_location_id); During the copy operation the network location had no ID in because it had been unlink()'d, hence the exception. The fix is simple, just add a location name argument to the procedure: procedure location ( p_action in varchar, -- { add, remove } p_op_uid in int, p_lock in timestamp, p_network_id in int := null, p_location_id in int := null, p_location in varchar := null ) <--- add location name as v_net_id int := verify_or_die (p_network_id); v_loc_id int := NetDB_Location.verify_or_die (p_location_id, p_location); <--- use it This is only an issue for things like creating a new, independent, copy of NetDB, which has never actually happened (Highwire Press decided to us a different IPAM system). Plus it can be worked around by removing and adding the location before the commit(): for each highwire network { net = Network.load(source,network).unlink().bind(destination) net.locations.each do |loc| loc_with_id = Location.load(destination,loc.handle) net.remove_location(loc).add_location(loc_with_id) end net.commit() } Thus there was no great urgency to fix the bug, and much time passed... We eventually got around to focusing on the issue in 2023. As part of our effort we examined all the PL/SQL packages, searching for other procedures that, like NetDB_Network.location(), accept IDs but not names. We found a few: NetDB_User.org NetDB_AdminTeam.{member,org} NetDB_DHCPoption.application_{add,remove} Of these, the DHCPoption procedures are unused and untested, so they can be changed with impunity and we will consider them no more. Here's where things get interesting. Examining the Java library code for User and AdminTeam we see they'll never throw the "Record handle or ID must be supplied" for a couple reasons: As Persons, AdminTeam members are always looked up in the directory before being added, and an ID is acquired during that process. This is necessary. NetDB_AdminTeam.member() is working as desired. The org() procedures in User and AdminTeam each call verify_or_die() with the organization name to set the organization ID: for (int i = 0; i < add_departments.size (); i++) { Department d = add_departments.get (i); d.id (d._verify_or_die (transaction_name, datastore, d.name ())); That runs afoul of a couple of our design principles, namely DRY (don't repeat yourself) and "the middleware should be as dumb as possible." It violates DRY because the first thing the PL/SQL procedure does is call verify_or_die(). Calling it from the java code is redundant. Of course it's necessary in this case to get the ID. Adding the department name to the PL/SQL procedure will obviate that necessity, remove the redundancy, and simplify the code. The middleware should be as dumb as possible. It really shouldn't have to call verify_ or_die() in such cases. And here we see that, if the back end supported the necessary arguments, the middleware wouldn't have to know about verify_or_die() for this case. Against our precepts, we worked around the icky bug in NetDB_Network.location() by calling verify_or_die() from the java middleware to get the location ID. This is the expedient solution, not the correct solution. But the correct solution is part of a larger sweep through the code to eliminate unnecessary verify_or_die() middleware calls. We've chosen a small, suboptimal, change for now, and have added implementing the proper solution to our plans. Will it be another 8 years before the correct solution is implemented? Tune in again next year to find out.