Dynamic Filtering of APIs

573 views
Skip to first unread message

Bryan Nelson

unread,
Feb 23, 2017, 1:38:29 PM2/23/17
to Swagger
Greetings,

I've inherited a JAX-RS rest-based Java application that contains roughly 350 operations.  I have a need to dynamically generate multiple subset APIs out of this codebase based upon certain criteria at runtime.  For example, perhaps I want to generate an API that contains all of the "Brand X", "Employee", and "User" services.  But I also want to see an API that has all of "Brand Y" and "User" services.  I know that this can be done using the tagging elements of the Java annotations, but the trouble is I would have to alter the Java code and hide/unhide different operations, then re-build, restart the server, etc. each time I wanted to see a different subset of the API.  The limitation that I see with Swagger-Core out of the box is that the entire swagger.json file is generated upon server startup / first Swagger hit (please correct me if I'm wrong on that). 


Now in order to meet my need I have a few ideas.  All of them involve initially placing all the appropriate tags on each service operation in the Java code to begin with.

  1. UI Solution - Generate the complete API from a full swagger.json file that includes all operations.  Based upon some UI user inputs (perhaps checkboxes for "Brand X", "Brand Y", "User", etc.) parse through the full swagger.json file via Javascript and basically "filter out" all of the tags that aren't checked by the user, thus creating a subset swagger.json of only the desired tagged operations which can then be displayed via Swagger UI.
  2. Post-Json-Generated Java Solution - Generate the complete API from a full swagger.json file that includes all operations.  Create a rest-based web service that takes in user inputs in the request (for "Brand X", "Brand Y", "User", etc.), parse through the full swagger.json file using Java (Jackson, Gson, etc.), and basically "filter out" all of the tags that aren't checked by the user, thus creating a subset swagger.json of only the desired tagged operations which can then be returned in the service response and used via whatever UI technology desired
  3. Pre-Json-Generated Java Solution - Figure out a way to regenerate the swagger.json file with the application still running whenever desired, and then generate the partial API from a partial swagger.json file that includes only the desired operations based upon the tags (for "Brand X", "Brand Y", "User", etc.) using a Java Filter.  This could be run before the swagger.json file was created so only the desired subset was ever created based upon input parameters (e.g. the tag names).  This could potentially be created as a rest-based service as well.

I'd love some input on these solutions.  I think that #2 is desirable over #1 because it is not coupled to any UI implementation at all and would be more reusable.  However, I think that, if possible, #3 would be the best way to go.  My mine question is there even a way to accomplish #3?  Can you the swagger.json file be regenerated without restarting the server?

Also, is there a better/known way to achieve what I'm trying to do?

Any thoughts are very much appreciated; thanks for your time!

 

Ron Ratovsky

unread,
Feb 23, 2017, 1:58:30 PM2/23/17
to swagger-sw...@googlegroups.com

Hi Brian,

 

Have you seen our own filtering option in swagger-core?

Take a look at this sample to get an idea - https://github.com/swagger-api/swagger-samples/blob/master/java/java-jersey2/src/main/java/io/swagger/sample/util/ApiAuthorizationFilterImpl.java.

--
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.

Bryan Nelson

unread,
Feb 23, 2017, 2:06:41 PM2/23/17
to Swagger
Hi Ron,

Yes I have.  This is the kind of filter I would like to implement in my solution #3.  But my understanding as of now is that the ApiAuthorizationFilter would only help me if I didn't need to regenerate the swagger.json on the fly.  Is there a way to regenerate the swagger.json file with the application still running whenever desired?  If that isn't possible then I'm not sure how the ApiAuthorizationFilter could help me...

Thank you for your time,
bryan

To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggersocket+unsub...@googlegroups.com.

Ron Ratovsky

unread,
Feb 23, 2017, 2:10:02 PM2/23/17
to swagger-sw...@googlegroups.com

Are you changing your resources dynamically at runtime? If not, I don’t understand why you need to regenerate the swagger.json.

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.

--

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.

Bryan Nelson

unread,
Feb 23, 2017, 2:14:00 PM2/23/17
to Swagger
I'm not changing them dynamically at runtime.  Perhaps I am misunderstanding when the ApiAuthorizationFilter would get applied?  It seems like this would happen as a "one-time thing" on when the very first swagger call was made.  Is that correct?

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.

Ron Ratovsky

unread,
Feb 23, 2017, 2:15:44 PM2/23/17
to swagger-sw...@googlegroups.com

No. The filter executed before the swagger.json returns to the consumer and allows for dynamic filtering of operations and parameters.

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.

--
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.

--
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.

Bryan Nelson

unread,
Feb 23, 2017, 2:23:40 PM2/23/17
to Swagger
Ah.  So you're saying that I could create a web service (like I was thinking in solution #3) that would invoke the ApiAuthorizationFilter using some passed in parameters that would essentially just give me back a subset of the overall swagger.json as desired?  

If that's the case then does the ApiAuthorizationFilter already inherently have access to the swagger.json file?

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.


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.

Ron Ratovsky

unread,
Feb 23, 2017, 2:30:34 PM2/23/17
to swagger-sw...@googlegroups.com

You already have a web service, hosting your API and swagger.json. You only need to write the Filter, configure swagger-core to use it, sit back, and relax.

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.

--
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.

--
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.

--
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.

Bryan Nelson

unread,
Feb 23, 2017, 2:38:41 PM2/23/17
to Swagger
At the risk of sounding really ignorant, what do you mean I "already have a web service"?  Right now I have the SwaggerUI pointing to the swagger.json file from the index.html file as such:

      if (url && url.length > 1) {
        url = decodeURIComponent(url[1]);
      } else {
        url = "/myContext/swagger.json";
      }
The UI then renders the swagger.json file from there.  Isn't that just pointing to a json file?  Are you saying that's actually a webservice?

Forgive my ignorance...

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.


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.


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.

Ron Ratovsky

unread,
Feb 23, 2017, 2:44:59 PM2/23/17
to swagger-sw...@googlegroups.com

Is your swagger.json not generated using swagger-core at runtime?

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.

--
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.

--
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.

--
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.

--
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.

Bryan Nelson

unread,
Feb 23, 2017, 3:06:07 PM2/23/17
to Swagger
Ok, here's my setup.  I have the UI working like mentioned above.  I then have a java class that extends javax.ws.rs.core.Application where I do this:

public class MyApplication extends Application {

 
public MyApplication() {
        BeanConfig beanConfig = new BeanConfig();
        beanConfig.setVersion("1.0");
        beanConfig.setTitle("My App");
        beanConfig.setDescription("My description.");
        beanConfig.setSchemes(new String[]{"http, https"});
        beanConfig.setBasePath("/myContext/"); 
        beanConfig.setResourcePackage("com.myPackage.rest.resource");
        beanConfig.setPrettyPrint(true);
        beanConfig.setScan(true);
    }

    @Override
    public Set<Class<?>> getClasses() { 
     
Set<Class<?>> resources = new HashSet<Class<?>>(); 
        resources.add(ApiListingResource.class);
        resources.add(SwaggerSerializers.class);
        
        return resources;
    }

}

That's all I have really besides all my annotations obviously.


Ron Ratovsky

unread,
Feb 23, 2017, 3:15:47 PM2/23/17
to swagger-sw...@googlegroups.com

So that’s your web service. You just need to add your filter to that.

 

 

 

From: <swagger-sw...@googlegroups.com> on behalf of Bryan Nelson <bryan.j...@gmail.com>
Reply-To: "swagger-sw...@googlegroups.com" <swagger-sw...@googlegroups.com>
Date: Thursday, 23 February 2017 at 12:06
To: Swagger <swagger-sw...@googlegroups.com>
Subject: Re: Dynamic Filtering of APIs

 

Ok, here's my setup.  I have the UI working like mentioned above.  I then have a java class that extends javax.ws.rs.core.Application where I do this:

--

Bryan Nelson

unread,
Feb 23, 2017, 3:20:43 PM2/23/17
to Swagger
I'm not trying to be obtuse, but how is that a web service?  Also, I need it to accept input params (which would be the tags I'd want to dynamically filter on) and I don't see anyway to make that happen in what I pasted above?

To unsubscribe from this group and stop receiving emails from it, send an email to swagger-swaggersocket+unsub...@googlegroups.com.

Ron Ratovsky

unread,
Feb 23, 2017, 3:28:15 PM2/23/17
to swagger-sw...@googlegroups.com

The Application class is the starting point of your JAX-RS app. It triggers the scanning of your resources and exposes them as a rest service.

All you need to do is create your own Filter (extending AbstratSpecFilter) and adding it to your beanConfig as you can see in https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5#using-swaggers-beanconfig.

 

Look again at https://github.com/swagger-api/swagger-samples/blob/master/java/java-jersey2/src/main/java/io/swagger/sample/util/ApiAuthorizationFilterImpl.java.

The `if(params.containsKey("api_key"))` code checks if there’s a parameter called api_key. It’s just something we chose. You can choose to call it tags or whatever you want.

If you want to use a header instead, you can do that too.

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.

--

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.

Bryan Nelson

unread,
Feb 23, 2017, 3:54:42 PM2/23/17
to Swagger
Now this is becoming more clear.  

The Application class is the starting point of your JAX-RS app. I

Ok, I understand that.
 
It triggers the scanning of your resources

Ok. I got that.
 
and exposes them as a rest service.

This is where I'm confused...under what endpoint is it registered?  Are you saying it is just exposing it at the root of whatever the ApplicationPath annotation has on the extended Application class?  That seems to be the case but I guess my confusion is where is that happening?  Does BeanConfig do that?

Thanks for bearing with me; I really want to understand this!

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.

Ron Ratovsky

unread,
Feb 23, 2017, 4:03:19 PM2/23/17
to swagger-sw...@googlegroups.com

Your getClasses() method in the Application class tells JAX-RS what to scan (there are other methods as well).

 

ApiListingResource.class is just a JAX-RS endpoint like any of your own.

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.

--
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.

--
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.

Bryan Nelson

unread,
Feb 23, 2017, 4:24:40 PM2/23/17
to Swagger
ApiListingResource.class is just a JAX-RS endpoint like any of your own.

Oh.My.Goodness.  I'll risk the egg on my face here and say that I never realized that!  I went on GitHub and looked at ApiListingResource.java and, although I feel pretty dumb, everything is clear now!  My main confusion was that the web service path for ApiListingResource takes a file type as a path param...I never realized that was actually a web service.  I always thought it was just accessing a file under the hood. 

Okay, so now I see what you mean.  I can just extend AbstractSpecFilter putting in my own filtering based upon passed in tags (via header, params, whatever) and then also extend either ApiListingResource.java or, more likely BaseApiListingResource.java, and alter the service there to accept the input (via header, params, whatever) for the filtering items.

Done.

Thanks a lot for your patience Ron...this was extremely helpful!

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.


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.

Ron Ratovsky

unread,
Feb 23, 2017, 4:34:31 PM2/23/17
to swagger-sw...@googlegroups.com

You actually shouldn’t need to modify ApiListingResource at all, just create the filter.

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.

--
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.

--
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.

--
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.

Bryan Nelson

unread,
Feb 23, 2017, 4:40:59 PM2/23/17
to Swagger
Oh, right.  Because I could essentially do something like this right now "/myContext/swagger.json?filter=whatever" and the service in ApiListingResource will be able to access that filter query param already.

I just have to reference the "filter" param in my filter...wow.

It took a while, but I think I got there.

Thanks again!

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.


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.


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.

Reply all
Reply to author
Forward
0 new messages