swagger-core icon indicating copy to clipboard operation
swagger-core copied to clipboard

java.lang.ClassCastException: class io.swagger.v3.oas.models.media.JsonSchema cannot be cast to class io.swagger.v3.oas.models.media.ComposedSchema

Open davsclaus opened this issue 6 months ago • 8 comments

We have an issue in Apache Camel when upgrading swagger-core from 2.2.23 to 2.2.32 in relation to parsing as open-api v3.1 models. The same test work with parsing as open-api v3.0.

The exception we see from tests have a stacktrace leading into a ClassCastException.

java.lang.ClassCastException: class io.swagger.v3.oas.models.media.JsonSchema cannot be cast to class io.swagger.v3.oas.models.media.ComposedSchema (io.swagger.v3.oas.models.media.JsonSchema and io.swagger.v3.oas.models.media.ComposedSchema are in unnamed module of loader 'app')

	at io.swagger.v3.core.jackson.ModelResolver.resolve(ModelResolver.java:1046)
	at org.apache.camel.openapi.RestModelConverters$ClassNameExtensionModelResolver.resolve(RestModelConverters.java:117)
	at io.swagger.v3.core.converter.ModelConverterContextImpl.resolve(ModelConverterContextImpl.java:97)
	at io.swagger.v3.core.jackson.ModelResolver.resolve(ModelResolver.java:824)
	at org.apache.camel.openapi.RestModelConverters$ClassNameExtensionModelResolver.resolve(RestModelConverters.java:117)
	at io.swagger.v3.core.converter.ModelConverterContextImpl.resolve(ModelConverterContextImpl.java:97)
	at io.swagger.v3.core.converter.ModelConverters.readAll(ModelConverters.java:204)
	at io.swagger.v3.core.converter.ModelConverters.readAll(ModelConverters.java:195)
	at org.apache.camel.openapi.RestModelConverters.readClassOpenApi3(RestModelConverters.java:77)
	at org.apache.camel.openapi.RestModelConverters.readClass(RestModelConverters.java:66)
	at org.apache.camel.openapi.RestOpenApiReader.appendModels(RestOpenApiReader.java:1029)
	at org.apache.camel.openapi.RestOpenApiReader.parse(RestOpenApiReader.java:324)
	at org.apache.camel.openapi.RestOpenApiReader.read(RestOpenApiReader.java:209)

The parser creates the schema model in line 597 depending on v3.1 vs v3.0 as the following code shows:

https://github.com/swagger-api/swagger-core/blob/master/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java#L597

And then you have the class cast exception because of this:

https://github.com/swagger-api/swagger-core/blob/master/modules/swagger-core/src/main/java/io/swagger/v3/core/jackson/ModelResolver.java#L1046

Maybe that type cast need to check if its v3.1 and v3.0 or better handle the ComposedSchema vs JsonSchema without a hardcoded type-cast.

davsclaus avatar May 21 '25 07:05 davsclaus

Ticket at Apache Camel: https://issues.apache.org/jira/browse/CAMEL-22094

davsclaus avatar May 21 '25 07:05 davsclaus

I ran into this too. If it helps debug & fix the issue, here's a quick way to reproduce the problem. It looks like any @Schema annotation with allOf(), anyOf(), oneOf() will trigger it.

package example.swagger;

import io.swagger.v3.core.util.Json31;
import io.swagger.v3.jaxrs2.integration.JaxrsOpenApiContextBuilder;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.integration.SwaggerConfiguration;
import io.swagger.v3.oas.integration.api.OpenApiContext;
import io.swagger.v3.oas.models.OpenAPI;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import java.util.Set;

interface A {
    String getA();
}

interface B {
    String getB();
}

@Schema(allOf = {A.class, B.class})
interface C extends A, B {}

@Path("test")
class Resource {
    @GET
    public C get() {
        return null; // implementation not needed for this example
    }
}

public class Repro {
    public static void main(String[] args) throws Exception {
        SwaggerConfiguration config = new SwaggerConfiguration()
                .resourcePackages(Set.of("example.swagger"))
                .openAPI31(true);
        OpenApiContext context = new JaxrsOpenApiContextBuilder<>()
                .openApiConfiguration(config)
                .buildContext(true);
        OpenAPI openApi = context.read();   // <======== Throws ClassCastException w/2.2.31

        System.out.println(Json31.mapper().writeValueAsString(openApi));
    }
}

shawnsmith avatar Jun 03 '25 18:06 shawnsmith

Agree with @davsclaus analysis. This is a blocking issue, for any further upgrades from 2.2.30

bnasslahsen avatar Jun 09 '25 10:06 bnasslahsen

Given that ComposedSchema only adds a toString method I thought I'd see what happens if the ModelResolver just doesn't do that cast:

            Schema composedSchema = model;

All swagger-project tests pass and my project builds cleanly.

Yaytay avatar Jun 15 '25 06:06 Yaytay

The same happened to me when I upgraded to 2.2.33 and set the <openapi31>true</openapi31>.

thiagohora avatar Jun 18 '25 20:06 thiagohora

Same for me with 2.2.34

EmhyrVarEmreis avatar Jul 31 '25 15:07 EmhyrVarEmreis

I have created a PR with fix for this error https://github.com/swagger-api/swagger-core/pull/4948

EmhyrVarEmreis avatar Aug 01 '25 08:08 EmhyrVarEmreis

Hi @EmhyrVarEmreis , Thanks a lot for coming up with the solution and putting in the work on this! I’ve created a follow-up PR here: https://github.com/swagger-api/swagger-core/pull/4950 based on your changes. I’ve renamed a few variables to make the code a bit more readable, and I also added some additional tests to ensure there’s no regression.

ewaostrowska avatar Aug 11 '25 09:08 ewaostrowska