Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Router creation fails with Open API spec that has an example for a string of format date-time - vertx version 3.9.9. #2120

Closed
ddavoren opened this issue Feb 3, 2022 · 2 comments
Labels

Comments

@ddavoren
Copy link

ddavoren commented Feb 3, 2022

Version

3.9.9

Context

I hit the issue when we upgraded to vertx 3.9.9 - 3.9.9 itself pulls in jackson version 2.11.3.
I also needed to update jackson to version 2.12.x in order to resolve CVE issues.

In jackson 2.12.0 extra validation was added when creating serializers. If there is a known type that should have a serializer loaded via a registered module, it will fail during serialization.

FasterXML/jackson-databind#2683
FasterXML/jackson-databind@a39892c

When I load an Open API spec with a schema that contains a sting type, format date-time, and an example, the creation of the router will fail with an exception.

java.lang.IllegalArgumentException: Java 8 date/time type java.time.OffsetDateTime not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: io.swagger.v3.oas.models.media.ObjectSchema["properties"]->java.util.LinkedHashMap["date"]->io.swagger.v3.oas.models.media.DateTimeSchema["example"])
at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4314)
at com.fasterxml.jackson.databind.ObjectMapper.convertValue(ObjectMapper.java:4245)
at io.vertx.ext.web.api.contract.openapi3.impl.OpenApi3Utils.generateSanitizedJsonSchemaNode(OpenApi3Utils.java:242)
at io.vertx.ext.web.api.contract.openapi3.impl.OpenAPI3RequestValidationHandlerImpl.parseRequestBody(OpenAPI3RequestValidationHandlerImpl.java:481)
at io.vertx.ext.web.api.contract.openapi3.impl.OpenAPI3RequestValidationHandlerImpl.parseOperationSpec(OpenAPI3RequestValidationHandlerImpl.java:106)
at io.vertx.ext.web.api.contract.openapi3.impl.OpenAPI3RequestValidationHandlerImpl.(OpenAPI3RequestValidationHandlerImpl.java:89)
at io.vertx.ext.web.api.contract.openapi3.impl.OpenAPI3RouterFactoryImpl.getRouter(OpenAPI3RouterFactoryImpl.java:317)
at io.vertx.reactivex.ext.web.api.contract.openapi3.OpenAPI3RouterFactory.getRouter(OpenAPI3RouterFactory.java:162)
at io.reactivex.internal.operators.single.SingleMap$MapSingleObserver.onSuccess(SingleMap.java:57)
at io.reactivex.internal.operators.single.SingleDoOnError$DoOnError.onSuccess(SingleDoOnError.java:52)
at io.reactivex.internal.operators.single.SingleDoOnSuccess$DoOnSuccess.onSuccess(SingleDoOnSuccess.java:59)
at io.reactivex.internal.operators.single.SingleFlatMap$SingleFlatMapCallback$FlatMapSingleObserver.onSuccess(SingleFlatMap.java:111)
at io.vertx.reactivex.impl.AsyncResultSingle.lambda$subscribeActual$0(AsyncResultSingle.java:49)
at io.vertx.reactivex.ext.web.api.contract.openapi3.OpenAPI3RouterFactory$10.handle(OpenAPI3RouterFactory.java:341)
at io.vertx.reactivex.ext.web.api.contract.openapi3.OpenAPI3RouterFactory$10.handle(OpenAPI3RouterFactory.java:338)
at io.vertx.core.impl.ContextImpl.lambda$null$0(ContextImpl.java:327)
at io.vertx.core.impl.ContextImpl.executeTask(ContextImpl.java:366)
at io.vertx.core.impl.EventLoopContext.lambda$executeAsync$0(EventLoopContext.java:38)
at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:469)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.lang.Thread.run(Thread.java:748)
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Java 8 date/time type java.time.OffsetDateTime not supported by default: add Module "com.fasterxml.jackson.datatype:jackson-datatype-jsr310" to enable handling (through reference chain: io.swagger.v3.oas.models.media.ObjectSchema["properties"]->java.util.LinkedHashMap["date"]->io.swagger.v3.oas.models.media.DateTimeSchema["example"])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1276)
at com.fasterxml.jackson.databind.ser.impl.UnsupportedTypeSerializer.serialize(UnsupportedTypeSerializer.java:35)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeOptionalFields(MapSerializer.java:869)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serializeWithoutTypeInfo(MapSerializer.java:760)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:720)
at com.fasterxml.jackson.databind.ser.std.MapSerializer.serialize(MapSerializer.java:35)
at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:728)
at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:770)
at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:178)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)
at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:319)
at com.fasterxml.jackson.databind.ObjectMapper._convert(ObjectMapper.java:4292)
... 24 common frames omitted

