Generator-jhipster: org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class java.time.ZonedDateTime

Created on 8 Aug 2018  路  8Comments  路  Source: jhipster/generator-jhipster

Overview of the issue

With a project upgraded to Jhipster5, when saving a document that have afield of type java.util.Date into MongoDB I get the following exception. It happens that SpringDataMongo convert the field date to the type ZoneDateTime.
The problem probably exists for the other converters of class JSR310DateConverters

org.bson.codecs.configuration.CodecConfigurationException: Can't find a codec for class java.time.ZonedDateTime.
at org.bson.codecs.configuration.CodecCache.getOrThrow(CodecCache.java:46)
at org.bson.codecs.configuration.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:63)
at org.bson.codecs.configuration.ChildCodecRegistry.get(ChildCodecRegistry.java:51)
at org.bson.codecs.DocumentCodec.writeValue(DocumentCodec.java:184)
at org.bson.codecs.DocumentCodec.writeMap(DocumentCodec.java:199)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:141)
at org.bson.codecs.DocumentCodec.encode(DocumentCodec.java:45)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
at com.mongodb.operation.BulkWriteBatch$WriteRequestEncoder.encode(BulkWriteBatch.java:381)
at com.mongodb.operation.BulkWriteBatch$WriteRequestEncoder.encode(BulkWriteBatch.java:371)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
at com.mongodb.connection.BsonWriterHelper.writeDocument(BsonWriterHelper.java:74)
at com.mongodb.connection.BsonWriterHelper.writePayload(BsonWriterHelper.java:58)
at com.mongodb.connection.CommandMessage.encodeMessageBodyWithMetadata(CommandMessage.java:133)
at com.mongodb.connection.RequestMessage.encode(RequestMessage.java:147)
at com.mongodb.connection.InternalStreamConnection.sendAndReceive(InternalStreamConnection.java:245)
at com.mongodb.connection.UsageTrackingInternalConnection.sendAndReceive(UsageTrackingInternalConnection.java:98)
at com.mongodb.connection.DefaultConnectionPool$PooledConnection.sendAndReceive(DefaultConnectionPool.java:441)
at com.mongodb.connection.CommandProtocolImpl.execute(CommandProtocolImpl.java:80)
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:189)
at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:264)
at com.mongodb.connection.DefaultServerConnection.command(DefaultServerConnection.java:126)
at com.mongodb.operation.MixedBulkWriteOperation.executeCommand(MixedBulkWriteOperation.java:372)
at com.mongodb.operation.MixedBulkWriteOperation.executeBulkWriteBatch(MixedBulkWriteOperation.java:254)
at com.mongodb.operation.MixedBulkWriteOperation.access$700(MixedBulkWriteOperation.java:65)
at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:198)
at com.mongodb.operation.MixedBulkWriteOperation$1.call(MixedBulkWriteOperation.java:189)
at com.mongodb.operation.OperationHelper.withReleasableConnection(OperationHelper.java:433)
at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:189)
at com.mongodb.operation.MixedBulkWriteOperation.execute(MixedBulkWriteOperation.java:65)
at com.mongodb.Mongo$3.execute(Mongo.java:837)
at com.mongodb.MongoCollectionImpl.executeSingleWriteRequest(MongoCollectionImpl.java:1025)
at com.mongodb.MongoCollectionImpl.executeInsertOne(MongoCollectionImpl.java:513)
at com.mongodb.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:493)
at com.mongodb.MongoCollectionImpl.insertOne(MongoCollectionImpl.java:487)
at org.springframework.data.mongodb.core.MongoTemplate$8.doInCollection(MongoTemplate.java:1276)
at org.springframework.data.mongodb.core.MongoTemplate.execute(MongoTemplate.java:524)
at org.springframework.data.mongodb.core.MongoTemplate.insertDocument(MongoTemplate.java:1270)
at org.springframework.data.mongodb.core.MongoTemplate.doInsert(MongoTemplate.java:1051)
at org.springframework.data.mongodb.core.MongoTemplate.insert(MongoTemplate.java:988)
at org.springframework.data.mongodb.repository.support.SimpleMongoRepository.save(SimpleMongoRepository.java:80)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryComposition$RepositoryFragments.invoke(RepositoryComposition.java:377)
at org.springframework.data.repository.core.support.RepositoryComposition.invoke(RepositoryComposition.java:200)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$ImplementationMethodExecutionInterceptor.invoke(RepositoryFactorySupport.java:629)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:593)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:578)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:59)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212)
at com.sun.proxy.$Proxy181.save(Unknown Source)
at com.ifpen.truckrouting.web.rest.ifpen.TruckRoutingWs.computeForecastConsumption1(TruckRoutingWs.java:144)

