ebowman / api-first-hand

API-First bootstrapping tool for building RESTful web services from a Swagger/OpenAPI spec
MIT License
142 stars 22 forks source link

Help with int64 & date-time #75

Open jona7o opened 7 years ago

jona7o commented 7 years ago

Hi, i tried to implement the api in a project, but i have some problems with the data types:

When i send a number i get (integer & format: int64 in swagger):

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[ClassCastException: java.lang.Integer cannot be cast to java.lang.Long]]

and when i send a date-time object from swagger i get:

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[JsonMappingException: Can not instantiate value of type [simple type, class java.time.ZonedDateTime] from String value ('2017-03-25T11:58:04.522Z'); no single-String constructor/factory method at [Source: [B@4dc50d3; line: 17, column: 14] (through reference chain: Contact["created"])]]

Do you have an idea what's the problem?

Greetings Tobias

slavaschmidt commented 7 years ago

Hey @jona7o, it would be very helpful if you could provide the full specification which is failing or if not possible at least relevant parts of it and full stacktraces.

jona7o commented 7 years ago

Hi, here are the relevant parts of the swagger file (i choose a smaller entity - but the error is the same):

definition: Note: type: object properties: id: type: integer format: int64 owningPersonId: type: integer format: int64 owningCompanyId: type: integer format: int64 created: type: string format: date-time modified: type: string format: date-time responsible: type: string text: type: string popup: type: boolean read: type: boolean completed: type: boolean and path: `
/notes: post: tags:

the "generated" code:

val addNote = addNoteAction { (noteToCreate: Note) => // ----- Start of unmanaged code area for action ManagementYaml.addNote Services.noteService.insert(NoteRowConverter > noteToCreate) // ----- End of unmanaged code area for action ManagementYaml.addNote }

via swagger ui i send a post with sample data: { "owningPersonId": 12, "owningCompanyId": 13, "created": "2017-03-26T12:16:38.622Z", "modified": "2017-03-26T12:16:38.622Z", "responsible": "string test", "text": "hope you can help me - great plugin :)", "popup": true, "read": true, "completed": true }

and the error: ` [error] - application -