A scaled down version of the API spec that causes the problem

openapi: '3.0.3'
info:
  title: Test
  version: '2.1'
  description: |
    test
tags:
  - name: Usage
    description: Operations for dealing with usage
  - name: UsageSpecification
    description: Operations for dealing with usage specifications
servers:
  - url: http://localhost:8080/test/v2
components:
  schemas:
    Usage:
      type: object
      properties:
        date:
          type: string
          format: date-time
          description: Date of usage
          example: '2013-04-19T16:42:23-04:00'
paths:
  /usage:
    post:
      operationId: getUsages
      summary: Retrieve a number of usages
      requestBody:
        description: |
          If `id` and `href` are not provided they will be generated by the
          system.
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Usage'
      responses:
        '200':
          description: Usages successfully retrieved (with more remaining)

The mapper that converts the swagger Schema to an ObjectNode is created here and cannot be modified by the application.

io.vertx.ext.web.api.contract.openapi3.impl.OpenApi3Utils
 
public static JsonNode generateSanitizedJsonSchemaNode(Schema s, OpenAPI oas) {
    ObjectNode node = ObjectMapperFactory.createJson().convertValue(s, ObjectNode.class);
    walkAndSolve(node, node, oas);
    return node;
  }

With jackson 2.11.x and before this works no problem as the checks for the type OffsetDateTime are not there and a bean serializer is used. The checks have been added to jackson 2.12.x which causes the failure.

If the application had access to modify this mapper it could register the JavaTimeModule with the mapper which would solve the problem.

I see in vertx 4.x that there are new API's for creating the router which I have tested and don't have this issue, however, we cannot move to vertx 4.x just yet.

Note: the workaround is to remove the examples from the spec.

Steps to reproduce

Run the attached App - vertx-date-time-failure.
With jackson at version 2.11.x in the POM file, the router can be created.
With jackson at version 2.12.x in the POM file, the router fails with the stack trace seen above.

project.zip

@ddavoren ddavoren added the bug label Feb 3, 2022
@pmlopes
Copy link
Member

pmlopes commented Feb 4, 2022

@ddavoren in 4.2.3 we do have jackson 2.13.1. Jackson is a widely used dependency across all vert.x modules, so its version must be aligned. The change required some internal changes to other modules, so backporting it not a trivial cherry pick operation.

You have 2 options here:

  1. force override of jackson on all your dependencies, in maven, you can exclude jackson from all vert.x dependencies and explicitly declare the dependencies you need.
  2. Try to upgrade from 3.9.9. to at least 4.2.3

Do you have the CVE number that affects 2.11.x? The only number I've found was:

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2020-28491

This is jackson-databind-cbor specific. Unless you're using vertx-auth-webauthn this issue should not affect you as the dependency for that component is only declared on that vert.x module.

@pk-work
Copy link
Contributor

pk-work commented Apr 26, 2024

Hi, there is a complete new rebuild of the OpenAPI Router [1], which hopefully solves the problem. Please check out if this works for you.

I am closing this issue now, as the ticket refers to a version of OpenAPI Router that is no longer supported. If the bug still occurs with the new OpenAPI router version, I would be very happy if you would open a new issue.

[1] https://vertx.io/docs/vertx-web-openapi-router/java/

@pk-work pk-work closed this as completed Apr 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Development

No branches or pull requests

3 participants