1. Introduction
The Springfox suite of java libraries are all about automating the generation of machine and human readable specifications for JSON APIs written using the spring family of projects. Springfox works by examining an application, once, at runtime to infer API semantics based on spring configurations, class structure and various compile time java Annotations.
1.1. History
Springfox has evolved from a project originally created by Marty Pitt and was named swagger-springmvc. Much kudos goes to Marty.
1.2. Goals
-
To extend support for a number of the evolving standards targeted at JSON API specification and documentation such as: swagger, RAML and jsonapi.
-
To extend support for spring technologies other than spring webmvc
-
Philosophically, we want to discourage using (swagger-core) annotations that are not material to the service description at runtime. For e.g. the jackson annotations should always trump or have more weight than
@ApiModelProperty
or for e.g.@NotNull
or specifying @RequestParam#required should always win. Annotations are to to be used only to supplement documentation or override/tweak the resulting spec in cases where its not possible to infer service/schema characteristics.
1.3. What it’s not
Endorsed or approved by the Spring Framework Contributors
1.4. Development Environment
-
File >> open >> build.gradle
-
Make sure to check the 'use the default gradle wrapper' option.
-
First time build
./gradlew cleanIdea idea
-
To get more output from any gradle commands/tasks append a
-i
(info) or-d
(debug) e.g.
./gradlew build -i
-
To publish to local maven repository
./gradlew clean build publishToMavenLocal -i
This build is optimized for releasing software to bintray/sonatype. In order for gradle to figure out the version the gradle plugin relies on local folder being a cloned git repository. Downloading the source archive and building will NOT work! |
1.4.1. Pre-Commit Build
-
Code quality (code coverage, checkstyle)
./gradlew check
1.4.2. Building reference documentation
To view the docs in a browser run:
./gradlew docs
When frequently generating the docs use the Gradle daemon as follows
./gradlew asciidoc --daemon
1.4.3. CI Environment
Circle CI
1.5. Releasing
To release a non-snapshot version of Springfox:
-
Execute the the release commands: The below properties are required to run a release:
-
GITHUB_TOKEN
-
BINTRAY_USERNAME
-
BINTRAY_PASSWORD
Recommend using [autoenv](https://github.com/kennethreitz/autoenv) with a .env
file at the root of the repo.
./gradlew release publishDocs -PbintrayUsername=$BINTRAY_USERNAME -PbintrayPassword=$BINTRAY_PASSWORD
-PreleaseType= -i
The release steps are as follows: - check that the git workspace is clean - check that the local git branch is master - check that the local git branch is the same as origin - gradle test - gradle check - upload (publish) all artifacts to Bintray - Bumps the project version in version.properties
- Git tag the release - Git push
1.5.1. Snapshot
This is normally done by the CI server
./gradlew snapshot -PbintrayUsername= -PbintrayPassword=
1.5.2. Override deploy
To bypass the standard release flow and upload directly to bintray use the following task - manually set the version in version.properties
./gradlew clean build bintrayUpload -PbintrayUsername=$BINTRAY_USERNAME -PbintrayPassword=$BINTRAY_PASSWORD -PreleaseType=
--stacktrace
1.5.3. Updating documentation
To update the docs for an existing release pass the updateMode
switch
./gradlew publishDocs -PupdateMode
1.5.4. Contributing
Please see the wiki for some guidelines
1.6. Support
If you find issues or bugs please submit them via the Springfox Github project
2. Getting Started
2.1. Dependencies
The Springfox libraries are hosted on bintray and jcenter. The artifacts can be viewed accessed at the following locations:
-
Release:
-
https://jcenter.bintray.com/io/springfox/
-
http://jcenter.bintray.com/io/springfox/
-
-
Snapshot
-
http://oss.jfrog.org/simple/oss-snapshot-local/io/springfox/
-
http://oss.jfrog.org/oss-snapshot-local/io/springfox/
-
Springfox has multiple modules and the dependencies will vary depending on the desired API specification standard. Below outlines how to include the springfox-swagger2 module which produces Swagger 2.0 API documentation.
2.1.1. Gradle
Release
repositories {
jcenter()
}
dependencies {
compile "io.springfox:springfox-swagger2:2.6.1"
}
Snapshot
repositories {
maven { url 'http://oss.jfrog.org/artifactory/oss-snapshot-local/' }
}
dependencies {
compile "io.springfox:springfox-swagger2:2.6.2-SNAPSHOT" }
2.1.2. Maven
Release
jcenter-snapshots
jcenter https://jcenter.bintray.com/ io.springfox springfox-swagger2 2.6.1
Snapshot
jcenter-snapshots
jcenter http://oss.jfrog.org/artifactory/oss-snapshot-local/ io.springfox springfox-swagger2 2.6.2-SNAPSHOT
2.1.3. Springfox-swagger2 with Spring MVC and Spring Boot
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 |
/*
*
* Copyright 2015 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
package springfox.springconfig;
import com.fasterxml.classmate.TypeResolver;
import org.joda.time.LocalDate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.context.request.async.DeferredResult; import springfox.documentation.builders.PathSelectors; import springfox.documentation.builders.RequestHandlerSelectors; import springfox.documentation.builders.ResponseMessageBuilder; import springfox.documentation.builders.ParameterBuilder; import springfox.documentation.schema.ModelRef; import springfox.documentation.schema.WildcardType; import springfox.documentation.service.ApiKey; import springfox.documentation.service.AuthorizationScope; import springfox.documentation.service.SecurityReference; import springfox.documentation.service.Tag; import springfox.documentation.spi.DocumentationType; import springfox.documentation.spi.service.contexts.SecurityContext; import springfox.documentation.spring.web.plugins.Docket; import springfox.documentation.swagger.web.ApiKeyVehicle; import springfox.documentation.swagger.web.SecurityConfiguration; import springfox.documentation.swagger.web.UiConfiguration; import springfox.documentation.swagger2.annotations.EnableSwagger2; import springfox.petstore.controller.PetController; import java.util.List; import static com.google.common.collect.Lists.*; import static springfox.documentation.schema.AlternateTypeRules.*; @SpringBootApplication @EnableSwagger2 @ComponentScan(basePackageClasses = { PetController.class }) public class Swagger2SpringBoot { public static void main(String[] args) { ApplicationContext ctx = SpringApplication.run(Swagger2SpringBoot.class, args); } @Bean public Docket petApi() { return new Docket(DocumentationType.SWAGGER_2) .select() .apis(RequestHandlerSelectors.any()) .paths(PathSelectors.any()) .build() .pathMapping("/") .directModelSubstitute(LocalDate.class, String.class) .genericModelSubstitutes(ResponseEntity.class) .alternateTypeRules( newRule(typeResolver.resolve(DeferredResult.class, typeResolver.resolve(ResponseEntity.class, WildcardType.class)), typeResolver.resolve(WildcardType.class))) .useDefaultResponseMessages(false) .globalResponseMessage(RequestMethod.GET, newArrayList(new ResponseMessageBuilder() .code(500) .message("500 message") .responseModel(new ModelRef("Error")) .build())) .securitySchemes(newArrayList(apiKey())) .securityContexts(newArrayList(securityContext())) .enableUrlTemplating(true) .globalOperationParameters( newArrayList(new ParameterBuilder() .name("someGlobalParameter") .description("Description of someGlobalParameter") .modelRef(new ModelRef("string")) .parameterType("query") .required(true) .build())) .tags(new Tag("Pet Service", "All apis relating to pets")) .additionalModels(typeResolver.resolve(AdditionalModel.class)) ; } @Autowired private TypeResolver typeResolver; private ApiKey apiKey() { return new ApiKey("mykey", "api_key", "header"); } private SecurityContext securityContext() { return SecurityContext.builder() .securityReferences(defaultAuth()) .forPaths(PathSelectors.regex("/anyPath.*")) .build(); } List |