Swagger: how to combine shared information from different APIs - java

I am adding swagger 1.5.0 support to an existing java application that implements 20+ different REST APIs and uses Jersey 1.17.1 with package scanning. Does anyone have any best practice recommendations? For example:
Should swagger definitions be added to each java class or can they be
added to an independent file(s) to avoid touching each class?
Each API requires the same set of headers which I have defined in great details for the first class using #ApiImplicitParam. Instead of
repeating that information for every operation of every class, is
there a way to apply it to all APIs?

There are a zillion ways to integrate the swagger 1.5.x libraries (note: 1.5.10 is latest) with a JAX-RS application. I suggest you follow a scheme like in the swagger-petstore and split the files by top-level path segments, which should provide a logical organization.
For repeated headers, you can have each resource class extend a base class which has an annotated class-level variable. That will apply to each operation in the classes that extend it.

Related

How to prohibit usage of classes with certain annotation

In our organizations we've got several microservices and lots of libraries.
Some libraries define "public" classes that are not intended for public usage - only inside library in multiple packages (thus can't be package-private)
I'd like to add something similar to Kotlin's "internal" modifier - a checkstyle rule/annotation processor/test component that verifies that consumer applications don't import these classes.
for example, I will mark them as #ForInternalUsageOnly or put into package com.ourorg.mylib.internal_usage
what can be a non-copy-pasted (e.g. a jar or a gradle task) implementation that verifies that such classes are not imported? Preferably - on compilation level
It sounds like you should be using the Java 9+ module feature, and its ability specify what classes are exposed outside of a given module.
Here are some references to get you started:
Understanding Java 9 Modules
A Guide to Java 9 Modularity
and there are lots of tutorials and videos.
While it should be possible to do what you propose using annotations and a checker, I can't recommend any practical examples.
You can achieve something like this with ArchUnit easily, your ArchRule would be something like -
#ArchTest
public static final ArchRule customArchRule = noClasses()
.should()
.dependOnClassesThat()
.areAnnotatedWith(ForInternalUsageOnly.class);
Assuming you are using it with JUnit 5 or 4, classes in noClasses() are determined by #AnalyzeClasses, you can read more about setting up and using ArchUnit from here.

Intercept whole class with Java standard features

I want to intercept a whole class with java standard features, because i am not allowed to add new dependencies to the project (websphere 85).
I want to call a function, which does multiple api calls (swagger generated) for example myapi.bla(), myapi.blabla(), etc and get the headers from the response.
I thought about intercepting all methods of the class "myapi" and then access the headers (myapi.getApiClient.getResponseheaders).
Do you know how to intercept all methods of a class with java or websphere85 built in features?
Thank you!
There are prominently 2 ways to achieve this,
AOP, you can use AspectJ to achieve this which basically modifies the class to inject interceptions, either at compile or load time. Example.
Dynamic Proxy. A good explanation on how to use it with example. Though it comes with a performance cost.

Classloader problem with JAXB internal implementation interface com.sun.xml.bind.namespacePrefixMapper

I need help for the following problem: I use Websphere Liberty 19.0.0.9 with Oracle and IBM Java 1.8 an run an older application (EAR) containing an EJB, which serializes XML with JAXB. The application needs to control XML namespace definitions and prefixes and does this by providing an implementation of com.sun.xml.bind.namespacePrefixMapper to javax.xml.bind.Marshaller.setProperty with property "com.sun.xml.bind.namespacePrefixMapper".
At runtime the error java.lang.NoClassDefFoundError: com/sun/xml/bind/marshaller/NamespacePrefixMapper occurs when loading the implementation class.
The server.xml contains feature javaee-8.0, and the liberties’ JAXB implementation wlp-19.0.0.9\lib\com.ibm.ws.jaxb.tools.2.2.10_1.0.32.jar contains the class com.sun..xml.bind.marshaller.NamespacePrefixMapper.
I tried to solve it by putting the jaxb-impl-2.2.4.jar to the EAR/lib (which is the wrong way because JAXB is provided by JEE) but then an error occurred in the com.sun.xml.bind.v2.runtime.MarshallerImpl.setProperty(MarshallerImpl.java:511) because the check if(!(value instanceof NamespacePrefixMapper)) failed, because the Classloader (AppClassLoader) of the implementation provided another class object for class NamespacePrefixMapper than the MarshallerImpls’ classloader (org.eclipse.osgi.internal.loader.EquinoxClassLoader). But this showed that the liberty can access the the NamespacePrefixMapper.
I made several attempts to use the same classloader for the implementation and the MarschallerImpl when loading them, and I tried to solve it by classloder settings in the server.xml. No success.
I know that it is not recommended to use such JAXB implementation specific classes, but the application was developed this way and cannot be changed easily.
Any help is appreciated which tells me how to convince liberty to either provide the NamespacePrefixMapper class to the application classloader, or to use the application classloaders NamespacePrefixMapper also in the MarschallerImpl.
Thank you.
//The implementation class looks for example like this:
public class MyNamespacePrefixMapperImpl extends com.sun.xml.bind.marshaller.NamespacePrefixMapper {...}
JAXBContext c = JAXBContext.newInstance(some mapped class);
Marshaller m = c.createMarshaller();
com.sun.xml.bind.marshaller.NamespacePrefixMapper mapper = new MyNamespacePrefixMapperImpl();// Here the NoClassDefFoundError occurs.
m.setProperty("com.sun.xml.bind.namespacePrefixMapper", mapper); // Here the instanceof check fails if jaxb-impl.jar is in EAR/lib.
this is a precarious situation without an easy solution. Liberty attempts to "hide" internal packages to avoid scenarios where users want a slightly different version of the implementation than what the framework provides - the most glaring example of this problem was in traditional WAS where users wanted to use a different version of Jakarta Commons Logging than what was shipped with WAS - this required users to provide their own, either in an isolated shared library, or use other parent-last classloading hacks to make it work. Liberty avoids those issues by isolating the internal implementations from the user applications.
So that works great when a user wants to use a different version of a third party library than what Liberty provides, but as you have discovered, that doesn't work so great when your legacy application depends on those hidden/isolated third party libraries.
The most ideal solution would be to refactor the application code so as to not depend on internal JAXB classes - somebody with more JAXB expertise may be able to help with this... But it sounds like that may not be feasible, so another alternative would be to create a user feature. A user feature is essentially an extension to Liberty's runtime - so it has access to packages that user applications do not. It also allows you to add packages as APIs for the user applications - so you could use a user feature to add the com.sun.xml.bind.marshaller as a public API - then your user application could extend it freely. You could also include your MyNamespacePrefixMapperImpl class in your user feature and register it there so that it would automatically apply to all applications in your server.
You can find more information on user features here:
https://www.ibm.com/support/knowledgecenter/en/SSEQTP_liberty/com.ibm.websphere.wlp.doc/ae/twlp_feat_example.html
Hope this helps, Andy

Documenting existing JAX-RS implementation with Swagger without annotating it

I would like to generate the Swagger documentation for an existing JAX-RS implementation without having to modify my code at all. I'd love not to have to introduce any kind of Swagger annotations decorating my classes.
Here
https://github.com/swagger-api/swagger-core/wiki/Swagger-Core-JAX-RS-Project-Setup-1.5.X.
they seem to suggest that after configuring your application to use Swagger you have to annotate your code for swagger to be able to generate swagger.json. Am I right? Are annotations needed? If not, I don't understand very well their purpose
Is this magic of documenting your existing JAX-RS application without modifying you code possible?
I've found this http://www.adam-bien.com/roller/abien/entry/jax_rs_get_swagger_json.
Could this be a solution?
Swagger annotations are required to add the documentation to your JAX-RS implementation. The purpose is to define your API operations and parameters, what is their meaning and purpose.
The link you shared appears to be some sort of a hack mechanism. But i don't see how any code can find out the intent of your API unless you explicitly declare it.
If you need to minimize swagger annotation usage, there are 2 ways to do this:
Only use #Api at class level and do not use method level annotations. This will render a basic swagger.json with a listing of your GET/POST etc APIs.
Write an interface and use annotations here. You API class needs to just extend this interface then. This will reduce impact on your existing class.
Hope this helps.

Tool to identify Java annotations in various Java APIs

I'm trying to identify places where annotation names are the same or similar to compile a list of these things to make sure our team knows where possible points of confusion can be found. For example, Guice #provides and RESTeasy #provider are similar enough in spelling but different enough in semantics as to confuse people so I'd like to call that out explicitly and explain the differences.
What I'm looking for is a tool or even a website that enumerates the annotations associated with packages. This might be a pipe dream, but before I manually start going through and collecting these things I thought I'd check.
I was considering writing one based on Javadoc that simply only pulled in the annotations but I don't have access to Java source files in many cases.
Any thoughts or suggestions?
In Eclipse you can use the standard method "Search for references" (context menu of a used annotation References -> Project) and you are getting a list where the annotations is used within your project.
I suggest to scan for annotations yourself and generate a list for that.
You can do that by writing your own implementation of an annotation processer, i.e. extend AbstractProcessor. Within this processor you can write a text file containing all Annotations. You can add this processor to your build procedure, then it will execute the processor when you build the project.
Another way to do this is using the Google Reflections library. This might be a bit more work since you would need to write a small programm to fetch the annotations and write the file.
I wrote such a tool: https://github.com/MoserMichael/ls-annotations
it decompiles the byte code and lists declarations (classes, functions, variables) with annotations only. You can also use it to find all classes/interfaces derived from a given class/inerface - and all the classes/interfaces derived from a given class/interface.
The tool uses the asm library to scan class files and to extract annotations. it can detect annotations with retention policy CLASS and RUNTIME. It can't detect annotations with retention policy SOURCE that are not put into bytecode, for example #Override is one of these.
Why not scanning your classpath and export all used annotations? Then just use some simple parsing / text compare to see the elements with almost the same name?

Categories