Swagger overrides Path-Annotations - jax-rs

I just got swagger to produces a valid swagger.json.
I configured swagger by using the Application-config method.
However, as soon as I override the getClasses-Method to add the swagger resouces, my JAX-RS Path-annotated classes stop working.
The method looks like this
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> resources = new HashSet<>();
resources.add(io.swagger.jaxrs.listing.ApiListingResource.class);
resources.add(io.swagger.jaxrs.listing.SwaggerSerializers.class);
return resources;
}
and invoking super.getClasses() returns am empty set.
I got too many resources in my project, which I would not like to add manually.
Is there any way swagger does not mess with my previous configuration?
Thank you!

You can use a javax.ws.rs.core.Feature. Just register the classes through the callback's FeatureContext. Annotating the feature with #Provider will have it registered through the scanning.
#Provider
public class SwaggerFeature implements Feature {
#Override
public boolean configure(FeatureContext context) {
context.register(ApiListingResource.class);
context.register(SwaggerSerializers.class);
return true;
}
}
But note that if the application is already registering the resources and providers by class-path scanning, I imagine it should also pick up the Swagger classes, as they are annotated with #Path[1] and #Provider[2]. Those are the annotations the class-path scan looks for.
I haven't tried it myself (I stopped using class-path scanning[3]), but have you tried just not registering them at all? In theory the class-path scan should pick it up.
1. io.swagger.jaxrs.listing.ApiListingResource
2. io.swagger.jaxrs.listing.SwaggerSerializers
3. When to Use JAX-RS Class-path Scanning Mechanism

Related

How to write global filter for mobilefirst 8.0 java adapter

