If you’ve tried to store a custom Java object inside a Cassandra table using Spring Data Cassandra and encountered an error like:
No converter found capable of converting from type [com.example.TransactionEntity] to type [com.datastax.oss.driver.api.core.data.UdtValue]
you’re not alone. This error appears when Spring Data Cassandra can’t map your Java class to a Cassandra User-Defined Type (UDT). In this article, you’ll learn why this happens and how to fix it step-by-step.
Why the Error Happens
Cassandra stores primitive types (text, int, boolean, etc.) easily, but when you embed a complex object in another entity (for example, a TransactionEntity
inside an Account
entity), Spring Data Cassandra expects a corresponding UDT to be defined in the keyspace. Without a UDT or a converter, Spring cannot serialize the object to Cassandra’s format, which triggers the “No converter found…” exception.
Step 1: Define a User-Defined Type in Cassandra
First, create a UDT in your Cassandra keyspace that matches your Java object fields:
CREATE TYPE IF NOT EXISTS transaction_type (
mandate_id text,
check_id text,
creditor_id text
);
This schema corresponds to a Java class like:
public class TransactionEntity {
private String mandateId;
private String checkId;
private String creditorId;
// getters and setters
}
Step 2: Annotate Your Java Classes
Mark your UDT class with @UserDefinedType
so Spring knows it maps to a Cassandra type:
import org.springframework.data.cassandra.core.mapping.UserDefinedType;
@UserDefinedType("transaction_type")
public class TransactionEntity {
private String mandateId;
private String checkId;
private String creditorId;
// getters and setters
}
Then, in your entity class, refer to the UDT:
@Table("accounts")
public class Account {
@PrimaryKey
private String id;
private TransactionEntity transaction; // mapped to transaction_type
}
Step 3: Register a UserDefinedType
Bean
If you prefer to manually control the mapping (or need access to UdtValue
), expose the UDT as a Spring bean:
@Configuration
public class CassandraConfig {
private final CqlSession session;
public CassandraConfig(CqlSession session) {
this.session = session;
}
@Bean
public UserDefinedType transactionType() {
return session.getMetadata()
.getKeyspace("your_keyspace").orElseThrow()
.getUserDefinedType("transaction_type").orElseThrow();
}
}
This ensures Spring can inject the UserDefinedType
into your converters or services.
Step 4: (Optional) Write a Custom Converter
For fine-grained control, write a converter to transform your Java object into a UdtValue
:
public class TransactionEntityToUdtConverter
implements Converter<TransactionEntity, UdtValue> {
private final UserDefinedType udtType;
public TransactionEntityToUdtConverter(UserDefinedType udtType) {
this.udtType = udtType;
}
@Override
public UdtValue convert(TransactionEntity source) {
if (source == null) return null;
return udtType.newValue()
.setString("mandate_id", source.getMandateId())
.setString("check_id", source.getCheckId())
.setString("creditor_id", source.getCreditorId());
}
}
Register the converter:
@Bean
public CassandraCustomConversions cassandraCustomConversions(UserDefinedType transactionType) {
return new CassandraCustomConversions(
List.of(new TransactionEntityToUdtConverter(transactionType))
);
}
Step 5: Save and Query the Data
Now you can persist your objects without errors:
accountRepository.save(new Account("123",
new TransactionEntity("m1", "c1", "cr1")));
Spring Data Cassandra will convert your TransactionEntity
into the UDT automatically.
SEO Keywords to Target
- Spring Data Cassandra custom object mapping
- Cassandra User Defined Type Java example
- No converter found capable of converting UdtValue
- Spring Cassandra @UserDefinedType
- CassandraCustomConversions example
Final Thoughts
The “No converter found…” error is a common stumbling block when moving from simple Cassandra schemas to richer domain models. The fix is to:
- Define a UDT in Cassandra.
- Map your Java class with
@UserDefinedType
. - Optionally create a custom converter.
- Register a
UserDefinedType
bean if needed.
Following these steps ensures Spring Data Cassandra can seamlessly convert your Java objects to Cassandra’s storage format.