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

Schema introspection of Map<String,Foo> #838

Closed
nschwalbe opened this issue Jul 11, 2024 · 7 comments
Closed

Schema introspection of Map<String,Foo> #838

nschwalbe opened this issue Jul 11, 2024 · 7 comments
Labels
bug Something isn't working staged for release

Comments

@nschwalbe
Copy link

nschwalbe commented Jul 11, 2024

Describe the bug
It seems that a map key and value is not introspected.
In the UI schema is object and not Foo and no examples are shown.

Dependencies and versions used
springwolf amqp 1.4.0

Code example

@Schema(description = "Some description")
class Foo {
   @Schema(example = "foo")
   private String name;
   @Schema(example = "bar")
   private String title;
}

class MyEvent {
  @Schema(description = "a map of ...")
  private Map<String, Foo> map;
}

Renders to Example Message:

{
   "map": { }
}

Am I missing something? I tried Schema with additionalProperties but that didn't change anything.
List<Foo> works, so I expected that Map<String,Foo> should also work.

@nschwalbe nschwalbe added the bug Something isn't working label Jul 11, 2024
@timonback
Copy link
Member

Hi @nschwalbe, thank you for the report.

We indeed did not cover maps in the current implementation, but this will be added in #839

Copy link

The change is staged for release and will be part of the next release.

If you want to try and verify it in your application today,
use the latest 1.X.0-SNAPSHOT build as described in our README.md > Testing SNAPSHOT version

Thank you for the report/contribution!

@nschwalbe
Copy link
Author

nschwalbe commented Jul 15, 2024

Hi @timonback, thanks for your quick response!
I tested it with the snapshot version and it works for the simple case Map<String,Foo> but not for collections e.g. Map<String,Set<Foo>>

I got following exception:

