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)
@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**
{
"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
}
}
entityName.json files generated in the .jhipster directoryls: no such file or directory: .jhipster/*.json
JDL entity definitions
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
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?