Skip to content

Latest commit

 

History

History
198 lines (156 loc) · 6.18 KB

custom-converters.adoc

File metadata and controls

198 lines (156 loc) · 6.18 KB

Creating custom converters with Spring Data Aerospike

Sometimes it is required to change default conversion logic of entities. You can either create custom converter for one field or for the whole entity.

Custom converter for a field

If you need to modify conversion only for save-related operations then you’ll need to create writing converter that implements Converter<%Your field type here%, Map<String, Object>>; for read-related operations — reading converter that implements Converter<Map<String, Object>, %Your field type here%>. In case read conversion depends on write conversion and vice versa — you’ll need to have both of the converters.

Let’s have a look at a simple document:

UserDocument.java
@Value
@Document
public class UserDocument {

    @Id
    long id;

    @Field
    UserData data;

    @Value
    public static class UserData {

        String address;
        String country;
    }
}

In this example we want to create both writing and reading converters for the UserData data field:

UserDataConverters.java
public class UserDataConverters {

    @WritingConverter
    public enum UserDataToMapConverter implements Converter<UserDocument.UserData, Map<String, Object>> {
        INSTANCE;

        @Override
        public Map<String, Object> convert(UserDocument.UserData source) {
            return Map.of(
                    "addr", source.address().toUpperCase(),
                    "country", source.country().toUpperCase()
            );
        }
    }

    @ReadingConverter
    public enum MapToUserDataToConverter implements Converter<Map<String, Object>, UserDocument.UserData> {
        INSTANCE;

        @Override
        public UserDocument.UserData convert(Map<String, Object> source) {
            String address = (String) source.getOrDefault("addr", "N/A");
            String country = (String) source.getOrDefault("country", "N/A");
            return new UserDocument.UserData(address, country);
        }
    }
}

Custom converters need to be registered in customConverters method in a configuration class that extends AbstractAerospikeDataConfiguration:

AerospikeConfiguration.java
@Configuration
public class AerospikeConfiguration extends AbstractAerospikeDataConfiguration {

    // other code omitted

    @Override
    protected List<?> customConverters() {
        return List.of(
                UserDataConverters.MapToUserDataToConverter.INSTANCE,
                UserDataConverters.UserDataToMapConverter.INSTANCE
        );
    }
}

Custom converter for an entity

If you need to modify conversion only for save-related operations then you’ll need to create writing converter that implements Converter<%Your entity type here%, AerospikeWriteData>; for read-related operations — reading converter that implements Converter<AerospikeReadData, %Your entity type here%>. In case read conversion depends on write conversion and vice versa — you’ll need to have both of the converters.

In this example we will use simple ArticleDocument as our entity:

ArticleDocument.java
@Value
@Document(collection = ArticleDocument.SET_NAME)
public class ArticleDocument {

    public static final String SET_NAME = "demo-service-articles";

    @Id
    String id;

    String author;

    String content;

    boolean draft;
}

Let’s create custom converters. In this specific example we are going to set expiration for the draft article to 10 seconds and for all other we will set expiration to none:

ArticleDocumentConverters.java

public class ArticleDocumentConverters {

    @WritingConverter
    @RequiredArgsConstructor
    public static class ArticleDocumentToAerospikeWriteDataConverter implements Converter<ArticleDocument, AerospikeWriteData> {

        private static final int TEN_SECONDS = 10;
        private static final int NEVER_EXPIRE = -1;
        private final String namespace;
        private final String setName;

        @Override
        public AerospikeWriteData convert(ArticleDocument source) {
            Key key = new Key(namespace, setName, source.getId());
            int expiration = source.isDraft() ? TEN_SECONDS : NEVER_EXPIRE;
            Integer version = null; // not versionable document
            Collection<Bin> bins = List.of(
                    new Bin("author", source.getAuthor()),
                    new Bin("content", source.getContent()),
                    new Bin("draft", source.isDraft())
            );
            return new AerospikeWriteData(key, bins, expiration, version);
        }
    }

    @ReadingConverter
    public enum AerospikeReadDataToArticleDocumentToConverter implements Converter<AerospikeReadData, ArticleDocument> {
        INSTANCE;

        @Override
        public ArticleDocument convert(AerospikeReadData source) {
            String id = (String) source.getKey().userKey.getObject();
            String author = (String) source.getValue("author");
            String content = (String) source.getValue("content");
            boolean draft = (boolean) source.getValue("draft");
            return new ArticleDocument(id, author, content, draft);
        }
    }
}

Now we need to register custom converters in customConverters method:

AerospikeConfiguration.java
@Configuration
@EnableAerospikeRepositories(basePackages = "com.demo.customconverters.repository")
public class AerospikeConfiguration extends AbstractAerospikeDataConfiguration {

    @Value("${spring.data.aerospike.namespace}")
    private String namespace;

    @Override
    protected List<Object> customConverters() {
        return List.of(
                UserDataConverters.MapToUserDataToConverter.INSTANCE,
                UserDataConverters.UserDataToMapConverter.INSTANCE,
                ArticleDocumentConverters.AerospikeReadDataToArticleDocumentToConverter.INSTANCE,
                new ArticleDocumentConverters.ArticleDocumentToAerospikeWriteDataConverter(namespace,
                        ArticleDocument.SET_NAME)
        );
    }
}

Demo application

To see demo application go to Custom Converters Demo.