io.github.springwolf.core.asyncapi.components.examples.walkers.SchemaWalker$ExampleGeneratingException: Array schema does not have a name: class ArraySchema {
    class Schema {
        type: array
        format: null
        $ref: null
        description: A map of projectIds and a list of users which were added to the project
        title: null
        multipleOf: null
        maximum: null
        exclusiveMaximum: null
        minimum: null
        exclusiveMinimum: null
        maxLength: null
        minLength: null
        pattern: null
        maxItems: null
        minItems: null
        uniqueItems: true
        maxProperties: null
        minProperties: null
        required: null
        not: null
        properties: null
        additionalProperties: null
        nullable: null
        readOnly: null
        writeOnly: null
        example: null
        externalDocs: null
        deprecated: null
        discriminator: null
        xml: null
    }
}
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.lambda$buildArrayExample$4(DefaultSchemaWalker.java:173) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at java.base/java.util.Optional.orElseThrow(Optional.java:403) ~[na:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.lambda$buildArrayExample$5(DefaultSchemaWalker.java:172) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at java.base/java.util.Optional.map(Optional.java:260) ~[na:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.buildArrayExample(DefaultSchemaWalker.java:171) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.buildExample(DefaultSchemaWalker.java:87) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.lambda$buildPropertyExampleListFromSchema$7(DefaultSchemaWalker.java:286) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
	at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
	at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1939) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) ~[na:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.buildPropertyExampleListFromSchema(DefaultSchemaWalker.java:294) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.buildMapExample(DefaultSchemaWalker.java:249) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.buildFromObjectSchema(DefaultSchemaWalker.java:234) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.buildExample(DefaultSchemaWalker.java:91) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.lambda$buildPropertyExampleListFromSchema$7(DefaultSchemaWalker.java:286) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
	at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
	at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1939) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) ~[na:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.buildPropertyExampleListFromSchema(DefaultSchemaWalker.java:294) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.buildFromObjectSchemaWithProperties(DefaultSchemaWalker.java:259) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.buildFromObjectSchema(DefaultSchemaWalker.java:226) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.buildExample(DefaultSchemaWalker.java:91) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.examples.walkers.DefaultSchemaWalker.fromSchema(DefaultSchemaWalker.java:64) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.postprocessors.ExampleGeneratorPostProcessor.process(ExampleGeneratorPostProcessor.java:26) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.schemas.SwaggerSchemaService.postProcessSchema(SwaggerSchemaService.java:210) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.schemas.SwaggerSchemaService.extractSchema(SwaggerSchemaService.java:89) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.components.DefaultComponentsService.registerSchema(DefaultComponentsService.java:51) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.scanners.common.payload.internal.PayloadService.buildSchema(PayloadService.java:35) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadAsyncOperationService.lambda$extractSchema$0(PayloadAsyncOperationService.java:25) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at java.base/java.util.Optional.map(Optional.java:260) ~[na:na]
	at io.github.springwolf.core.asyncapi.scanners.common.payload.PayloadAsyncOperationService.extractSchema(PayloadAsyncOperationService.java:25) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.scanners.common.AsyncAnnotationScanner.buildMessage(AsyncAnnotationScanner.java:94) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.scanners.common.AsyncAnnotationScanner.buildOperation(AsyncAnnotationScanner.java:82) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.scanners.operations.annotations.AsyncAnnotationOperationsScanner.buildOperation(AsyncAnnotationOperationsScanner.java:68) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[na:na]
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:184) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197) ~[na:na]
	at java.base/java.util.Iterator.forEachRemaining(Iterator.java:133) ~[na:na]
	at java.base/java.util.Spliterators$IteratorSpliterator.forEachRemaining(Spliterators.java:1939) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[na:na]
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline$15$1.accept(ReferencePipeline.java:541) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179) ~[na:na]
	at java.base/java.util.Spliterators$ArraySpliterator.forEachRemaining(Spliterators.java:1024) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.ForEachOps$ForEachOp.evaluateSequential(ForEachOps.java:151) ~[na:na]
	at java.base/java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateSequential(ForEachOps.java:174) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:596) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276) ~[na:na]
	at java.base/java.util.HashMap$KeySpliterator.forEachRemaining(HashMap.java:1715) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:575) ~[na:na]
	at java.base/java.util.stream.AbstractPipeline.evaluateToArrayNode(AbstractPipeline.java:260) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:616) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toArray(ReferencePipeline.java:622) ~[na:na]
	at java.base/java.util.stream.ReferencePipeline.toList(ReferencePipeline.java:627) ~[na:na]
	at io.github.springwolf.core.asyncapi.scanners.operations.annotations.AsyncAnnotationOperationsScanner.scan(AsyncAnnotationOperationsScanner.java:52) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.operations.DefaultOperationsService.findOperations(DefaultOperationsService.java:34) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.DefaultAsyncApiService.initAsyncAPI(DefaultAsyncApiService.java:71) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.asyncapi.DefaultAsyncApiService.getAsyncAPI(DefaultAsyncApiService.java:42) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.SpringwolfInitApplicationListener.onApplicationEvent(SpringwolfInitApplicationListener.java:31) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at io.github.springwolf.core.SpringwolfInitApplicationListener.onApplicationEvent(SpringwolfInitApplicationListener.java:17) ~[springwolf-core-1.5.0-20240713.181812-9.jar:na]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.doInvokeListener(SimpleApplicationEventMulticaster.java:185) ~[spring-context-6.1.5.jar:6.1.5]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.invokeListener(SimpleApplicationEventMulticaster.java:178) ~[spring-context-6.1.5.jar:6.1.5]
	at org.springframework.context.event.SimpleApplicationEventMulticaster.multicastEvent(SimpleApplicationEventMulticaster.java:156) ~[spring-context-6.1.5.jar:6.1.5]
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:451) ~[spring-context-6.1.5.jar:6.1.5]
	at org.springframework.context.support.AbstractApplicationContext.publishEvent(AbstractApplicationContext.java:384) ~[spring-context-6.1.5.jar:6.1.5]
	at org.springframework.boot.context.event.EventPublishingRunListener.ready(EventPublishingRunListener.java:109) ~[spring-boot-3.2.4.jar:3.2.4]
	at org.springframework.boot.SpringApplicationRunListeners.lambda$ready$6(SpringApplicationRunListeners.java:80) ~[spring-boot-3.2.4.jar:3.2.4]
	at java.base/java.lang.Iterable.forEach(Iterable.java:75) ~[na:na]
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:118) ~[spring-boot-3.2.4.jar:3.2.4]
	at org.springframework.boot.SpringApplicationRunListeners.doWithListeners(SpringApplicationRunListeners.java:112) ~[spring-boot-3.2.4.jar:3.2.4]
	at org.springframework.boot.SpringApplicationRunListeners.ready(SpringApplicationRunListeners.java:80) ~[spring-boot-3.2.4.jar:3.2.4]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:348) ~[spring-boot-3.2.4.jar:3.2.4]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1354) ~[spring-boot-3.2.4.jar:3.2.4]
	at org.springframework.boot.SpringApplication.run(SpringApplication.java:1343) ~[spring-boot-3.2.4.jar:3.2.4]
	at eu.aconium.docs.amqp.AmqpDocsApplication.main(AmqpDocsApplication.java:11) ~[classes/:na]

@timonback
Copy link
Member

Thanks for the update @nschwalbe

We tend to err on the side of what is possible and tend to be more restrictive. Since you provided this example, we can add it to our test suite and fill the gaps of possible combinations of payloads :)

I created #841, but will have @sam0r040 to have a look at it to confirm that the original restriction for xml generation is still required.

@timonback
Copy link
Member

timonback commented Jul 18, 2024

Hi @nschwalbe
follow up has been merged as well.

Can you verify the new Snapshot that will be available in the next 10 minutes?

@nschwalbe
Copy link
Author

@timonback Yes, it works! 👍

Copy link

The change is available in the latest release. 🎉

Thank you for the report/contribution and making Springwolf better!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working staged for release
Projects
None yet
Development

No branches or pull requests

2 participants