Why Apiator?
In our team we prefer to use tools that make life of developer easier. Apiator is one of them. It helps you to build entire API documentation with minimal configuration.
The motivation is to take information about API usage directly from a source code and spend as little as possible time and lines of code to describe your API.
Of course it’s difficult to predict all of the possible cases of API frameworks configuration so our second goal is high configurability. You can override or extends almost every functionality of Аpiator with help of type safe configuration code (not a configuration file)!
Getting started
Apiator is built with JDK 11 so it’s minimum required api level of source code and build tool-chain
Getting a binary
Binary artifacts are hosted on Bintray repo https://dl.bintray.com/ainrif/maven
You can use Set Me Up!
guide from Bintray repo
Configuration
The main class of apiator is Apiator
😉 and it can be configured via ApiatorConfig
By default ApiatorConfig
is set up to search for classes annotated with com.ainrif.apiator.api.annotation.Api
.
So you must select only type of web service provider and type of renderer, f.e.:
ApiatorConfig config = new ApiatorConfig();
config.provider = new JaxRsProvider();
config.renderer = new CoreHtmlRenderer();
String html = new Apiator(config).render();
The result string will be a html
which is "all in one" document so you can save it and serve from http server as is.
Note
|
More examples of configuration can be found at corresponding *SmokeSpec
|
How to run with …
Apiator can be used as a library in a classpath of application that you need to document. Good choice is to incorporate apiator into your build process to deliver documentation with application together.
Gradle plugin
Minimum requirement - Gradle 5.3
The Apiator Gradle plugin is published in the same repo with apiator.
So you have to add it to build script classpath in root build.gradle
:
buildscript {
repositories {
maven { url "https://dl.bintray.com/ainrif/maven" }
}
dependencies {
classpath 'com.ainrif.apiator:apiator-gradle-plugin:<apiator-version>'
}
}
apply plugin: 'com.ainrif.apiator'
After it you can configure Apiator in the required module (which classpath contains all endpoints):
apiator {
runnerClass = 'path.to.ApiatorRunner' // (1)
}
-
full name of the class which implements
ApiatorGradleRunner
and have default (or zero-arg) constructor
Class which implements ApiatorGradleRunner
will created and call for documentation generation.
In implemented method ApiatorGradleRunner#execute(…)
you have to configure and run Apiator.
Note
|
Complete configuration examples can be found at testing-gradle-plugin module in classes
TestingJavaPluginApiatorConfig for Java and TestGroovyPluginApiatorConfig for Groovy
|
To separate the dependencies of Apiator from project dependencies the additional Gradle SourceSet can be used.
apiator
SourceSet have its own classpath which extends main
can be configured via apiatorCompile
in gradle.
See the build.gradle
file of testing-gradle-plugin
module.
As a library
Apiator can be used as a standard library.
Everything you need is to download all necessary libraries and run them in the same classpath
with you endpoint classes.
Note
|
If you need to extend classpath at runtime you can do it with incubating functionality Apiator#setExtraClassPath(URL[]) .
Extra classpath will be available during scanning and javadoc parsing.
|
Features overview
-
Zero additional code for basic documenting
An annotations configuration of web-frameworks (like jax-rs or micronaut) is quite good basic description of your API. We just deliver it in a different way.
-
Static generation (doesn’t affect you production code)
You documentation can be generated during the build and can be deployed separately of your project. Or not (up to you)
-
JSON representation
All parsed API can be represented as reproducible JSON. You can store it in VCS (like git) and watch the difference between versions (go to detailed description):
-
HTML representation
In a few moments you API will converted into human friendly page (go to detailed description):
-
JavaDoc processing
Extend you Api information with native JavaDoc support. Now you documentation is served directly from you api classes
-
Single file HTML representation
All images and scripts are incorporated in one file which can be open in any browser of even sent via e-mail
-
And much more in the future :)
Understanding of changelog
The entire list of changes and feature can be found in repository
The semantics of changelog records is:
-
new : for the new features
-
fix : for fixed issues
-
update : for changes or extensions of public api and configurations
-
improvement : for internal updated and performance tweaks
User Guide
Default representation of Apiator collected data is class ApiScheme. It contains all API method (with class hierarchy) and meta information from annotations (from provider) and JavaDoc. It’s difficult to use such data in a raw view therefore there are renderers.
Let’s look at the following example (written on groovy to reduce amount of lines):
Apiator apiator = new Apiator(
new ApiatorConfig(
basePackage: 'com.ainrif.apiator.test.model.jaxrs.smoke',
provider: new JaxRsProvider(),
renderer: new CoreHtmlRenderer({
plugins << new JaxRsCompositePlugin()
}),
docletConfig: new DocletConfig(includeBasePackage: 'com.ainrif')
)
)
This code configuration uses:
-
Provider which understands jax-rs frameworks,
-
Render which produces html view for api
-
Plugin for renderer that adds special model types for jax-rs frameworks
-
Doclet support and required base package to scan.
Note
|
For additional configuration params you can look at configuration classes and read the doc. Available components are described in corresponding chapters of current doc. |
How it works
This part contains high level description of major Apiator features and mechanics
Introspection
When Apiator starts to work it scans your source code in search of known web services configurations. The information is collected from source code like:
-
used classes in request as params
-
types of response as a return value
-
specific annotations
-
hierarchy of classes
-
JavaDoc descriptions
Such process when source code tells about itself are called introspection. In this case we don’t expect any specific information for Apiator.
There are several introspection types:
-
on classes — when Apiator retrieves information like properties (based on accessibility, i.e. on public getters, setters and fields) or templates (checking class hierarchy and generics).
-
on web service provider — if web services provider uses annotations for configuration then Apiator will use them to get info about endpoints.
-
on JavaDoc — we collect JavaDoc and attach them everywhere it is possible :)
Core annotations
Annotation can be found in module api
and can be used fot providing of additional information or for the overrides.
Available annotations:
-
Api - marker is used to highlight classes to scans
-
ConcreteTypes - overrides return value from endpoint method
-
Param - set additional meta about param usage
JavaDoc support
Apiator can gather some information from your JavaDoc comments. With help of it you can provide description for your Api Contexts (classes), Endpoints (methods) and Params (method arguments).
There are two modes:
-
set paths to sources manually (the fastest one for the huge projects with a lot of source roots)
-
auto-search according to found Api classes (default, suitable for small projects with small depth of nested modules)
Providers
Providers have knowledge about web frameworks and their dsl.
Providers implement WebServiceProvider
and return data about methods which represent API endpoints
JaxRsProvider
JAX-RS specification describes in some details how your REST endpoints should look like. This information is stored in many annotations across your application. We just collect it together and add some data from implementation.
In some cases it’s difficult to use only JAX-RS api.
F.e. when you return javax.ws.rs.core.Response
as a result content can be any.
To solve such cases we provide Apiator api
module which can clarify implementation details.
MicronautProvider
This provider is built as integration with Micronaut Framework. Micronaut provides api and libraries to build REST-like microservices.
Currently Apiator supports only routing and API declarations built via annotations described in the documentation
Renderers
Renderers describe how does Apiator output should look. In general renderers are transformers from internal Apiator scheme to something like JSON, XML, HTML, etc.
Core JSON renderer
This renderer is a JSON representation of internal Apiator Schema.
It can be used as input source data for other renderers (like HTML Renderer)
or for comparison of different api versions.
The result output can be customized with Plugins
Model description
The top level of resulting JSON represents next data:
-
apiContexts - list of all contexts that were found (usually coincides with the class in java)
-
apiatorInfo - technical information about Apiator version and settings
-
clientApiInfo - additional information provided by Api creator
-
usedApiTypes - list of business domain objects
-
usedEnumerations - list of enums (sets of string constants)
JSON Representation of Api Type
Note
|
Api Type - the common abstraction for all the complex types (not : STRING , LONG , ARRAY … )All Api Types which are used as params or return types obey the Model Type abstraction |
Basic structure of Api Type includes only two fields
-
modelType - one of Model Type set
-
type - string with Api Type name (only if modelType is
OBJECT
)
Additional fields of Api Type are used for Templates Types (aka Java Generics)
-
basedOn - array of Templates, structure of nested objects is also Template Type
-
templateName - name of template variable used in source code
Note
|
Many of others Types inherit the Template type structure |
Api Context
Note
|
JSON fields with value null are omitted in result output. They are presented in the next example only in demo purpose.
|
{
"apiContexts": [
{
"apiEndpoints": [
/*...*/
{
"description": "Method level javadoc",
"method": "GET", // (1)
"name": "getAuthors", // (2)
"params": [ // (3)
{
"basedOn": [], // (4)
"description": "Param level javadoc",
"defaultValue": null,
"httpParamType": "QUERY",
"index": 0,
"modelType": "STRING",
"name": "search",
"templateName": null,
"type": null
}
],
"path": "/", // (5)
"returnTypes": [{
"basedOn": [ // (4)
{
"basedOn": [],
"modelType": "OBJECT",
"templateName": null,
"type": "org.example.library.Author"
}
],
"modelType": "ARRAY",
"templateName": null,
"type": null
}]
},
/*...*/
],
"apiPath": "/library", // (6)
"description": "Some info from JavaDoc",
"name": "org.example.library.controllers.LibraryController"
},
/*...*/
]
/*...*/
}
-
name of HTTP method to call this endpoint
-
handler name in a source code
-
available parameterization for this endpoint
-
template type information (like Generics in Java)
-
path to endpoint related to context path (6)
-
prefix path to the endpoint
Used Api Types and Enumerations
Example of JSON representation:
{
"fields": [
{
"basedOn": [],
"modelType": "LONG",
"name": "id",
"readable": true,
"writable": false
},
{
"basedOn": [],
"modelType": "STRING",
"name": "firstName",
"readable": true,
"writable": true
},
/*...*/
],
"modelType": "OBJECT",
"type": "org.example.library.Author"
}
readable/writable
mean that server have getters / setters for those fields (or they are public in java terms)
Enumeration is kind of Api type:
{
"modelType": "ENUMERATION",
"type": "org.example.library.Book$Status",
"values": [
"PUBLISHED",
"DRAFT",
"REPRINT"
]
}
Model Type
Model Types are Apiator internal types which exists to classify every processed object
ModelType | Example | Description |
---|---|---|
|
|
correspond to native JDK types |
|
|
describe different types of collections |
|
|
custom types which can be represented as well known format |
|
|
class which describes inheritors of |
|
|
this model type is used for custom classes which are exposed via API as part of interface. Such classes will be introspected recursively to determine types of their fields |
|
|
this type means Apiator cannot get useful info about such class. It is type for general classes. |
|
|
internal type. Is used to show that given class shouldn’t be introspected. If such type have appeared in you documentation in most cases it means you API exposes some language dependent internals |
Plugins
Plugins are generic mechanism to extend and override Core JSON Renderer behavior.
All plugins implement CoreJsonRendererPlugin
interface and can be combined in CompositePlugin
for ease of use.
Note
|
Plugins with suffix *CompositePlugin contain all available plugins with it’s prefix .
I.E.: JaxRsCompositePlugin contains JaxRsModelTypePlugin, JaxRsParamPlugin…
|
ModelTypePlugin
These plugins encapsulate the logic of classes to Model Types matching. The matching goes while Model Type wouldn’t be found or plugins run out. From one plugin to another along the chain.
The ModelTypePlugin
interface contains only one method returning whether ModelType
or null
.
If plugin returns null
next plugin will be used.
Note
|
The order of this type of Plugins is important. So non-default plugins are processed first, i.e. in LIFO order of addition |
The plugins are ON by default DefaultModelTypeCompositePlugin
:
-
AnyModelTypePlugin
-
CollectionsModelTypePlugin
-
BinaryModelTypePlugin
-
OldDateModelTypePlugin
-
CoreJavaModelTypePlugin
-
Jsr310ModelTypePlugin
And some custom plugins which can be used to extend amount of known types
-
JaxRsModelTypePlugin
PropertyPlugin
This type of plugin allows to customize fields representation of model objects. By default Properties are public fields and properties in terms of JavaBeans (get* & set* methods)
Available Plugins:
-
JacksonPropertyPlugin - support Jackson property annotations
ParamPlugin
ParamPlugins
allows to extend information about endpoint param (like default value or optional).
Available Plugins:
-
JaxRsParamPlugin - supports
@DefaultValue
Core HTML renderer
Reference HTML representation of Apiator results. This renderer produces the most complete graphic interface according to core model. Html Render extends configuration from Json Renderer with path to output file.
Interface description

-
Fuzzy search
-
List of Endpoints
-
Menu with used Api Types
-
Card of Endpoint (detailed view)
Card of Endpoint
Show generic information about http endpoint and provides navigation links

Development Guide
Requirements:
-
Gradle 5.3 to build apiator plugin
-
JDK 11 to build and test all Apiator modules
-
Node.js 10 to develop Core Html Renderer
Core HTML renderer
The package.json
is located in source root of html renderer view - renderer/core-html-renderer/src/main/node
.
To run dev version on http://localhost:1234 execute next commands:
; npm i
; npm run dev
Html renderer is based on Json Render so there is a prepared dataset (json) which represents all features available in Apiator.
It’s located at renderer/core-html-renderer/src/main/node/apiator/js/apiatorJsonStub.js
and is used by default in dev mode.
There is a task from root gradle project to regenerate this json:
; # use wrapper version according to your OS
; ./gradlew generate_stub
The generated stub can be committed into the repo as is without additional formating to keep history of changes.