Class CodecRegistry
- java.lang.Object
-
- org.apache.cassandra.cql3.functions.types.CodecRegistry
-
public final class CodecRegistry extends java.lang.Object
A registry forTypeCodec
s. When the driver needs to serialize or deserialize a Java type to/from CQL, it will lookup in the registry for a suitable codec. The registry is initialized with default codecs that handle basic conversions (e.g. CQLtext
tojava.lang.String
), and users can add their own. Complex codecs can also be generated on-the-fly from simpler ones (more details below).Creating a registry
By default, the driver uses
CodecRegistry#DEFAULT_INSTANCE
, a shareable, JVM-wide instance initialized with built-in codecs for all the base CQL types. The only reason to create your own instances is if you have multipleCluster
objects that use different sets of codecs. In that case, useCluster.Builder#withCodecRegistry(CodecRegistry)
to associate the registry with the cluster:CodecRegistry myCodecRegistry = new CodecRegistry(); myCodecRegistry.register(myCodec1, myCodec2, myCodec3); Cluster cluster = Cluster.builder().withCodecRegistry(myCodecRegistry).build(); // To retrieve the registry later: CodecRegistry registry = cluster.getConfiguration().getCodecRegistry();
CodecRegistry
instances are thread-safe.It is possible to turn on log messages by setting the
CodecRegistry
logger level toTRACE
. Beware that the registry can be very verbose at this log level.Registering and using custom codecs
To create a custom codec, write a class that extends
TypeCodec
, create an instance, and pass it to one of theregister
methods; for example, one could create a codec that maps CQL timestamps to JDK8'sjava.time.LocalDate
:class LocalDateCodec extends TypeCodec<java.time.LocalDate> { ... } myCodecRegistry.register(new LocalDateCodec());
The conversion will be available to:
- all driver types that implement
GettableByIndexData
,GettableByNameData
,SettableByIndexData
and/orSettableByNameData
. Namely:Row
,BoundStatement
,UDTValue
andTupleValue
; SimpleStatement#SimpleStatement(String, Object...) simple statements
;- statements created with the
querybuilder.QueryBuilder Query builder
.
Example:
Row row = session.executeQuery("select date from some_table where pk = 1").one(); java.time.LocalDate date = row.get(0, java.time.LocalDate.class); // uses LocalDateCodec registered above
You can also bypass the codec registry by passing a standalone codec instance to methods such as
GettableByIndexData.get(int, TypeCodec)
.Codec generation
When a
CodecRegistry
cannot find a suitable codec among existing ones, it will attempt to create it on-the-fly. It can manage:- collections (lists, sets and maps) of known types. For example, if you registered a codec
for JDK8's
java.time.LocalDate
like in the example above, you getList<LocalDate>>
andSet<LocalDate>>
handled for free, as well as allMap
types whose keys and/or values arejava.time.LocalDate
. This works recursively for nested collections; user types
, mapped toUDTValue
objects. Custom codecs are available recursively to the UDT's fields, so if one of your fields is atimestamp
you can use yourLocalDateCodec
to retrieve it as ajava.time.LocalDate
;tuple types
, mapped toTupleValue
(with the same rules for nested fields);custom types
, mapped toByteBuffer
.
If the codec registry encounters a mapping that it can't handle automatically, a
CodecNotFoundException
is thrown; you'll need to register a custom codec for it.Performance and caching
Whenever possible, the registry will cache the result of a codec lookup for a specific type mapping, including any generated codec. For example, if you registered
LocalDateCodec
and ask the registry for a codec to convert a CQLlist<timestamp>
to a JavaList<LocalDate>
:- the first lookup will generate a
TypeCodec<List<LocalDate>>
fromLocalDateCodec
, and put it in the cache; - the second lookup will hit the cache directly, and reuse the previously generated instance.
The javadoc for each
codecFor
variant specifies whether the result can be cached or not.Codec order
When the registry looks up a codec, the rules of precedence are:
- if a result was previously cached for that mapping, it is returned;
- otherwise, the registry checks the list of built-in codecs – the default ones – and the
ones that were explicitly registered (in the order that they were registered). It calls
each codec's
accepts
methods to determine if it can handle the mapping, and if so returns it; - otherwise, the registry tries to generate a codec, according to the rules outlined above.
It is currently impossible to override an existing codec. If you try to do so,
register(TypeCodec)
will log a warning and ignore it. - all driver types that implement
-
-
Constructor Summary
Constructors Constructor Description CodecRegistry()
Creates a new instance initialized with built-in codecs for all the base CQL types.
-
Method Summary
All Methods Instance Methods Concrete Methods Modifier and Type Method Description <T> TypeCodec<T>
codecFor(DataType cqlType)
<T> TypeCodec<T>
codecFor(DataType cqlType, com.google.common.reflect.TypeToken<T> javaType)
<T> TypeCodec<T>
codecFor(DataType cqlType, java.lang.Class<T> javaType)
<T> TypeCodec<T>
codecFor(DataType cqlType, T value)
<T> TypeCodec<T>
codecFor(T value)
Returns acodec
that accepts the given value.CodecRegistry
register(java.lang.Iterable<? extends TypeCodec<?>> codecs)
Register the given codecs with this registry.CodecRegistry
register(TypeCodec<?> newCodec)
Register the given codec with this registry.CodecRegistry
register(TypeCodec<?>... codecs)
Register the given codecs with this registry.
-
-
-
Method Detail
-
register
public CodecRegistry register(TypeCodec<?> newCodec)
Register the given codec with this registry.This method will log a warning and ignore the codec if it collides with a previously registered one. Note that this check is not done in a completely thread-safe manner; codecs should typically be registered at application startup, not in a highly concurrent context (if a race condition occurs, the worst possible outcome is that no warning gets logged, and the codec gets registered but will never actually be used).
- Parameters:
newCodec
- The codec to add to the registry.- Returns:
- this CodecRegistry (for method chaining).
-
register
public CodecRegistry register(TypeCodec<?>... codecs)
Register the given codecs with this registry.- Parameters:
codecs
- The codecs to add to the registry.- Returns:
- this CodecRegistry (for method chaining).
- See Also:
register(TypeCodec)
-
register
public CodecRegistry register(java.lang.Iterable<? extends TypeCodec<?>> codecs)
Register the given codecs with this registry.- Parameters:
codecs
- The codecs to add to the registry.- Returns:
- this CodecRegistry (for method chaining).
- See Also:
register(TypeCodec)
-
codecFor
public <T> TypeCodec<T> codecFor(T value)
Returns acodec
that accepts the given value.This method takes an arbitrary Java object and tries to locate a suitable codec for it. Codecs must perform a
runtime inspection
of the object to determine if they can accept it or not, which, depending on the implementations, can be expensive; besides, the resulting codec cannot be cached. Therefore there might be a performance penalty when using this method.Furthermore, this method returns the first matching codec, regardless of its accepted CQL type. It should be reserved for situations where the target CQL type is not available or unknown. In the Java driver, this happens mainly when serializing a value in a
SimpleStatement#SimpleStatement(String, Object...) SimpleStatement
or in thequerybuilder.QueryBuilder
, where no CQL type information is available.Codecs returned by this method are NOT cached (see the
top-level documentation
of this class for more explanations about caching).- Parameters:
value
- The value the codec should accept; must not benull
.- Returns:
- A suitable codec.
- Throws:
CodecNotFoundException
- if a suitable codec cannot be found.
-
codecFor
public <T> TypeCodec<T> codecFor(DataType cqlType) throws CodecNotFoundException
Returns acodec
that accepts the givenCQL type
.This method returns the first matching codec, regardless of its accepted Java type. It should be reserved for situations where the Java type is not available or unknown. In the Java driver, this happens mainly when deserializing a value using the
getObject
method.Codecs returned by this method are cached (see the
top-level documentation
of this class for more explanations about caching).- Parameters:
cqlType
- TheCQL type
the codec should accept; must not benull
.- Returns:
- A suitable codec.
- Throws:
CodecNotFoundException
- if a suitable codec cannot be found.
-
codecFor
public <T> TypeCodec<T> codecFor(DataType cqlType, java.lang.Class<T> javaType) throws CodecNotFoundException
Returns acodec
that accepts the givenCQL type
and the given Java class.This method can only handle raw (non-parameterized) Java types. For parameterized types, use
codecFor(DataType, TypeToken)
instead.Codecs returned by this method are cached (see the
top-level documentation
of this class for more explanations about caching).- Parameters:
cqlType
- TheCQL type
the codec should accept; must not benull
.javaType
- The Java type the codec should accept; can benull
.- Returns:
- A suitable codec.
- Throws:
CodecNotFoundException
- if a suitable codec cannot be found.
-
codecFor
public <T> TypeCodec<T> codecFor(DataType cqlType, com.google.common.reflect.TypeToken<T> javaType) throws CodecNotFoundException
Returns acodec
that accepts the givenCQL type
and the given Java type.This method handles parameterized types thanks to Guava's
TypeToken
API.Codecs returned by this method are cached (see the
top-level documentation
of this class for more explanations about caching).- Parameters:
cqlType
- TheCQL type
the codec should accept; must not benull
.javaType
- TheJava type
the codec should accept; can benull
.- Returns:
- A suitable codec.
- Throws:
CodecNotFoundException
- if a suitable codec cannot be found.
-
codecFor
public <T> TypeCodec<T> codecFor(DataType cqlType, T value)
Returns acodec
that accepts the givenCQL type
and the given value.This method takes an arbitrary Java object and tries to locate a suitable codec for it. Codecs must perform a
runtime inspection
of the object to determine if they can accept it or not, which, depending on the implementations, can be expensive; besides, the resulting codec cannot be cached. Therefore there might be a performance penalty when using this method.Codecs returned by this method are NOT cached (see the
top-level documentation
of this class for more explanations about caching).- Parameters:
cqlType
- TheCQL type
the codec should accept; can benull
.value
- The value the codec should accept; must not benull
.- Returns:
- A suitable codec.
- Throws:
CodecNotFoundException
- if a suitable codec cannot be found.
-
-