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

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions