1

I have the following repository:

public interface MyRepository extends MongoRepository<MyDocument, String>, QueryDslPredicateExecutor<MyDocument>{ ...

I wrote a class which provides some predicates for me, one is to search between a time frame of two ZonedDateTimes

public static Predicate hasTimeBeetween(final ZonedDateTime from, final ZonedDateTime to) {
    return QMyDocument.myDocument.remoteTime.between(from, to);
}

If I call the findAll method without that predicate everything is fine if I add the predicate as follows

    ZonedDateTime now = ZonedDateTime.now();
    MyDocument cNow = this.createInDatabase(this.createDocumentInDatabase(now));

    Iterable<CrudNut> findAll = this.repository.findAll(CrudNutPredicates.hasTimeBeetween(now.minusDays(1), now.plusDays(1)));

I run in the following exception:

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.ProvidersCodecRegistry.get(ProvidersCodecRegistry.java:37)
at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:210)
at com.mongodb.DBObjectCodec.encodeMap(DBObjectCodec.java:220)
at com.mongodb.DBObjectCodec.writeValue(DBObjectCodec.java:196)
at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:128)
at com.mongodb.DBObjectCodec.encode(DBObjectCodec.java:61)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:63)
at org.bson.codecs.BsonDocumentWrapperCodec.encode(BsonDocumentWrapperCodec.java:29)
at org.bson.codecs.EncoderContext.encodeWithChildContext(EncoderContext.java:91)
at org.bson.codecs.BsonDocumentCodec.writeValue(BsonDocumentCodec.java:133)
at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:112)
at org.bson.codecs.BsonDocumentCodec.encode(BsonDocumentCodec.java:40)
at com.mongodb.connection.RequestMessage.addDocument(RequestMessage.java:253)
at com.mongodb.connection.RequestMessage.addDocument(RequestMessage.java:205)
at com.mongodb.connection.CommandMessage.encodeMessageBodyWithMetadata(CommandMessage.java:75)
at com.mongodb.connection.RequestMessage.encodeWithMetadata(RequestMessage.java:160)
at com.mongodb.connection.CommandProtocol.sendMessage(CommandProtocol.java:192)
at com.mongodb.connection.CommandProtocol.execute(CommandProtocol.java:111)
at com.mongodb.connection.DefaultServer$DefaultServerProtocolExecutor.execute(DefaultServer.java:159)
at com.mongodb.connection.DefaultServerConnection.executeProtocol(DefaultServerConnection.java:286)
at com.mongodb.connection.DefaultServerConnection.command(DefaultServerConnection.java:173)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:215)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:206)
at com.mongodb.operation.CommandOperationHelper.executeWrappedCommandProtocol(CommandOperationHelper.java:112)
at com.mongodb.operation.CountOperation$1.call(CountOperation.java:210)
at com.mongodb.operation.CountOperation$1.call(CountOperation.java:206)
at com.mongodb.operation.OperationHelper.withConnectionSource(OperationHelper.java:230)
at com.mongodb.operation.OperationHelper.withConnection(OperationHelper.java:203)
at com.mongodb.operation.CountOperation.execute(CountOperation.java:206)
at com.mongodb.operation.CountOperation.execute(CountOperation.java:53)
at com.mongodb.Mongo.execute(Mongo.java:772)
at com.mongodb.Mongo$2.execute(Mongo.java:759)
at com.mongodb.DBCollection.getCount(DBCollection.java:962)
at com.mongodb.DBCollection.getCount(DBCollection.java:937)
at com.mongodb.DBCollection.getCount(DBCollection.java:931)
at com.mongodb.DBCollection.getCount(DBCollection.java:914)
at com.mongodb.DBCollection.getCount(DBCollection.java:885)
at com.mongodb.DBCollection.count(DBCollection.java:824)
at com.querydsl.mongodb.AbstractMongodbQuery.fetchCount(AbstractMongodbQuery.java:391)
at com.querydsl.mongodb.AbstractMongodbQuery.fetchResults(AbstractMongodbQuery.java:376)
at org.springframework.data.mongodb.repository.support.QueryDslMongoRepository.findAll(QueryDslMongoRepository.java:104)
at org.springframework.data.mongodb.repository.support.QueryDslMongoRepository.findAll(QueryDslMongoRepository.java:50)
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.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:503)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:488)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:460)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy69.findAll(Unknown Source)
at com.favendo.squirrel.persistence.CrudNutRepositoryTests.readTimeFrame(CrudNutRepositoryTests.java:83)
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.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.springframework.test.context.junit4.statements.RunBeforeTestMethodCallbacks.evaluate(RunBeforeTestMethodCallbacks.java:75)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.springframework.test.context.junit4.statements.RunAfterTestMethodCallbacks.evaluate(RunAfterTestMethodCallbacks.java:86)
at org.springframework.test.context.junit4.statements.SpringRepeat.evaluate(SpringRepeat.java:84)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:252)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.runChild(SpringJUnit4ClassRunner.java:94)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.springframework.test.context.junit4.statements.RunBeforeTestClassCallbacks.evaluate(RunBeforeTestClassCallbacks.java:61)
at org.springframework.test.context.junit4.statements.RunAfterTestClassCallbacks.evaluate(RunAfterTestClassCallbacks.java:70)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.springframework.test.context.junit4.SpringJUnit4ClassRunner.run(SpringJUnit4ClassRunner.java:191)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)