Reproduce the error
@Configuration
@EnableMongoRepositories("com.ifpen.truckrouting.repository")
@Profile("!" + JHipsterConstants.SPRING_PROFILE_CLOUD)
@Import(value = MongoAutoConfiguration.class)
@EnableMongoAuditing(auditorAwareRef = "springSecurityAuditorAware")
public class DatabaseConfiguration {
...
    @Bean
    public MongoCustomConversions customConversions() {
        List<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(DateToZonedDateTimeConverter.INSTANCE);
        converters.add(ZonedDateTimeToDateConverter.INSTANCE);
        return new MongoCustomConversions(converters);
    }
...
}

import java.util.Date;

@Document(collection = "transaction")
public class Transaction {
    @Id
    private String id;
    private String companyName;
    private String username;
    private Date date;
}

public interface TransactionRepository extends MongoRepository<Transaction, String> {
}
##### **Related issues** ##### **Suggest a Fix** I bypass the problem by adding `@ReadingConverter` and `@WritingConverter` to the converters:
    @ReadingConverter
    enum DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {
...
}
    @WritingConverter
    enum ZonedDateTimeToDateConverter implements Converter<ZonedDateTime, Date> {
...
    }
##### **JHipster Version(s)** JHipster 5.1.0 (working fine with 4.x) ##### **JHipster configuration** ##### **JHipster Version(s)**
[email protected] C:\Users\lemaireo\git\truck-routing
`-- [email protected]

##### **JHipster configuration, a `.yo-rc.json` file generated in the root folder**
.yo-rc.json file
{
  "generator-jhipster": {
    "promptValues": {
      "packageName": "com.ifpen.truckrouting"
    },
    "jhipsterVersion": "4.10.2",
    "baseName": "TruckRouting",
    "packageName": "com.ifpen.truckrouting",
    "packageFolder": "com/ifpen/truckrouting",
    "serverPort": "8088",
    "authenticationType": "jwt",
    "clusteredHttpSession": false,
    "websocket": false,
    "databaseType": "mongodb",
    "devDatabaseType": "mongodb",
    "prodDatabaseType": "mongodb",
    "searchEngine": false,
    "messageBroker": false,
    "serviceDiscoveryType": "eureka",
    "buildTool": "gradle",
    "enableSocialSignIn": false,
    "enableSwaggerCodegen": false,
    "jwtSecretKey": "replaced-by-jhipster-info",
    "enableTranslation": false,
    "applicationType": "microservice",
    "testFrameworks": [],
    "jhiPrefix": "jhi",
    "clientPackageManager": "yarn",
    "skipClient": true,
    "skipUserManagement": true
  }
}

JDL for the Entity configuration(s) entityName.json files generated in the .jhipster directory

ls: no such file or directory: .jhipster/*.json


JDL entity definitions


Environment and Tools

java version "10.0.2" 2018-07-17
Java(TM) SE Runtime Environment 18.3 (build 10.0.2+13)
Java HotSpot(TM) 64-Bit Server VM 18.3 (build 10.0.2+13, mixed mode)

git version 2.9.0.windows.1

node: v8.11.3

npm: 5.6.0

yeoman: 2.0.0

yarn: 1.3.2

Docker version 17.07.0-ce, build 8784753

docker-compose version 1.15.0, build e12f3b94

All 8 comments

Same error for me. I solved it by reverting to spring-boot-gradle-plugin:2.0.1.RELEASE in "build.gradle":

buildscript {
     repositories {
        ...
     }
    dependencies {
        classpath("org.springframework.boot:spring-boot-gradle-plugin:2.0.1.RELEASE")
    }
}

NB: I am not a member of the jhipster team. I am just contributing by giving my own solution to the problem.

An alternative solution is to use the Java 8 APIs for Date and Time LocalDate, LocalTime, LocalDateTime, ZonedDateTime, etc.. The minimum requirement is JDK 8+ for JHipster 5.X, you should prefer the Java8 Date and Time classes. Java 8 Date/Time provides a set of APIs for easier development.

I can confirm that a field of type java.util.Date don't work when saving a document. For this issue, we should use @ReadingConverter and @WritingConverter annotations to determine if we should consider a converter as a reading or a writing converter.
See Mongo Converter Disambiguation

Closing as j.u.Date is not a type supported by Jhipster. Please use jdk8 j.t.Instant instead which is far better.

Then what's the use of these classes in the JHipster jar ?

import io.github.jhipster.domain.util.JSR310DateConverters.DateToZonedDateTimeConverter;
import io.github.jhipster.domain.util.JSR310DateConverters.ZonedDateTimeToDateConverter;

And that part of code generated by Jhipster for mongoDB in .../config/DatabaseConfiguration.java, which does not seem to be taken into account since the switch from Spring Boot 2.0.1 to Spring Boot 2.0.3, and which was solving the above exception ?

@Bean
public MongoCustomConversions customConversions() {
    log.info("Registering Mongo custom converters");
    List<Converter<?, ?>> converters = new ArrayList<>();
    converters.add(DateToZonedDateTimeConverter.INSTANCE);
    converters.add(ZonedDateTimeToDateConverter.INSTANCE);
    return new MongoCustomConversions(converters);
}

Maybe someone should suppress them, in order to clarify things ?

I understand this is closed but I have a project where I need to use Date (as it is dependent on other projects). How can I solve this issue by using @ReadingConverter and @WritingConverter? and how come MongoCustomConversions customConversions() is not going in effect?

@lemaireo Can you share your workaround using @ReadingConverter and @WritingConverter? Thanks

@jvence The problem seems to be fixed in the most recent releases of Jhipster.
At that time, when we faced the problem, we fixed it that way by modifying DatabaseConfiguration.java:

@Bean
    public MongoCustomConversions customConversions() {
        List<Converter<?, ?>> converters = new ArrayList<>();
        converters.add(DateToZonedDateTimeConverter.INSTANCE);
        converters.add(ZonedDateTimeToDateConverter.INSTANCE);
        return new MongoCustomConversions(converters);
    }

and adding the 2 following methods in this class:

@ReadingConverter
    enum DateToZonedDateTimeConverter implements Converter<Date, ZonedDateTime> {

        INSTANCE;

        @Override
        public ZonedDateTime convert(Date source) {
            return source == null ? null : ZonedDateTime.ofInstant(source.toInstant(), ZoneId.systemDefault());
        }
    }

    @WritingConverter
    enum ZonedDateTimeToDateConverter implements Converter<ZonedDateTime, Date> {

        INSTANCE;

        @Override
        public Date convert(ZonedDateTime source) {
            return source == null ? null : Date.from(source.toInstant());
        }
    }

@lemaireo Thank you for the code. We ended up implementing a similar solution. We did generate the app with the latest version of jhipster 6.1.0. Are you certain it's been fixed?

Was this page helpful?
0 / 5 - 0 ratings