Open kriegerkl opened 7 years ago
Thanks @kriegerkl for re-opening this ticket. The suggested solution in the original thread appears to be for a different problem, namely how to add multiple resource packages to the same swagger API, rather than how to keep two APIs separated.
Any solution for this, even I am facing the same problem.
Many many thanks to Dherik, who just emailed me this solution to the problem:
Did you try to set the ConfigId and ScannerId in the BeanConfig? I have the same issue, but I was using web.xml and add this parameters in my Application:
For api1:
`
<param-value>api1</param-value>
@andi-livn , I'm glad that work for you! I posted the solution, but after that I thought that your problem is different and I deleted my answer. But you had already received the e-mail from Github :)
I think I posted the solution in another thread. I'm trying to find where now... lol.
All the secret for this works is in BaseApiListingResource
(code). By default, the swagger load only one time (see the static initialized
variable) and this is the problem that I have: show always the swagger documention from the first endpoint loaded. I can't explain only looking the code your case, in which the second (last) endpoint loaded is mandatory.
About setScannerId and setConfigId, when you set these variables, Swagger use another mechanism to control what endpoint was already loaded, using the static ConcurrentMap
and controlling using a kind of "key" for that ConcurrentMap
: the scannerId and configId values.
@andi-livn Are you use the Guice with the servlet? if I use the Guice like the official demo https://github.com/swagger-api/swagger-samples/blob/master/java/java-jersey2-guice/src/main/webapp/WEB-INF/web.xml , how to config it?
according to my test, which servlet module is configured firstly, the corresponding beanConfig will be enabled.
@xmeng1 We aren't using Guice and in fact not even Jersey 2, but the old 1.19, so unfortunately I cannot answer your question, sorry.
@andi-livn @dherik Do you have any idea on how this would translate to Swagger 2.0?
Sorry @strangelookingnerd we have never made the switch to Swagger 2.x in our application, still on the 1.5.x branch.
For anyone looking for a Swagger 2.x solution, here is what I did:
public abstract class AbstractApplication extends Application {
@Context
private ServletConfig _servletConfig;
public AbstractApplication() {
try {
SwaggerConfiguration oasConfig = new SwaggerConfiguration().id(UUID.randomUUID().toString())
.prettyPrint(true)
.resourceClasses(getServiceApis().stream().map(Class::toString).collect(Collectors.toSet()));
new JaxrsOpenApiContextBuilder<>().servletConfig(_servletConfig).openApiConfiguration(oasConfig)
.buildContext(true);
} catch (OpenApiConfigurationException ex) {
throw new RuntimeException(ex.getMessage(), ex);
}
}
public abstract Set<Class<?>> getServiceApis();
@Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<>(getServiceApis());
// Add Swagger
resources.add(OpenApiResource.class);
return resources ;
}
public class MyApplication extends AbstractApplication {
@Override
public Set<Class<?>> getServiceApis() {
return Stream.of(MyServiceApi.class).collect(Collectors.toSet());
}
}
This way I didn't have to tinker with the web(-fragment).xml and all of my Applications only had to extend the abstract and provide their Service APIs.
The only thing that is important here is that each and every Application has their own (unique) SwaggerConfiguration ID in order to be split into multiple swagger.jason properly.
Generally in Swagger Core 2.0, you can achieve this using contexts and context ids, please check wiki Context section, specifically the last example.
We are running two separate Jersey APIs in the same server context, il.e. two separate classes extending com.sun.jersey.api.core.PackagesResourceConfig are configured in Tomcat 7's web.xml to be two accessible under two separate base paths. Simplified it's:
The two APIs do not share any model classes or other code and are completely separate in every aspect incl security, filter chains etc. There are two separate application.wadl files (and their corresponding XSD schema) generated by Jersey, each describing only the resources from their respective API.
We are using swagger in the first API, configuring it using BeanConfig:
BeanConfig bc = new BeanConfig(); bc.setVersion("1.0"); bc.setTitle(" API1 Documentation"); bc.setSchemes(new String[]{"https"}); bc.setBasePath("/appRoot/api1"); bc.setResourcePackage("api1.resource"); bc.setScan(true);
Now we try to add Swagger to the second API as well, by declaring this in our Api2ServerConfig:
BeanConfig bc = new BeanConfig(); bc.setVersion("1.0"); bc.setTitle(" API2 Documentation"); bc.setSchemes(new String[]{"https"}); bc.setBasePath("/appRoot/api2"); bc.setResourcePackage("api2.resource"); bc.setScan(true);
Unfortunately while this results in two separate swagger.json documents under /appRot/api1/swagger.json and /appRoot/api2/swagger.json, the two APIs are not treated separately as we had hoped.
The contents of whichever swagger document we access first after starting the server are fine. If we access /appRoot/api1/swagger.json, it contains all the paths and types of API1 and nothing from API2's realm. If however we next access /appRoot/api2/swagger.json, it lists both its own resources AND every tag, path and type definition from API1. Vice versa, if /appRoot/api2/swagger.json is accessed first and then appRoot/api1/swagger.json, API2's document is correct, but itself is now leaking into API1's swagger.json. The title and basePath are correct in both documents.
It is the same problem like in #1359. It is not possible to have 2 BeanConfigs with 2 different BasePath.