Skip to content

1.9.1

Latest
Compare
Choose a tag to compare
@armiol armiol released this 27 Sep 16:23
43e6946

This is a minor release of Spine's Google Cloud library in 1.x family, which, however, brings a minor breaking change into API.

Custom column mappings via DsColumnMapping

In particular, it is now possible to override the default mappings provided by DsColumnMapping. Previously, SPI users could only extend DsColumnMapping's behavior by overriding this method:

protected void setupCustomMapping(
            ImmutableMap.Builder<Class<?>, ColumnTypeMapping<?, ? extends Value<?>>> builder);

It was good enough if one wanted to append their mapping rules. But such an approach did not allow to re-define the existing (framework-default) mapping — since a builder of ImmutableMap was passed, preventing from having duplicate keys.

This method is now made final, effectively closing it as an extension point.

Now, the API for SPI users implies overriding another method:

@SPI
protected ImmutableMap<Class<?>, ColumnTypeMapping<?, ? extends Value<?>>> customMapping()

This one allows to return an immutable map of mappings, combining them into the final result, giving priority to those values which were provided by SPI users.

Please see the documentation for DsColumnMapping for more details.

How to use it

Referring to the original issue, end-users may configure how Timestamp.getDefaultValue() is stored for some column. In the example below, a Datastore-specific null is written for such values to the corresponding property of respective Datastore Entity:

/**
 * A mapping similar to the default one,
 * but telling to store {@link Timestamp}s as {@code null}s.
 */
public final class CustomMapping extends DsColumnMapping {

    @Override
    protected ImmutableMap<Class<?>, ColumnTypeMapping<?, ? extends Value<?>>> customMapping() {
        return ImmutableMap.of(Timestamp.class, ofNullableTimestamp());
    }

    @SuppressWarnings("UnnecessaryLambda" /* For brevity */)
    private static ColumnTypeMapping<Timestamp, Value<?>> ofNullableTimestamp() {
        return timestamp -> {
            if (timestamp.equals(Timestamp.getDefaultInstance())) {
                return NullValue.of();
            }
            return TimestampValue.of(
                    ofTimeSecondsAndNanos(timestamp.getSeconds(), timestamp.getNanos())
            );
        };
    }
}

See #186 for more detail on the change.