! @73f10a4n7 - Internal server error, for (POST) [/notes] ->

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[JsonMappingException: Can not instantiate value of type [simple type, class java.time.ZonedDateTime] from String value ('2017-03-26T12:16:38.622Z'); no single-String constructor/factory method at [Source: [B@1be1e445; line: 4, column: 14] (through reference chain: management.yaml.Note["created"])]] at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:293) at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:220) at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:100) at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:99) at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:346) at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:345) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70) at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40) at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248) at scala.concurrent.Promise$class.complete(Promise.scala:55) at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153) at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:251) at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:251) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55) at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:91) at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply(BatchingExecutor.scala:91) at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply(BatchingExecutor.scala:91) at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72) at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:90) at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:39) at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:415) at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) Caused by: com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.ZonedDateTime] from String value ('2017-03-26T12:16:38.622Z'); no single-String constructor/factory method at [Source: [B@1be1e445; line: 4, column: 14] (through reference chain: management.yaml.Note["created"]) at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:256) at com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:993) at com.fasterxml.jackson.databind.deser.ValueInstantiator._createFromStringFallbacks(ValueInstantiator.java:316) at com.fasterxml.jackson.databind.deser.std.StdValueInstantiator.createFromString(StdValueInstantiator.java:288) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromString(BeanDeserializerBase.java:1200) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:144) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:135) at com.fasterxml.jackson.module.scala.deser.OptionDeserializer.deserialize(OptionDeserializerModule.scala:60) at com.fasterxml.jackson.module.scala.deser.OptionDeserializer.deserialize(OptionDeserializerModule.scala:11) at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:490) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeWithErrorWrapping(BeanDeserializer.java:465) at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeUsingPropertyBased(BeanDeserializer.java:380) at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1123) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:298) at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:133) at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3807) at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2890) at de.zalando.play.controllers.PlayBodyParsing$$anonfun$4.apply(PlayBodyParsing.scala:98) at de.zalando.play.controllers.PlayBodyParsing$$anonfun$4.apply(PlayBodyParsing.scala:94) at de.zalando.play.controllers.PlayBodyParsing$.de$zalando$play$controllers$PlayBodyParsing$$parserCore(PlayBodyParsing.scala:103) at de.zalando.play.controllers.PlayBodyParsing$$anonfun$anyParser$1.apply(PlayBodyParsing.scala:85) at de.zalando.play.controllers.PlayBodyParsing$$anonfun$anyParser$1.apply(PlayBodyParsing.scala:84) at scala.util.Either$RightProjection.map(Either.scala:535) at play.api.mvc.BodyParser$$anon$4$$anonfun$apply$8.apply(Action.scala:162) at play.api.mvc.BodyParser$$anon$4$$anonfun$apply$8.apply(Action.scala:162) at scala.util.Success$$anonfun$map$1.apply(Try.scala:237) at scala.util.Try$.apply(Try.scala:192) at scala.util.Success.map(Try.scala:237) at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:237) at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:237) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) at play.api.libs.iteratee.Execution$trampoline$.executeScheduled(Execution.scala:109) at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:71) at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40) at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248) at scala.concurrent.Promise$class.complete(Promise.scala:55) at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153) at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:237) at scala.concurrent.Future$$anonfun$map$1.apply(Future.scala:237) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55) at akka.dispatch.BatchingExecutor$Batch.run(BatchingExecutor.scala:73) at akka.dispatch.ExecutionContexts$sameThreadExecutionContext$.unbatchedExecute(Future.scala:76) at akka.dispatch.BatchingExecutor$class.execute(BatchingExecutor.scala:120) at akka.dispatch.ExecutionContexts$sameThreadExecutionContext$.execute(Future.scala:75) at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40) at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248) at scala.concurrent.Promise$class.trySuccess(Promise.scala:94) at scala.concurrent.impl.Promise$DefaultPromise.trySuccess(Promise.scala:153) at akka.stream.impl.HeadOptionStage$$anon$3.onPush(Sinks.scala:233) at akka.stream.impl.fusing.GraphInterpreter.processPush(GraphInterpreter.scala:747) at akka.stream.impl.fusing.GraphInterpreter.processEvent(GraphInterpreter.scala:736) at akka.stream.impl.fusing.GraphInterpreter.execute(GraphInterpreter.scala:616) at akka.stream.impl.fusing.GraphInterpreterShell.runBatch(ActorGraphInterpreter.scala:471) at akka.stream.impl.fusing.GraphInterpreterShell.receive(ActorGraphInterpreter.scala:433) at akka.stream.impl.fusing.ActorGraphInterpreter.akka$stream$impl$fusing$ActorGraphInterpreter$$processEvent(ActorGraphInterpreter.scala:603) at akka.stream.impl.fusing.ActorGraphInterpreter$$anonfun$receive$1.applyOrElse(ActorGraphInterpreter.scala:618) at akka.actor.Actor$class.aroundReceive(Actor.scala:484) at akka.stream.impl.fusing.ActorGraphInterpreter.aroundReceive(ActorGraphInterpreter.scala:529) at akka.actor.ActorCell.receiveMessage(ActorCell.scala:526) at akka.actor.ActorCell.invoke(ActorCell.scala:495) at akka.dispatch.Mailbox.processMailbox(Mailbox.scala:257) at akka.dispatch.Mailbox.run(Mailbox.scala:224) at akka.dispatch.Mailbox.exec(Mailbox.scala:234) ... 4 common frames omitted `

When i delete the date-time props from the post, i get the second error i have mentioned above:

{ "owningPersonId": 12, "owningCompanyId": 13, "responsible": "string test", "text": "hope you can help me - great plugin :)", "popup": true, "read": true, "completed": true }

error:

` [error] - application -

! @73f10fe61 - Internal server error, for (POST) [/notes] ->

