Skip to content

[Bug]: [swagger-core-jakarta] ModelConverterContextImpl does not properly cache AnnotatedType #4965

@anteperic

Description

@anteperic

Description of the problem/issue

Based on analysis, swagger-core-jakarta does not properly cache (store) already processed AnnotatedTypes.

For instance, Java String type is always recalculated as it is not found in:
private final Set<AnnotatedType> processedTypes;

Root cause is probably faulty equals() or hashcode() implementation in the `AnnotatedType.

Affected Version

Discovered in 2.2.27

Steps to Reproduce

A simple code modification of the io.swagger.v3.core.converter.ModelConverterContextImpl can showcase that the same types are "recalculated" See "CONVERTERS" part.

    @Override
    public Schema resolve(AnnotatedType type) {

        AnnotatedType aType = ReferenceTypeUtils.unwrapReference(type);
        if (aType != null) {
            return resolve(aType);
        }

        if (processedTypes.contains(type)) {
            return modelByType.get(type);
        } else {
            processedTypes.add(type);
        }
        Iterator<ModelConverter> converters = this.getConverters();
        Schema resolved = null;
        if (converters.hasNext()) {
            var start = System.currentTimeMillis();
            ModelConverter converter = converters.next();
            LOGGER.info("[CONVERTERS] {}", type.getType().getTypeName());
            resolved = converter.resolve(type, this, converters);
            var duration = System.currentTimeMillis() - start;
            LOGGER.info("[CONVERTERS] {} took {}ms", type.getType().getTypeName(), duration);
        }

        if (resolved != null) {
            modelByType.put(type, resolved);

            Schema resolvedImpl = resolved;
            if (resolvedImpl.getName() != null) {
                modelByName.put(resolvedImpl.getName(), resolved);
            }
        } else {
            processedTypes.remove(type);
        }

        return resolved;
    }

Expected Behavior & Actual Behavior

Swagger Schema for repeating AnnotatedTypes should not be resolved by converter. Instead, value should be fetched from existing modelByType.

Logs / Stack Traces

This is an example from our machine. Note: some specifics are omitted.

2025-09-02T17:43:21.124 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String]
2025-09-02T17:43:21.124 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String] took 0ms
2025-09-02T17:43:21.124 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String]
2025-09-02T17:43:21.124 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String] took 0ms
2025-09-02T17:43:21.124 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.util.Date]
2025-09-02T17:43:21.124 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.util.Date] took 0ms
2025-09-02T17:43:21.125 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.Long]
2025-09-02T17:43:21.125 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.Long] took 0ms
2025-09-02T17:43:21.125 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class int]
2025-09-02T17:43:21.125 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class int] took 0ms
2025-09-02T17:43:21.125 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] java.lang.String
2025-09-02T17:43:21.125 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] java.lang.String took 0ms
2025-09-02T17:43:21.127 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String]
2025-09-02T17:43:21.127 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String] took 0ms
2025-09-02T17:43:21.127 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String]
2025-09-02T17:43:21.127 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String] took 0ms
2025-09-02T17:43:21.129 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String]
2025-09-02T17:43:21.129 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String] took 0ms
2025-09-02T17:43:21.130 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] java.lang.String
2025-09-02T17:43:21.130 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] java.lang.String took 0ms
2025-09-02T17:43:21.133 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String]
2025-09-02T17:43:21.133 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String] took 0ms
2025-09-02T17:43:21.133 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String]
2025-09-02T17:43:21.133 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String] took 0ms
2025-09-02T17:43:21.133 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String]
2025-09-02T17:43:21.133 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String] took 0ms
2025-09-02T17:43:21.134 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String]
2025-09-02T17:43:21.134 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String] took 1ms
2025-09-02T17:43:21.134 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String]
2025-09-02T17:43:21.134 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.lang.String] took 0ms
2025-09-02T17:43:21.134 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.util.Date]
2025-09-02T17:43:21.134 INFO qtp1695504428-376 io.swagger.v3.core.converter.ModelConverterContextImpl - [CONVERTERS] [simple type, class java.util.Date] took 0ms

Additional Context

Checklist

  • I have searched the existing issues and this is not a duplicate.
  • I have provided sufficient information for maintainers to reproduce the issue.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions