Multiple APIs from single war file

166 views
Skip to first unread message

Peter Varga

unread,
Nov 27, 2014, 3:04:26 PM11/27/14
to swagger-sw...@googlegroups.com
I'm using Swagger with JAX-RS + Jersey. So far we've had 1 single API:

/v1

Now we need to add another

/v2

Both of these are served by the same war file, via a separate <servlet> in the web.xml.

I would like to get the Swagger resource listing using
/v1/api-docs-v1
/v2/api-docs-v2


I've defined my own classes that extend the ApiListingResource class, but I'm not having much luck. Swagger seems to cache the resource listing. I always get the resource listing for whichever one was invoked first.

Is what I'm trying to do possible or is this just not going to work?

Thanks

tony tam

unread,
Nov 27, 2014, 3:49:42 PM11/27/14
to swagger-sw...@googlegroups.com

I think the only way you can do this is if you configure one of the servlets to scan both packages.

Peter Varga

unread,
Dec 2, 2014, 12:29:10 PM12/2/14
to swagger-sw...@googlegroups.com
Well, I don't want to do that because I want each servlet to serve a different API.

One can have as many servlets as desired, and Jersey has no issues with this. All paths to Jersey APIs are relative to the servlet's URL.

So this is a limitation in Swagger? Some state is global/static when it shouldn't be?

Ron

unread,
Dec 2, 2014, 12:35:49 PM12/2/14
to swagger-sw...@googlegroups.com
It's a limitation of swagger-core, not of Swagger. It's not really such a common use case that we were asked to support so far.

--
You received this message because you are subscribed to the Google Groups "Swagger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggers...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

tony tam

unread,
Dec 3, 2014, 2:02:25 AM12/3/14
to swagger-sw...@googlegroups.com
You can do this with some hacking in swagger-core 1.5.0-SNAPSHOT but not in 1.3.x as the swagger object in 1.3.x is a static global, and cannot vary inside a single class loader.

Tom Clabon

unread,
Feb 19, 2015, 5:09:27 AM2/19/15
to swagger-sw...@googlegroups.com
We have the exact same use case, multiple versions of an API. We currently use 1.3.5 and it seems like there is quite some work to upgrade to 1.5.0.

I tracked the issue down to the ApiListingCache which has a single, static cache object. This is used, even if the listing is requested for a different Application instance.

In our case, each API is an Application, and the Application instance for an API is a Singleton, so I have patched swagger 1.3.5 locally to change the cache in ApiListingCache to be keyed by the Application instance and it works fine for us. However, I don't know if this is a safe assumption for anyone else? If it is, I can make a pull request for the patch.


On Wednesday, December 3, 2014 at 7:02:25 AM UTC, tony tam wrote:
You can do this with some hacking in swagger-core 1.5.0-SNAPSHOT but not in 1.3.x as the swagger object in 1.3.x is a static global, and cannot vary inside a single class loader.
On Dec 2, 2014, at 9:35 AM, Ron <web...@gmail.com> wrote:

It's a limitation of swagger-core, not of Swagger. It's not really such a common use case that we were asked to support so far.
On 2 December 2014 at 19:29, Peter Varga <peter...@gmail.com> wrote:
Well, I don't want to do that because I want each servlet to serve a different API.

One can have as many servlets as desired, and Jersey has no issues with this. All paths to Jersey APIs are relative to the servlet's URL.

So this is a limitation in Swagger? Some state is global/static when it shouldn't be?


On Thursday, November 27, 2014 3:49:42 PM UTC-5, tony tam wrote:

I think the only way you can do this is if you configure one of the servlets to scan both packages.

On Thursday, November 27, 2014 10:04:26 AM UTC-10, Peter Varga wrote:
I'm using Swagger with JAX-RS + Jersey. So far we've had 1 single API:

/v1

Now we need to add another

/v2

Both of these are served by the same war file, via a separate <servlet> in the web.xml.

I would like to get the Swagger resource listing using
/v1/api-docs-v1
/v2/api-docs-v2


I've defined my own classes that extend the ApiListingResource class, but I'm not having much luck. Swagger seems to cache the resource listing. I always get the resource listing for whichever one was invoked first.

Is what I'm trying to do possible or is this just not going to work?

Thanks

--
You received this message because you are subscribed to the Google Groups "Swagger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggersocket+unsub...@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Swagger" group.
To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggersocket+unsub...@googlegroups.com.

tony tam

unread,
Feb 19, 2015, 11:49:30 AM2/19/15
to swagger-sw...@googlegroups.com
Upgrading a single API to 1.5.x should be trivial as all the annotations have remained constant.  If you're doing something special (like it sounds like you are), it may be tougher.

For what I *think* you're doing, there's a elegant solution and it gets you around monkey patching swagger.

My assumption is that you have one war file in your container for, say version1 of your api.  That has a completely different swagger description than another api, version2.  Depending on "some logic", you will serve up the appropriate version of swagger.

If that logic is a path segment, or a header param, the solution is the same.

Deploy two war files in your container, each using the 1.5.x swagger-jaxrs.  Make a third war file with a servlet which will determine which api version they're looking for an forward the request to the appropriate path.  That will give you not only an unmodified (and extensible) swagger implementation, but a clean separation between the code in both deployments.

Make sense?

Tom Clabon

unread,
Feb 25, 2015, 8:16:24 AM2/25/15
to swagger-sw...@googlegroups.com
Yep we're doing something "special" so it's not so simple to upgrade. 

What you're doing makes sense, but we don't generally run our apps as wars, but instead start a Jetty instance. Inside Jetty, we deploy a Servlet for each API version. Each API has a set of interfaces with Jersey/Swagger annotations. Some of our apps we can run as wars, but the app is a single war composed of all the APIs that app can support. Either way, our APIs all run in the same Swagger scope so your solution or a similar one would not work for us.

The way I patched Swagger works fine for us, and I'd like for it to be integrated into Swagger itself. However, I don't know whether the assumption that each Application is a singleton is always true which is critical to this patch working nicely (otherwise there would be no point having a cache).

Tom

tony tam

unread,
Mar 3, 2015, 8:45:54 PM3/3/15
to swagger-sw...@googlegroups.com
Hi Tom, there are many options.  First, swagger is simply a pojo that is written out to JSON.  There are many, many ways to generate it.

The simplest way to extend that logic is to look in the Reader.java.  It simply takes in a Set<Class<?>> and will return the pojo.  Can't get any easier than that.

The set of classes can come from any logic you like.  Use reflections to scan for them, for example.  But they need to have the Swagger Annotations.
Reply all
Reply to author
Forward
0 new messages