smallrye-open-api icon indicating copy to clipboard operation
smallrye-open-api copied to clipboard

Duplicate operationId

Open nimo23 opened this issue 1 year ago • 2 comments

According to https://github.com/smallrye/smallrye-open-api/issues/1688, it should be resolved, but I am getting also the "SROAP07903: Duplicate operationId"-error.

I have MyResource which makes use of an Interface:

@Path("/myResource")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
@ApplicationScoped
public class MyResource implements MyInterface<User>{

        @GET
	@Path("/{id}")
	@APIResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(type = SchemaType.OBJECT, implementation = User.class)))
	@Override
	public Response getById(Integer id) {
		return MyInterfae.super.byId(id);
	}

}

The interface:

interface MyInterface<T> {

	@GET
	@Path("/{id}")
        default Response getById(@PathParam("id") Integer id) {
		// implemenation
	}

}

and the operationId is generated by Quarkus (version 3.15.1) by using the following property:

mp.openapi.extensions.smallrye.operationIdStrategy=CLASS_METHOD

when running in dev or test mode, it prints:

[io.sma.ope.run.sca.spi] (build-9) SROAP07903: Duplicate operationId: MyResource_getById produced by Class: com.acme.MyResource, Method: jakarta.ws.rs.core.Response getById(java.lang.Integer id) and Class: com.acme.MyResource, Method: jakarta.ws.rs.core.Response getById(Integer id)

If I interpret the error message correctly: It complains about a operationId even though it is the same class (it compares the MyResource class with itself which does not make sense), or?

nimo23 avatar Oct 03 '24 10:10 nimo23

@nimo23 is the getById method in your interface defined as a default method? Just curious because the code snippet shows a method body.

MikeEdgar avatar Oct 07 '24 18:10 MikeEdgar

is the getById method in your interface defined as a default method?

Yes, I corrected it above. It is:

@GET
@Path("/{id}")
default Response getById(@PathParam("id") Integer id) {
	// implemenation
}

nimo23 avatar Oct 08 '24 10:10 nimo23

@nimo23 are you required to re-specify the JAX-RS annotations on the implementation class?

That is, can you remove @GET @Path("/{id}") from MyResource#getById and allow them to be inherited from MyInterface#getById ?

MikeEdgar avatar Nov 14 '24 17:11 MikeEdgar

are you required to re-specify the JAX-RS annotations on the implementation class?

Yes, it is required. Since the interface is a generic interface, its implementation can be any class type. For example, the implementation of getId might have different operationIds because they belong to different types of classes:

// within Task implements MyInterface<Task>
@Operation(operationId = "TaskResource_taskById")

or

// within User implements MyInterface<User>
@Operation(operationId = "UserResource_userById")

Therefore, there is no way to set the operationId within the generic class.

nimo23 avatar Nov 14 '24 21:11 nimo23

What I am getting at is, if you put @GET @Path("/{id}") on getById in the interface, you shouldn't need to have it again in the implementations (as long as there are no other JAX-RS annotations on the implementation methods).

I think in that case you should get the operationIds as expected without the warning in the logs.

MikeEdgar avatar Nov 14 '24 21:11 MikeEdgar

What I am getting at is, if you put @GET @Path("/{id}") on getById in the interface, you shouldn't need to have it again in the implementations (as long as there are no other JAX-RS annotations on the implementation methods).

Yes, this seems to solve the problem. However, this problem is only solved as long as the user does not have to override the jax-rs annotations in their implementation class. See https://github.com/jakartaee/rest/blob/main/jaxrs-spec/src/main/asciidoc/chapters/resources/_annotationinheritance.adoc

nimo23 avatar Nov 14 '24 21:11 nimo23

Fair enough, I'll push a fix for this to ignore duplicates when the duplicate is an override.

MikeEdgar avatar Nov 14 '24 22:11 MikeEdgar