I need a global filter on mobilefirst 8.0 java adapter. Am tring to write ContainerRequestFilter filter. But i need some mobilefirst data in there. ConfigurationApi,AdaptersAPI. How can i get it in this context ? Or there have other way to call some code with all java adapter methods ?
You can write a ContainerRequestFilter and use it with an adapter. All you need to do is add to the getClasses() method in the adapter application class (unless it's in the same package as the application class, in this case it will happen automatically).
You can use the #Context annotation in filters to inject any MFP API you need, just like in your resource classes.
Here is a working example:
public class MyRequestFilter implements ContainerRequestFilter {
#Context
ConfigurationAPI configApi;
#Override
public void filter(ContainerRequestContext requestContext) throws IOException {
doStuff();
}
}
Thanks all! Question was solved. Helped this page
https://jax-rs-spec.java.net/nonav/2.0-rev-a/apidocs/index.html about #NameBinding annotation.
and additional #Produce annotation on Filter class.

How to add Custom Interceptor in Spring data rest (spring-data-rest-webmvc 2.3.0)

I am working on the spring data rest services & facing some issue in the custom interceptors. Earlier I used spring-data-rest-webmvc 2.2.0 & added interceptor in following way.
public RequestMappingHandlerMapping repositoryExporterHandlerMapping() {
RequestMappingHandlerMapping mapping = super
.repositoryExporterHandlerMapping();
mapping.setInterceptors(new Object[] { new MyInterceptor() });
return mapping;
}
It worked perfectly fine for me. But when i upgraded to spring-data-rest-webmvc 2.3.0 version, I noticed that handlerMapping is hidden behind DelegatingHandlerMapping. Hence I tried to add interceptor in following way.
In one of my config class I have extended RepositoryRestMvcConfiguration class & override its method.
public class AppConfig extends RepositoryRestMvcConfiguration {
#Autowired ApplicationContext applicationContext;
#Override
public DelegatingHandlerMapping restHandlerMapping()
{
RepositoryRestHandlerMapping repositoryMapping = new RepositoryRestHandlerMapping(super.resourceMappings(), super.config());
repositoryMapping.setInterceptors(new Object[] { new MyInterceptor()});
repositoryMapping.setJpaHelper(super.jpaHelper());
repositoryMapping.setApplicationContext(applicationContext);
repositoryMapping.afterPropertiesSet();
BasePathAwareHandlerMapping basePathMapping = new BasePathAwareHandlerMapping(super.config());
basePathMapping.setApplicationContext(applicationContext);
basePathMapping.afterPropertiesSet();
List<HandlerMapping> mappings = new ArrayList<HandlerMapping>();
mappings.add(basePathMapping);
mappings.add(repositoryMapping);
return new DelegatingHandlerMapping(mappings);
}
}
But after adding this some of my repository operations (findAll() operation on repository) start failing. If I removed this interceptors those operations worked fine. (In this interceptor I am just authenticate the user.)
Hence I am unable to understand problem here. Am I adding the interceptor in wrong way? Is there any other way to add the interceptor?
You should not use repositoryMapping.setInterceptors() - it destoys the internal interceptors Spring placed there, and that's probably the reason some methods stopped working.
I suggest you override jpaHelper() method and put your interceptors into the JpaHelper object in RepositoryRestMvcConfiguration. Spring will should them to the global interceptor list.
But, again, if all you need is authentication, why not use a Spring Security filter?
EDIT: the solution above works only for RepositoryRestHandlerMapping, not for BasePathAwareHandlerMapping.
I suggest you declare a custom MappedInterceptor bean somewhere:
#Bean
public MappedInterceptor myMappedInterceptor() {
return new MappedInterceptor(new String[]{"/**"}, new MyInterceptor());
}
From my understanding of the source code Spring should automatically add this interceptor to all request handlers.

Swagger api listing is empty

Recently I have configure swagger with one of my project. Its using jersey2 and JAX-WS on tomcat for restful API. I have used following manual to configure
https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-2.X-Project-Setup-1.5
${basepath}/swagger.json response with following
{"swagger":"2.0","info":{"version":"1.0.0","title":""},"host":"localhost:8080","basePath":"/myapi","schemes":["http"]}
Unfortounately it does not contain any api which is under my resource package.
I have tried with the answer of following question
swagger - empty listing with no API
But it didn't help either.
The above answer using com.wordnik.swagger.* package(s)
But with the manual I got io.swagger.* package(s), which doesn't have
JaxrsApiReader class
My assumption is swagger couldn't scan my api list from Resource package.
But could not figure out which configuration or which code snippet I have missed.
Any help?....
It looks like you forgot to mark the rest endpoints with #Api
I had the same issue, I used a different approach that worked for me, by adding information only in my Application class. In case you have one, that might help you:
public class MyApi extends Application {
public MyApi() {
super();
BeanConfig beanConfig = new BeanConfig();
beanConfig.setTitle("MyApi");
beanConfig.setVersion("0.0.1");
beanConfig.setSchemes(new String[]{"http", "https"});
beanConfig.setHost("localhost:8080");
beanConfig.setBasePath("/mypath");
//putting only the path to my api unblocked me, I removed "io.swagger.resources"
beanConfig.setResourcePackage("system.organization.api");
beanConfig.setScan(true);
beanConfig.setPrettyPrint(true);
}
#Override
public Set<Class<?>> getClasses() {
Set<Class<?>> s = new HashSet<>();
s.add(MyApis);
//for swagger
s.add(ApiListingResource.class);
s.add(SwaggerSerializers.class);
return s;
}
}
Then, the links of classes with #API annotation appeared in swagger.json
Mostly done with the same manual you used: https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-Jersey-1.X-Project-Setup-1.5

How to resolve dependency inside AuthorizeAttribute with WebApi and Ninject

My current setup is using Ninject for simple IoC, everything goes fine, but I'm not able to resolve one of the classes I need inside my AuthorizeAttribute. I need to access a class that does ClaimsVerification:
Here's my code:
IoC Config:
var kernel = new StandardKernel(); // Ninject IoC
// These registrations are "per instance request".
// See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/
kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
.InSingletonScope();
kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
kernel.Bind<ISmartDocumentorUow>().To<SmartDocumentorUow>();
kernel.Bind<IClaimsVerification>().To<ClaimsVerification>();
// kernel
//kernel.BindFilter<MyAuthorizeAttribute>(FilterScope.Controller, 0).WhenControllerHas<RequireRolesAttribute>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
MyAuthorizeAttribute:
public class MyAuthorizeAttribute : AuthorizeAttribute
{
[Inject]
IClaimsVerification clamisverify { get; set; }
public MyAuthorizeAttribute()
{
//var x = System.Web.Mvc.DependencyResolver.Current.(typeof(IClaimsVerification));
}
Yap, sorry, the problem was injecting the iClaimsverification that isn't working in web api..
I tryed with the public property and still it didn't work.
the bindfilter is commented out, because it doesn't exist in the core NInject api (dll), it does exists in the MVC dll of ninject but it works for Action filters in the web mvc, and not in the api mvc for what i can tell..
i do solved the issue like this, though i don't like a lot of this fix:
private IClaimsVerification verifier
{
get
{
return (GlobalConfiguration.Configuration.DependencyResolver.GetService(typeof(IClaimsVerification)) as IClaimsVerification);
}
}
The property you have marked with Inject is private - you need to initialize Ninject with a custom configuration to opt into what would be a much less efficient process
(You didnt state the problem in your question. I see you were trying BindFilter, but it's commented out (why?) - this is the correct approach. I recommend reading the Ninject.MVC3 wiki article on BindFilter for an example)

How to share fluent configuration in a Castle Windsor IOC container

I am trying to create an IOC container in Castle Windsor that's configuration is shared across assemblies.
(What follows is an example of how this works in Unity. What I want to do is to make it work the same way using Castle Windsor)
I have the following project configuration...
TestCompany.Services.Host
(Web project hosting a number of .svc files)
PrintService.svc
Web.Config
Unity.Config
TestCompany.Services.PrintService
IPrintService.cs
PrintService.cs
The actual implementation of my "PrintService" is not implemented inside my Services.Host but in the TestCompany.Services.PrintService assembly.
As part of my shared project code (not shown) I have a container helper which is responsible for loading the unity configuration...
public static IUnityContainer GetContainer()
{
// Checks for existance of container (_container == null) ommitted.
var section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection;
section.Configure(_container, name);
...
...
}
This method loads the unity configuration section from the Unity.Config and uses it to configure the container.
The advantage of this method is that one Unity.Config loaded inside (I presume) the AppDomain can service a number of assemblies. Simply calling GetContainer() from any of the assemblies consumed by my service host will return a container populated with the same type resolution's etc.
I really want to use the fluent configuration in Castle Windsor but I dont see how without this "shared" configuration file that can be acheived. PrintService and any future services will all need to resolve the same dependencies and I dont want to have to repeat my fluent configuration between these services.
Ideally I need some sort of container configured in the service host app that can "flow" into all of the assemblies that it makes use of.
Thanks.
I think I may not be understanding your question but I think I understand your scenario and here is how I do something similar, if it helps at all...
My Philosophy:
Each part of the application should be in charge of registering what
it knows about and nothing more, so there is no need for a single
central configuration file and things that are shared between
components are registered in one place and their interfaces are
available everywhere via a common library.
So let's take an example...
First of all, let us just say (for the purposes of my example) that IPrintService is something that you want to register an implementation of once and use throughout the application and that we have some other component that needs to be implemented by some external module from the main application. We, therefore, create an assembly called Common like so:
Common
public interface IPrintService
{
void Print();
}
public interface IMyService
{
void DoSomething();
}
Now let us think about the main part of the application (maybe it is an ASP .NET application, maybe justa console application, does not really matter). Here we construct the container and ask it to find all the possible components. We can do that like so:
Main Application
// Could be the Global.asax code behind but for simplicity this is
// just a console application
class Program
{
private static readonly IWindsorContainer Mycontainer
= BootstrapContainer();
// Allow access to the raw container - this is probably a bad idea but
// in the rare case that you need it you can get it from here
public static IWindsorContainer Container { get { return Mycontainer; } }
private static IWindsorContainer BootstrapContainer()
{
// Here we will just install every IWindsorInstaller found in any
// assembly in the same folder as the application (so no need for
// references or anything).
var c = new WindsorContainer();
string folder = Path.GetDirectoryName(
Assembly.GetExecutingAssembly().Location);
c.Install(FromAssembly.InDirectory(new AssemblyFilter(folder)));
return c;
}
}
// Here is the print service implementation
public class MyPrintService : IPrintService
{
public void Print()
{
// Print!
}
}
// This is the installer for the main module - here we are saying exactly
// what is implementing the interface
public class MainApplicationInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container
.Register(Component
.For<IPrintService>()
.ImplementedBy<MyPrintService>());
}
}
So now we have a common library with our shared inetrfaces and a main application that will register an implementation for our shared interface and also load up any other modules in the system.
The only thing, therefore, left to do is to consume that print service and use it. We can do this anywhere that is using the container so let's create a third assembly that references only Common (we will call it test module.
Test Module
// This installer installs just the things inside this module since that
// is all it knows about but those things can use things that are
// registered in the container by anybody.
public class TestModuleInstaller : IWindsorInstaller
{
public void Install(IWindsorContainer container,
IConfigurationStore store)
{
container
.Register(Component
.For<IMyService>()
.ImplementedBy<MyServiceThatDoesSomething>());
}
}
public class MyServiceThatDoesSomething : IMyService
{
private readonly IPrintService _printService;
public MyServiceThatDoesSomething(IPrintService printService)
{
_printService = printService;
}
public void DoSomething()
{
// Use the print service!
_printService.Print();
}
}
Finally compile everything and copy the test module to the same folder as the main application and then from the main you can do this:
Container.Resolve<IMyService>().DoSomething();
And then the magic happens! Well, some code runs and you find that the print service is called by the class from the module even though it knows nothing about it.
Anyway, maybe that helps a little bit, maybe not, good luck!