How to configure an @ApiDefinition annotation for all resource classes in a project?
DarkStar1 opened this issue · 2 comments
I'm currently trying out the 5.2.0-alpha1 version with swagger jersey components in my springboot project.
I get the following error when I annotate more than one class with the @Api() swagger annotation:
Validation of the application resource model has failed during application initialization. [[FATAL] A resource model has ambiguous (sub-)resource method for HTTP method GET and input mime-types as defined by"@consumes" and "@produces" annotations at Java methods public javax.ws.rs.core.Response com.holonplatform.jaxrs.swagger.internal.SwaggerApiListingResource.getApiListing(java.lang.String) and public javax.ws.rs.core.Response com.holonplatform.jaxrs.swagger.internal.SwaggerApiListingResource.getApiListing(java.lang.String) at matching regular expression /api-docs/default. These two methods produces and consumes exactly the same mime-types and therefore their invocation as a resource methods will always fail.; source='org.glassfish.jersey.server.model.RuntimeResource@2a7bb45c', [FATAL] A resource model has ambiguous (sub-)resource method for HTTP method GET and input mime-types as defined by"@consumes" and "@produces" annotations at Java methods public javax.ws.rs.core.Response com.holonplatform.jaxrs.swagger.internal.SwaggerApiListingResource.getApiListing(java.lang.String) and public javax.ws.rs.core.Response com.holonplatform.jaxrs.swagger.internal.SwaggerApiListingResource.getApiListing(java.lang.String) at matching regular expression /api-docs. These two methods produces and consumes exactly the same mime-types and therefore their invocation as a resource methods will always fail.; source='org.glassfish.jersey.server.model.RuntimeResource@258b4dfa']
So below is an reduced version of my setup:
@ApiDefinition(docsPath = "/api/docs", title = "...", version = "v1", prettyPrint = true)
@Api(value = "Trolley", consumes = "application/json", produces = "application/json")
@Path("Object")
public class SomeResource {
@ApiOperation("Just returns a JSON object.")
@ApiResponses(.....)
@GET
@Path("{objectId}")
public Response getObject(@PathParam("objectId") String templateVar){....}
}
@Api(value = "System Test", produces = "text/html")
@Component
@Path("system")
public class TestResource {
@ApiOperation("Just returns a HTML basic page with information.")
@ApiResponses(.....)
@GET
@Path("check")
public Response returnSomeHTMLTexT() {....}
}
The other question I have, as it is not clear in the documentation, must I add an @ApiDefinition to all resource classes in order to have them provide JSOn output at the same endpoint uri?
Hi @DarkStar1,
we just releases the Holon Platform version 5.2.0-alpha2, which fixes some bugs related to Swagger JAX-RS auto-configuration.
We're improving the documentation, you can find the 5.2.0-alpha2 Swagger JAX-RS auto-configuration docs here.
In short words, the Swagger API documentation endpoints auto-configuration works this way:
- If the Holon Swagger configuration properties are available from Spring Boot application properties, they take the precedence over the
@ApiDefinition
annotation. - Otherwise, the
@ApiDefinition
annotation is used for the Swagger endpoints configuration.
Anyhow, only the JAX-RS endpoints annotated with both @Path
and @Api
are taken into account for API documentation generation. This because is how the Swagger JAX-RS integration works by default.
So, if you use the Holon Swagger configuration properties, for example:
holon:
swagger:
resource-package: "my.api.endpoints.package"
To declare the package (one or more) to scan to detect the JAX-RS endpoints annotated with @Path
and @Api
and generate the Swagger API endpoint. The endpoint path is /api-docs
by default, or you can specify it using the path
property:
holon:
swagger:
resource-package: "my.api.endpoints.package"
path: "/my-docs"
So, if you don't use the Holon Swagger configuration properties, all the @Path
and @Api
annotated JAX-RS endpoint Spring beans are detected from classpath. So you have to ensure the JAX-RS endpoints are Spring beans too, for example using the @Component
annotation.
In this scenario, the @ApiDefinition
can be used (but it is optional) to configure:
- The Swagger API endpoint path, using the annotation
value()
- The Swagger API general configuration, for example the API title or description
The API path declaration can be used to declare more than one API documentation endpoint. The documentation of each valid JAX-RS endpoint bound to the same API path will be merged into a single Swagger API documentation endpoint.
For example, given the following JAX-RS endpoints:
@Api
@Path("example1")
@Component
class ExampleEndpoint1 {
/* Operations omitted */
}
@Api
@Path("example2")
@Component
class ExampleEndpoint2 {
/* Operations omitted */
}
A single Swagger API documentation endpoint will be auto-generated and mapped to the default /api-docs
path, and will include all the API operations provided by the two endpoint.
To declare two different Swagger API documentation endpoints, the @ApiDefinition
annotation can be used, for example:
@ApiDefinition("/docs1")
@Api
@Path("example1")
@Component
class ExampleEndpoint1 {
/* Operations omitted */
}
@ApiDefinition("/docs2")
@Api
@Path("example2")
@Component
class ExampleEndpoint2 {
/* Operations omitted */
}
This way, two Swagger API documentation endpoints will be auto-generated, one mapped to the /docs1
path and the other mapped to the /docs2
path.
To merge another JAX-RS endpoint, an @ApiDefinition
annotation with the same path can be used:
@ApiDefinition("/docs1")
@Api
@Path("example1")
@Component
class ExampleEndpoint1 {
/* Operations omitted */
}
@ApiDefinition("/docs2")
@Api
@Path("example2")
@Component
class ExampleEndpoint2 {
/* Operations omitted */
}
@ApiDefinition("/docs2")
@Api
@Path("example3")
@Component
class ExampleEndpoint3 {
/* Operations omitted */
}
In the example above, two Swagger API documentation endpoints will be auto-generated (one mapped to the /docs1
path and the other mapped to the /docs2
path): the first one will only contain the ExampleEndpoint1
operations, while the second one will contain both the ExampleEndpoint2
and ExampleEndpoint3
operations.
When you use the @ApiDefinition
annotation for the documentation configuration (title, description and so on), the @ApiDefinition
attribute values for the same API documentation path must be consistent, a configuration exception is thrown otherwise.
Thanks for your detailed explanation.