EngJon
EngJon

Reputation: 987

Spring Data Entity UUID is stored as legacy UUID in MongoDB

I'm dumping some data into my MongoDb and generate a UUID on the way. In the collection, this UUID field is stored as LUUID (legacy UUID - type 3) and I don't know how to avoid this, because I would want the format to be the standard UUID (type 4).

Entity:

@Document(collection = "sms")
public class SmsEntity {
    ...
    private UUID ubmMessageSid;  // <- this field gets stored as LUUID
    ...

    public static class Builder {
    ...
        private UUID ubmMessageSid;
    ...

        public Builder ubmMessageSid(UUID ubmMessageSid) {
            this.ubmMessageSid = ubmMessageSid;
            return this;
        }

        public SmsEntity build() {return new SmsEntity(this);}
    }
}

Repo:

@Repository
public interface SmsRepository extends CrudRepository<SmsEntity, String> {
}

Service storing this entity:

...
var ubmId = UUID.randomUUID();
var smsEntity = SmsEntity.builder()
    .ubmMessageSid(ubmId)
    ...
    .build();
repository.save(smsEntity);

Anything I have to annotate or configure to store the UUID as Binary/type4?

Upvotes: 6

Views: 6174

Answers (4)

Zap
Zap

Reputation: 346

In my case the property in the application.yml didn't work as well as the one using CodecRegistries. My working solution is:

MongoConfig.java:

    @Bean
    public MongoClient mongoClient() {
        MongoClientSettings.Builder builder = MongoClientSettings.builder();
        builder.uuidRepresentation(UuidRepresentation.JAVA_LEGACY);
        return MongoClients.create(builder.build());
    }

Upvotes: 0

tlogbon
tlogbon

Reputation: 1302

In Spring Boot 2, for Spring MongoDB 3.x, you can set this using the autoconfiguration properties:

# Options: unspecified, standard, c_sharp_legacy, java_legacy, python_legacy
spring.data.mongodb.uuid-representation=standard

Upvotes: 7

Azyl
Azyl

Reputation: 51

On version 3.x of Spring Data Mongo MongoClient has been replaced by MongoClientSettings:

CodecRegistry codecRegistry =
  CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(new UuidCodec(UuidRepresentation.JAVA_LEGACY)),
    MongoClientSettings.getDefaultCodecRegistry());

return new MongoClient(new ServerAddress(address, port), MongoClientSettings.builder().codecRegistry(codecRegistry).build());

Upvotes: 3

Spotvice
Spotvice

Reputation: 155

You can set the UUID codec in your Mongo config. That will persist your UUIDs with type 4 codec. The code you need to do that is the following:

CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(new UuidCodec(UuidRepresentation.STANDARD)),
                        MongoClient.getDefaultCodecRegistry());
        return new MongoClient(new ServerAddress(address, port), MongoClientOptions.builder().codecRegistry(codecRegistry).build());

Here is the complete class just in case:

import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.ServerAddress;
import org.bson.UuidRepresentation;
import org.bson.codecs.UuidCodec;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.config.AbstractMongoConfiguration;
import org.springframework.data.mongodb.core.mapping.event.ValidatingMongoEventListener;
import org.springframework.data.mongodb.repository.config.EnableMongoRepositories;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
@EnableAutoConfiguration
@EnableMongoRepositories(basePackages = "com.yourpackage.repositories")
public class MongoConfig extends AbstractMongoConfiguration {
    @Value("${mongo.database}")
    String database;
    @Value("${mongo.address}")
    String address;
    @Value("${mongo.port}")
    Integer port;

    @Override
    protected String getDatabaseName() {
        return database;
    }

    @Override
    public MongoClient mongoClient() {
        CodecRegistry codecRegistry =
                CodecRegistries.fromRegistries(CodecRegistries.fromCodecs(new UuidCodec(UuidRepresentation.STANDARD)),
                        MongoClient.getDefaultCodecRegistry());
        return new MongoClient(new ServerAddress(address, port), MongoClientOptions.builder().codecRegistry(codecRegistry).build());
    }

    @Bean
    public LocalValidatorFactoryBean localValidatorFactoryBean() {
        return new LocalValidatorFactoryBean();
    }

    @Bean
    public ValidatingMongoEventListener validatingMongoEventListener() {
        return new ValidatingMongoEventListener(localValidatorFactoryBean());
    }
}

Attention: With the new Spring Boot Version 2.2.0.RELEASE AbstractMongoConfiguration becomes deprecated and this is not working anymore. I made a post for that, maybe it's a bug or maybe someone knows the answer: Spring Boot Standard UUID codec not working with AbstractMongoClientConfiguration

Upvotes: 2

Related Questions