I understand the exception and that a codec is missing but do not know what to do to solve this. Can somebody help me?

Bilesh Ganguly
  • 3,792
  • 3
  • 36
  • 58
pDer666
  • 707
  • 5
  • 22
  • I think you need to add Java 8 Date/Time (JSR-310) types support to Spring Data MongoDB. – Hrabosch Jul 22 '16 at 09:11
  • ok thank you I will try this – pDer666 Jul 22 '16 at 09:13
  • Ok, let me know if it will work, I will create answer from comment. I think you can grab something from these answers: http://stackoverflow.com/questions/22972679/spring-data-mongodb-with-java-8-localdate-mappingexception here you can find inspiration. I dont think that MongoDB support new Java 8 types :/ – Hrabosch Jul 22 '16 at 09:15
  • Here you can find how to create your own converters (by implementing `Converter` interface : http://stackoverflow.com/questions/23972002/java-8-date-time-jsr-310-types-mapping-with-spring-data-mongodb – Hrabosch Jul 22 '16 at 09:19
  • I already added these converters before. Without it I wasn't even able to post my documents and got a ModelMappingException – pDer666 Jul 22 '16 at 09:19
  • And do you have Serializer for ZonedDataTime? Somethink like: `public class ZonedDateTimeSerializer extends InstantSerializerBase { public ZonedDateTimeSerializer() { super(ZonedDateTime.class, zdt -> zdt.toInstant().toEpochMilli()); } }` – Hrabosch Jul 22 '16 at 09:22
  • And here is similiar problem and solution http://stackoverflow.com/questions/30569228/mongodb-bson-codec-not-being-used-while-encoding-object – Hrabosch Jul 22 '16 at 09:23
  • @pDer666 You should not use `ZonedDateTime` at database level as `Zoned…` types handle more presentation-level aspects. Rather store UTC (or any other fixed timezone) and apply zone details outside the data store layer. The non-existing mapper is by design. – mp911de Jul 26 '16 at 13:36

1 Answers1

1

I had a similar issue in my application.

Instead of using the ComparableExpression between, I used the Temporal expressions after and before linked by a logical AND.

Try the following (you might want to add some null checks):

    public static Predicate hasTimeBeetween(final ZonedDateTime from, final ZonedDateTime to) {

        BooleanBuilder builder = new BooleanBuilder();
        builder.and(QMyDocument.myDocument.remoteTime.after(from));
        builder.and(QMyDocument.myDocument.remoteTime.before(to));

        return builder.getValue();
    }
ab1510
  • 26
  • 2
  • This workaround works but I do not really understand why. Thank you. @Hrabosch I also will try your solution mentioned in your comments and hopefully this will help me to get why I got that exception. Thank you too – pDer666 Jul 22 '16 at 09:36