Doing API-First development
When generating a JHipster application, you can choose the API first development using OpenAPI-generator
option when prompted for additional technologies.
This option will configure your build tool to use OpenAPI-generator to generate API code from an OpenAPI (Swagger) definition file.
Both Swagger v2 and OpenAPI v3 formats are supported.
Rationale for API-First development
In API first development, instead of generating the documentation from the code, you need to write the specification first and then generate code from it. This has the following advantages:
- You can design your API for the consumers and not as a consequence of your implementation.
- You can use the specification file to mock your new server endpoints before they are released so you can more easily decouple frontend and backend development.
- You don’t need a live server to use your OpenAPI documentation.
Using the OpenAPI-generator plugins
The OpenAPI specification file will be located at src/main/resources/swagger/api.yml and is used to generate endpoint interfaces that you can implement.
Those interfaces have default methods which answer with a 501 Not implemented
HTTP status and an empty body.
Write your specification using a tool such as swagger-editor, put it in src/main/resources/swagger/api.yml
, then run:
./mvnw generate-sources
Or for gradle:
./gradlew openApiGenerate
Then implement the “Delegate” interfaces generated in ${buildDirectory}/generated-sources/openapi/src/main/java/${package}/web/api/
with @Service
classes.
Example of code to write yourself for the famous petstore:
@Service
public class PetApiDelegateImpl implements PetApiDelegate {
@Override
public ResponseEntity<List<Pet>> findPetsByStatus(List<String> status) {
return ResponseEntity.ok(
status.stream()
.distinct()
.map(Pet.StatusEnum::fromValue)
.map(statusEnum -> new Pet().id(RandomUtils.nextLong()).status(statusEnum))
.collect(Collectors.toList())
);
}
}
If you provide the NativeWebRequest
bean to the delegate interface, then basic example bodies will be returned for the methods that have not been overridden (still with a 501 HTTP status code).
This is useful to mock your endpoints before providing the actual implementation.
@Service
public class PetApiDelegateImpl implements PetApiDelegate {
private final NativeWebRequest request;
public PetApiDelegateImpl(NativeWebRequest request) {
this.request = request;
}
@Override
public Optional<NativeWebRequest> getRequest() {
return Optional.ofNullable(request);
}
}
Then you can get the examples
$ curl -X GET --header 'Accept: application/json' 'http://localhost:8080/v2/pet/findByStatus?status=pending'
{ "photoUrls" : [ "photoUrls", "photoUrls" ], "name" : "doggie", "id" : 0, "category" : { "name" : "name", "id" : 6 }, "tags" : [ { "name" : "name", "id" : 1 }, { "name" : "name", "id" : 1 } ], "status" : "available"}%
$ curl -X GET --header 'Accept: application/xml' 'http://localhost:8080/v2/pet/findByStatus?status=pending'
<Pet> <id>123456789</id> <name>doggie</name> <photoUrls> <photoUrls>aeiou</photoUrls> </photoUrls> <tags> </tags> <status>aeiou</status></Pet>%