osheroff/mysql-binlog-connector-java

Deserialization trouble with BINARY(16) columns for UUID

bobdaly opened this issue · 0 comments

Library version: 0.27.5
This UUID string value ab9d25e0-64e6-469f-9873-8621910ed300 came from: java.util.UUID.randomUUID().toString() (JDK version 11)

It was persisted to a MySQL 8.0 database column of type BINARY(16) using the UUID_TO_BIN() function.
Here is the relevant code relying on the binlog library:

WriteRowsEventData eventData = event.getData();
List<Serializable[]> rowData = eventData.getRows();
(iterate over rowData)
Object obj = (value from UUID/BINARY column which will come back as a byte[])

For the vast majority of UUIDs, the byte[] is of the expected length - 16.
But some, like the value included above, have a length of 15.

The following conversion will fail with only 15 bytes:
ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
long high = byteBuffer.getLong();
long low = byteBuffer.getLong();
java.util.UUID uuid = new UUID(high, low);

The exception is:
java.nio.BufferUnderflowException
at java.base/java.nio.Buffer.nextGetIndex(Buffer.java:650)
at java.base/java.nio.HeapByteBuffer.getLong(HeapByteBuffer.java:452)

If the incorrectly sized byte[] has a 16th byte added as follows:
bin2[15] = Byte.valueOf("00");
The conversion works.

I should also state that interacting with the persisted UUID using BIN_TO_UUID works as expected (i.e there is no problem from MySQL's perspective).

BTW, the CHAR_AND_BINARY_AS_BYTE_ARRAY compatibility mode is being set as well:
EventDeserializer eventDeserializer = new EventDeserializer();
eventDeserializer.setCompatibilityMode(
EventDeserializer.CompatibilityMode.CHAR_AND_BINARY_AS_BYTE_ARRAY
);
binaryLogClient.setEventDeserializer(eventDeserializer);