I'v started looking for nice solution how to nicely persist entity using Spring CassandraOperations. The problems started because some fields within my entity is not cassandra supported, e.g. joda DateTime.
The workaround is to have additional fields within the same entity of type java.util.Date instead of joda DateTime, mark unrequired fields with @Transient. But this is not clean, so I started looking for automatic custom conversion.
Currently spring-data-cassandra reference does not provide information how to register custom converter. http://docs.spring.io/spring-data/cassandra/docs/current/reference/html/#cassandra.custom-converters
Is it possible to register custom converter (like here Spring Data Cassandra LocalDateTime Conversion) in CassandraSessionFactoryBean?
This is my code @Configuration public class CassandraConfig {
@Value("${cassandra.contactpoints}")
private String cassandraContactPoint;
@Value("${cassandra.port}")
private int cassandraPort;
@Value("${cassandra.keyspace}")
private String cassandraKeySpace;
@Bean
public CassandraClusterFactoryBean cluster() {
CassandraClusterFactoryBean cluster = new CassandraClusterFactoryBean();
cluster.setContactPoints(cassandraContactPoint);
cluster.setPort(cassandraPort);
return cluster;
}
@Bean
public CassandraMappingContext mappingContext() {
return new BasicCassandraMappingContext();
}
@Bean
public CassandraConverter converter() {
return new MappingCassandraConverter(mappingContext());
}
@Bean
public CassandraSessionFactoryBean session() throws Exception {
CassandraSessionFactoryBean session = new CassandraSessionFactoryBean();
session.setCluster(cluster().getObject());
session.setKeyspaceName(cassandraKeySpace);
session.setConverter(converter());
session.setSchemaAction(SchemaAction.NONE);
return session;
}
@Bean
public CassandraOperations cassandraTemplate() throws Exception {
return new CassandraTemplate(session().getObject());
}
@Bean
public ConversionService getConversionService() {
ConversionServiceFactoryBean bean = new ConversionServiceFactoryBean();
bean.setConverters(new HashSet<>(getConverters()));
bean.afterPropertiesSet();
return bean.getObject();
}
private Set<Converter<?, ?>> getConverters() {
Set<Converter<?, ?>> converters = new HashSet<>();
converters.addAll(Jsr310Converters.getConvertersToRegister());
converters.add(new DateTimeWriteConverter());
converters.add(new DateTimeReadConverter());
return converters;
}
public static class DateTimeWriteConverter implements Converter<DateTime, Long> {
@Override
public Long convert(DateTime source) {
return source.getMillis();
}
}
public static class DateTimeReadConverter implements Converter<Long, DateTime> {
@Override
public DateTime convert(Long source) {
return new DateTime(source);
}
}
}
Spring Cassandra's custom conversion works when you create a CassandraCustomConversions bean. Just add your custom converter and the default converters will stay. Below is my @Configuration class.
@Bean
CassandraCustomConversions cassandraCustomConversions() {
List<Converter<?, ?>> converters = new ArrayList<>();
converters.add(new MyDataReadConverter());
return new CassandraCustomConversions(converters);
}
static class CounterDataReadConverter implements Converter<ByteBuffer, MyData> {
@Override
public MyData convert(ByteBuffer source) {
try {
return MyData.parseFrom(source.array());
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
I am using spring-boot-starter-data-cassandra based on SpringBoot 2.0.0.RELEASE.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With