Was this page helpful?
ScyllaDB Java Driver is available under the Apache v2 License. ScyllaDB Java Driver is a fork of DataStax Java Driver. See Copyright here.
Caution
You're viewing documentation for a previous version of Scylla Java Driver. Switch to the latest stable version.
Advanced topic, only needed if you use Java serialization with driver rows or data types, or create tuple or UDT types manually.
Some driver components need to keep an internal reference to their originating Session. Under specific circumstances, they can lose that reference, and you might need to reattach them.
Namely, these components are:
result rows, and their column definitions.
Detachable types are an advanced topic, that should only be a concern for 3rd-party tool developers. If you’re simply executing requests and reading results, you probably won’t need to worry about them. See the bottom line at the end of this page for details.
Detachable components are those that encode or decode their fields themselves. For example, when you set a field on a tuple value:
tupleValue = tupleValue.setString(0, "foo");
The string “foo” is encoded immediately, and the TupleValue
object holds a reference to the binary
data. It is done that way in order to fail fast on encoding errors, and avoid duplicate work if you
reuse the tuple instance in multiple requests.
Encoding requires session-specific information:
the CodecRegistry instance (in case it contains custom codecs);
the protocol version (because the binary format can change across versions).
Therefore the tuple value needs a reference to the session to access those two objects.
Detachable types implement the Detachable interface, which has an isDetached()
method to check
the current status. Whenever you get an object from the driver, it is attached:
reading a row from a result set:
ResultSet rs = session.execute("SELECT * FROM foo");
Row row = rs.one();
assert !row.isDetached();
reading a data type from schema metadata:
UserDefinedType udt = session.getMetadata().getKeyspace("ks").getUserDefinedType("type1");
assert !udt.isDetached();
There is no way to detach an object explicitly. This can only happen when:
deserializing a previously serialized instance (we’re referring here to Java serialization);
attaching an object to another session;
creating a tuple or UDT definition manually:
TupleType tupleType = DataTypes.tupleOf(DataTypes.INT, DataTypes.TEXT, DataTypes.FLOAT);
assert tupleType.isDetached();
When an object is detached, it uses a default codec registry that only handles built-in types, and the latest non-beta protocol version supported by the driver. This might be good enough for you if you don’t use any custom codec (the binary format has been stable across modern protocol versions).
Use attach()
to reattach an object to the session:
TupleType tupleType = DataTypes.tupleOf(DataTypes.INT, DataTypes.TEXT, DataTypes.FLOAT);
assert tupleType.isDetached();
tupleType.attach(session.getContext());
assert !tupleType.isDetached();
// Now this will use the session's custom codecs if field 0 isn't a text CQL type:
TupleValue tupleValue = tupleType.newValue().setString(0, "foo");
When you pass a detached type to the session (for example by executing a request with a tuple value based on a detached tuple type), it will automatically be reattached.
If you’re reading data from one session and writing it into another, you should take a few extra precautions:
if you use custom codecs, they should obviously be registered with both sessions;
if the protocol version is different, you should avoid sharing UDT and tuple types; keep a separate set of definitions for each session, and copy the values field by field:
Row row = session1.execute("SELECT QUERY...").one();
UdtValue user1 = row.getUdtValue("user");
// Don't pass user1 to session2: create a new copy from userType2 instead
UserDefinedType userType2 =
session2.getMetadata().getKeyspace("ks").flatMap(ks -> ks.getUserDefinedType("user")).get();
UdtValue user2 = userType2.newValue();
user2.setString("first_name", user1.getString("first_name"));
user2.setString("last_name", user1.getString("last_name"));
session2.execute(SimpleStatement.newInstance("INSERT QUERY...", user2));
This will ensure that UDT definition are not accidentally reattached to the wrong session, and use the correct protocol version to encode values.
You only need to worry about detachable types if you serialize driver rows or data types, or if you create tuple or UDT types manually.
Even then, the defaults used by detached objects might be good enough for you:
the default codec registry works if you don’t have any custom codec;
the binary encoding format is stable across modern protocol versions. The last changes were for collection encoding from v2 to v3; Java driver 4 only supports v3 and above. When in doubt, check the “Changes” section of the protocol specifications.
Otherwise, just make sure you reattach objects any time you deserialize them or create them from scratch.
Was this page helpful?
ScyllaDB Java Driver is available under the Apache v2 License. ScyllaDB Java Driver is a fork of DataStax Java Driver. See Copyright here.