play.api.http.HttpErrorHandlerExceptions$$anon$1: Execution exception[[ClassCastException: java.lang.Integer cannot be cast to java.lang.Long]] at play.api.http.HttpErrorHandlerExceptions$.throwableToUsefulException(HttpErrorHandler.scala:293) at play.api.http.DefaultHttpErrorHandler.onServerError(HttpErrorHandler.scala:220) at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:100) at play.core.server.netty.PlayRequestHandler$$anonfun$2$$anonfun$apply$1.applyOrElse(PlayRequestHandler.scala:99) at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:346) at scala.concurrent.Future$$anonfun$recoverWith$1.apply(Future.scala:345) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) at play.api.libs.iteratee.Execution$trampoline$.execute(Execution.scala:70) at scala.concurrent.impl.CallbackRunnable.executeWithValue(Promise.scala:40) at scala.concurrent.impl.Promise$DefaultPromise.tryComplete(Promise.scala:248) at scala.concurrent.Promise$class.complete(Promise.scala:55) at scala.concurrent.impl.Promise$DefaultPromise.complete(Promise.scala:153) at scala.concurrent.Promise$class.failure(Promise.scala:104) at scala.concurrent.impl.Promise$DefaultPromise.failure(Promise.scala:153) at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:257) at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:251) at scala.concurrent.impl.CallbackRunnable.run(Promise.scala:32) at akka.dispatch.BatchingExecutor$AbstractBatch.processBatch(BatchingExecutor.scala:55) at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply$mcV$sp(BatchingExecutor.scala:91) at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply(BatchingExecutor.scala:91) at akka.dispatch.BatchingExecutor$BlockableBatch$$anonfun$run$1.apply(BatchingExecutor.scala:91) at scala.concurrent.BlockContext$.withBlockContext(BlockContext.scala:72) at akka.dispatch.BatchingExecutor$BlockableBatch.run(BatchingExecutor.scala:90) at akka.dispatch.TaskInvocation.run(AbstractDispatcher.scala:39) at akka.dispatch.ForkJoinExecutorConfigurator$AkkaForkJoinTask.exec(AbstractDispatcher.scala:415) at scala.concurrent.forkjoin.ForkJoinTask.doExec(ForkJoinTask.java:260) at scala.concurrent.forkjoin.ForkJoinPool$WorkQueue.runTask(ForkJoinPool.java:1339) at scala.concurrent.forkjoin.ForkJoinPool.runWorker(ForkJoinPool.java:1979) at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:107) Caused by: java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long at scala.runtime.BoxesRunTime.unboxToLong(BoxesRunTime.java:105) at management.yaml.NoteOwningCompanyIdValidator$$anonfun$1.apply(management.yaml.scala:524) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234) at scala.collection.TraversableLike$$anonfun$map$1.apply(TraversableLike.scala:234) at scala.collection.immutable.List.foreach(List.scala:381) at scala.collection.TraversableLike$class.map(TraversableLike.scala:234) at scala.collection.immutable.List.map(List.scala:285) at management.yaml.NoteOwningCompanyIdValidator.(management.yaml.scala:524) at management.yaml.NoteValidator.(management.yaml.scala:442) at management.yaml.NotesPostValidator.(management.yaml.scala:628) at management.yaml.ManagementYamlBase$$anonfun$addNoteAction$1$$anonfun$apply$42$$anonfun$apply$43.apply(management.yaml.scala:296) at management.yaml.ManagementYamlBase$$anonfun$addNoteAction$1$$anonfun$apply$42$$anonfun$apply$43.apply(management.yaml.scala:290) at scala.Option.map(Option.scala:146) at management.yaml.ManagementYamlBase$$anonfun$addNoteAction$1$$anonfun$apply$42.apply(management.yaml.scala:290) at management.yaml.ManagementYamlBase$$anonfun$addNoteAction$1$$anonfun$apply$42.apply(management.yaml.scala:287) at play.api.mvc.Action$.invokeBlock(Action.scala:498) at play.api.mvc.Action$.invokeBlock(Action.scala:495) at play.api.mvc.ActionBuilder$$anon$2.apply(Action.scala:458) at play.api.mvc.Action$$anonfun$apply$2$$anonfun$apply$5$$anonfun$apply$6.apply(Action.scala:112) at play.api.mvc.Action$$anonfun$apply$2$$anonfun$apply$5$$anonfun$apply$6.apply(Action.scala:112) at play.utils.Threads$.withContextClassLoader(Threads.scala:21) at play.api.mvc.Action$$anonfun$apply$2$$anonfun$apply$5.apply(Action.scala:111) at play.api.mvc.Action$$anonfun$apply$2$$anonfun$apply$5.apply(Action.scala:110) at scala.Option.map(Option.scala:146) at play.api.mvc.Action$$anonfun$apply$2.apply(Action.scala:110) at play.api.mvc.Action$$anonfun$apply$2.apply(Action.scala:103) at scala.concurrent.Future$$anonfun$flatMap$1.apply(Future.scala:253) ... 14 common frames omitted

`

slavaschmidt commented 7 years ago

The first issue is related to the #56, the fix should be a low hanging fruit.

The second issue unfortunately is more involving and related to the way play validations is used.

s12v commented 7 years ago

@jona7o, we had a similar issue with int64, and it seems to be fixed in 0.2.0

slavaschmidt commented 7 years ago

@s12v, I guess we starting to have more and more issues like when generated code compiles and runs but fails at the runtime. I'll create a test environment for such issues so that we can be sure we are won't introduce regression in future versions.