Existing frameworks such as Swagger and APIDOC provide much more features and overall a lot more sophisticated. This project aims to simplify API documentation to meet specific and opinionated goals and use cases - mainly for internal APIs.
Plain Old Java API (POJA) Documentation is a simplified (and opinionated) approach to documenting Java-based APIs. The primary goal is to provide a "vanilla Java" library and Gradle Plugin for developers to document their APIs outside of Javadoc without any overhead of additional COTs dependencies.
It provides a set of annotations similar to Swagger but only adopts relevant attributes for intended use cases. The core logic uses reflection to detect these annotations from compiled classes and generate output API doumentations in json format. Other formats and documentation logic can be extended via the PojaDocumentation
interface specifications and can be configured via the Gradle pojadoc
task.
// build.gradle
buildscript {
repositories {
mavenLocal()
}
dependencies {
classpath 'poja:poja-gradle-plugin:0.2'
}
}
apply plugin: 'java-library'
apply plugin: 'pojadoc'
pojadoc {
// default if not set; otherwise, your own custom PojaDocumentation implementation
documentationType = 'poja.core.DefaultDocumentation'
// default potential implementations to look for, if not set
potentialImplementations = ['javax.ws.rs', 'org.springframework.web.bind.annotation']
// default output pojadoc output directory, if not set
docOutputDir = "${project.buildDir}/pojadoc"
// default if not set; any class that cannot be processed through reflection due to dependencies issues will be ignored
ignoreNoClassDefFoundError = true
}
Documenting API implementations involves two annotations @Api
and @ApiOperation
. Unlike Swagger, documentation details are all captured within each annotation and not outside, i.e. within implementation methods, method parameters, method body, etc.
Annotation @Api
1. name: API name/identifier
2. description: Short description
3. value: The API root path value
3. url: Additional details can be externally linked (i.e. to javadoc, confluence, etc)
Example
@RestController
@Api(name = "poja", value = "/poja", description = "POJA Annotation Test Endpoint")
public class PojaEndpoint {}
Annotation @ApiOperation
1. path: Operation full path
2. description: Short description
3. produces: String[] Allowable formats this operation supports
4. methods: String[] HTTP methods that this operation supports
5. url: Additional details can be externally linked (i.e. to javadoc, confluence, etc)
6. parameters: ApiParam[] Parameters into this operation includes url parameters, request body, header attributes
Example
@ApiOperation(path = "/info", methods = { "GET" }, produces = { "test/plain" } )
@RequestMapping(value = "/info", method = { RequestMethod.GET }, produces = { "test/plain" })
public String info() {}
Annotation @ApiParam
, parameters to an API operation can be located in the URL path, the request body, or in header attributes.
1. name: Parameter name
2. description: Short description
3. location: url, body, header attribute
4. type: Paramter class type, default to String
5. url: Additional details can be externally linked (i.e. to javadoc, confluence, etc)
6. required: Required for operation
Example
@ApiOperation(path = "/submit", methods = { "POST" }, url = "http:https://javadoc/poja-sumbit.html", parameters = {
@ApiParam(name = "model", location = "body", type = PojaModel.class, url = "http:https://javadoc/model/PojaModel.html")
})
@RequestMapping(value = "/submit", method = { RequestMethod.POST })
public void submit(PojaModel model) {}
# puts poja-core and poja-gradle-plugin to ~/.m2
gradle publishToMavenLocal
# builds sample project that uses the Gradle plugin from ~/.m2
gradle -b api/build.gradle :clean :pojadoc
# outputs the sample API
cat api/build/pojadoc/poja.json
There will be 3 different types of outputs if using the default documentationType
-
- Each API root will contain its own output files
undocumented.json
contains the potential API implementations that contain no documentationuncategorized.json
contains operations that are not tied to a root API
Sample API Endpoint
{
"value": "/poja",
"type": "",
"description": "POJA Annotation Test Endpoint",
"url": "",
"operations": [
{
"parameters": [
{
"required": true,
"type": "poja.test.api.PojaModel",
"url": "http:https://javadoc/model/PojaModel.html",
"location": "body",
"name": "model"
}
],
"consumes": null,
"produces": null,
"description": "",
"methods": [
"POST"
],
"url": "http:https://javadoc/poja-sumbit.html",
"path": "/submit"
},
{
"parameters": [
],
"consumes": null,
"produces": [
"test/plain"
],
"description": "",
"methods": [
"GET"
],
"url": "",
"path": "/info"
}
],
"name": "poja"
}
Sample undocumented APIs
[
{
"value": "undocumented",
"type": "poja.test.api.PotentialJaxwsOperation",
"description": "Undocumented API",
"url": "",
"operations": [
],
"name": "undocumented"
},
{
"value": "undocumented",
"type": "poja.test.api.PotentialRestControllerOperation",
"description": "Undocumented API",
"url": "",
"operations": [
],
"name": "undocumented"
},
{
"value": "undocumented",
"type": "poja.test.api.PotentialJaxwsEndpoint",
"description": "Undocumented API",
"url": "",
"operations": [
],
"name": "undocumented"
},
{
"value": "undocumented",
"type": "poja.test.api.PotentialRestControllerEndpoint",
"description": "Undocumented API",
"url": "",
"operations": [
],
"name": "undocumented"
}
]
Sample uncategorized operations
[
{
"value": "uncategorized",
"type": "",
"description": "Uncategorized API: poja.test.api.UncategorizedPersonEndpoint",
"url": "",
"operations": [
[
{
"parameters": [
{
"required": true,
"type": "java.lang.String",
"url": "",
"location": "url",
"name": "userid"
}
],
"consumes": null,
"produces": null,
"description": "",
"methods": [
"POST"
],
"url": "http:https://javadoc/poja-sumbit.html",
"path": "/submit/{person}"
}
]
],
"name": "uncategorized"
},
{
"value": "uncategorized",
"type": "",
"description": "Uncategorized API: poja.test.api.UncategorizedEndpoint",
"url": "",
"operations": [
[
{
"parameters": [
{
"required": true,
"type": "java.lang.String",
"url": "",
"location": "url",
"name": "userid"
},
{
"required": true,
"type": "java.lang.String",
"url": "",
"location": "url",
"name": "ssn"
}
],
"consumes": null,
"produces": null,
"description": "",
"methods": [
"POST"
],
"url": "http:https://javadoc/poja-sumbit.html",
"path": "/submit/{userid}/{ssn}"
},
{
"parameters": [
{
"required": true,
"type": "java.lang.String",
"url": "",
"location": "url",
"name": "userid"
}
],
"consumes": null,
"produces": null,
"description": "",
"methods": [
"POST"
],
"url": "http:https://javadoc/poja-sumbit.html",
"path": "/submit/{userid}"
}
]
],
"name": "uncategorized"
}
]