connect icon indicating copy to clipboard operation
connect copied to clipboard

[BUG] DatabaseReceiver Cannot Accept Empty Sets without Error to Server Log

Open mbartlettglytec opened this issue 3 years ago • 2 comments

Describe the bug We're attempting to upgrade an instance of Mirth Connect from v3.9 --> v3.12.

In our legacy code, we would use Mirth's Database Reader Connector to execute a SQL query and receive anywhere from 0 -> n messages to be Filtered/Transformed/Sent to other Destinations, etc.

In 3.9, if our SQL Stored Procedure [DatabaseConnection.executeCachedQuery(String expression)] returned an empty set, we would pass back a new (empty) instance of a CachedRowSetImpl to the DatabaseReader - at which point the Connector would just fail to read any messages, and sit quietly until the next polling period (every 5 seconds).

After the upgrade to 3.12, passing back this empty CachedRowSetImpl object sends an Error to our ServerLog, and because it happens within the Mirth's 'DatabaseReceiver' code, we can't catch these or ignore them. We don't even get to the Source Filter to execute anything. As a result, we generate an Error every five seconds we check the DB and don't find any messages, flooding the logs; we can't move forward like that.

This is the result the 3.12 MC Database Reader is choking on. result = new Packages.com.sun.rowset.CachedRowSetImpl();

I've tried many things to get the DatabaseReceiver to be quiet - I've sent a new MirthCachedRowSet object, I've sent empty strings, I've sent nulls, I've sent 0's, and nothing is working.

We can't find any workarounds. Can someone figure out how to get the Database Reader to "shut up" when we don't get anything back from the database?

Expected behavior In the event SQL doesn't return any message content, we expect to send a new Packages.com.sun.rowset.CachedRowSetImpl() object to the DatabaseReader, and quietly error out - every five seconds.

Actual behavior In the event SQL doesn't return any message content, the ServerLog yells at us about a NullPointerException every five seconds, and we can't turn it off or catch it.

[2022-01-27 09:21:15,004] ERROR (com.mirth.connect.connectors.jdbc.DatabaseReceiver:159): Failed to poll for messages from the database in channel "REDACTED" com.mirth.connect.connectors.jdbc.DatabaseReceiverException: java.lang.NullPointerException at com.mirth.connect.connectors.jdbc.DatabaseReceiver.processResultSet(DatabaseReceiver.java:219) at com.mirth.connect.connectors.jdbc.DatabaseReceiver.poll(DatabaseReceiver.java:149) at com.mirth.connect.donkey.server.channel.PollConnectorJob.execute(PollConnectorJob.java:49) at org.quartz.core.JobRunShell.run(JobRunShell.java:213) at org.quartz.simpl.SimpleThreadPool$WorkerThread.run(SimpleThreadPool.java:557)Caused by: java.lang.NullPointerException at com.mirth.connect.connectors.jdbc.DatabaseReceiver.checkForDuplicateColumns(DatabaseReceiver.java:225) at com.mirth.connect.connectors.jdbc.DatabaseReceiver.processResultSet(DatabaseReceiver.java:187) ... 4 more

I've noticed that the 'checkForDuplicateColumns' doesn't occur in 3.9's processResultSet(), but occurs in 3.12's. Not sure if that's where the extra check (and NullPointerException) are coming from. Could just be a red herring.

Environment (please complete the following information):

  • OS: CentOS 7 (Mirth Appliance)
  • Java Distribution/Version: OpenJDK 11 (11+28)
  • Connect Version: 3.12.0

Workaround(s) No workarounds, please help us find one!

mbartlettglytec avatar Jan 27 '22 15:01 mbartlettglytec

The issue is the definitely checkForDuplicateColumns call. The CachedRowSetImpl doesn't initialize the field that contains the RowSetMetaData object until populate(Rowset rs) is called. You'd have write your own Java code to implement a "DevNull" version of a Rowset that will return a RowSetMetadata object that has the column count set to 0. Then use that in place of the CachedRowSetImpl if your query has no results.

EDIT: Actually the workaround is simpler than a custom rowset implementation. When you detect the empty result set from your stored procedure: return new java.util.ArrayList();

ab-20-m avatar Jan 27 '22 19:01 ab-20-m

Can you show the code you're using or a minimal example that shows the issue?

Would a minimal example for this case be SELECT 1 WHERE 1 = 2?

jonbartels avatar Jan 27 '22 19:01 jonbartels