OpenAPI System using standard REST controllers
Introduction
Ontimize OpenAPI Generator allows you to generate, from the interface files, the API code for standard REST controllers.
Prerequisites
There are 2 options to follow this tutorial, clone the repository with the initial state and follow the tutorial step by step, or download the final example and see which files are new and which have been updated.
Initial project
/$ git clone https://github.com/ontimize/ontimize-examples
/ontimize-examples$ cd ontimize-examples
/ontimize-examples$ git checkout boot-openapi-standard-controllers-initial
Final example
/$ git clone https://github.com/ontimize/ontimize-examples
/ontimize-examples$ cd ontimize-examples
/ontimize-examples$ git checkout boot-openapi-standard-controllers
To simplify the code being written, three dots (…) may appear in some parts of the code. This indicates that there may be previous code before and after those dots.
Steps
Add the OpenAPI module
We will add a new module to our project that will contain the API definition. Also this module will generate the Java interfaces that later we need to implement in our REST controllers.
Add the dependencies to the project
In the main pom.xml we need to add the new module and the Swagger dependencies:
pom.xml
...
<properties>
...
<swagger-annotations.version>1.6.2</swagger-annotations.version>
</properties>
<dependencyManagement>
<dependencies>
...
<dependency>
<groupId>com.ontimize</groupId>
<artifactId>projectwiki-openapi</artifactId>
<version>1.0.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
...
<modules>
<module>projectwiki-api</module>
<module>projectwiki-openapi</module>
<module>projectwiki-model</module>
<module>projectwiki-ws</module>
<module>projectwiki-boot</module>
</modules>
...
- ontimize-examples
- projectwiki-api
- src
- main
- java
- com
- ontimize
- projectwiki
- api
- core
- service
- IUserService.java
- service
- core
- api
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- projectwiki-boot
- src
- main
- java
- com
- ontimize
- projectwiki
- ServerApplication.java
- projectwiki
- ontimize
- com
- resources
- java
- main
- pom.xml
- src
- projectwiki-model
- src
- main
- db
- templateDB.txt
- java
- com
- ontimize
- projectwiki
- model
- core
- dao
- UserDao.java
- UserRoleDao.java
- service
- UserService.java
- dao
- core
- model
- projectwiki
- ontimize
- com
- resources
- dao
- placeholders.properties
- UserDao.xml
- UserRoleDao.xml
- dao
- db
- main
- pom.xml
- src
- projectwiki-openapi
- src
- main
- resources
- main
- pom.xml
- src
- projectwiki-ws
- src
- main
- java
- com
- ontimize
- projectwiki
- ws
- core
- rest
- MainRestController.java
- TestRestController.java
- UserRestController.java
- rest
- core
- ws
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- .gitignore
- pom.xml
- README.md
- projectwiki-api
Add the dependencies to the OpenAPI module
In the pom.xml of the OpenAPI module we need to add the following dependencies:
pom.xml
...
<dependencies>
...
<dependency>
<groupId>com.ontimize.jee</groupId>
<artifactId>ontimize-jee-server-rest</artifactId>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-annotations</artifactId>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>javax.annotation-api</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-validation</artifactId>
</dependency>
</dependencies>
...
- ontimize-examples
- projectwiki-api
- src
- main
- java
- com
- ontimize
- projectwiki
- api
- core
- service
- IUserService.java
- service
- core
- api
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- projectwiki-boot
- src
- main
- java
- com
- ontimize
- projectwiki
- ServerApplication.java
- projectwiki
- ontimize
- com
- resources
- application.yml
- java
- main
- pom.xml
- src
- projectwiki-model
- src
- main
- db
- templateDB.txt
- java
- com
- ontimize
- projectwiki
- model
- core
- dao
- UserDao.java
- UserRoleDao.java
- service
- UserService.java
- dao
- core
- model
- projectwiki
- ontimize
- com
- resources
- dao
- placeholders.properties
- UserDao.xml
- UserRoleDao.xml
- dao
- db
- main
- pom.xml
- src
- projectwiki-openapi
- src
- main
- resources
- main
- pom.xml
- src
- projectwiki-ws
- src
- main
- java
- com
- ontimize
- projectwiki
- ws
- core
- rest
- MainRestController.java
- TestRestController.java
- UserRestController.java
- rest
- core
- ws
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- .gitignore
- pom.xml
- README.md
- projectwiki-api
Add the API definition
Following the OpenAPI specification we will create the definition for the test controller (More information in this link):
openapi-rest.yml
openapi: 3.0.3
info:
title: projectwiki API
version: '1.0'
description: The projectwiki API
servers:
- url: '/'
description: Localhost
paths:
/test/test:
get:
operationId: testRest
tags:
- Test
summary: Test
description: >
Develop purposes only.
responses:
'200':
description: OK
content:
text/plain:
schema:
type: string
'400':
description: Bad request
'401':
description: Not found
'404':
description: Unauthorized
default:
description: Unexpected error
post:
operationId: postTest
tags:
- Test
summary: POST Test
description: >
Develop purposes only.
x-codegen-request-body-name: person
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Person'
examples:
Laura Bugle:
value:
name: 'Laura'
surname: 'Bugle'
responses:
'200':
description: OK
content:
text/plain:
schema:
type: string
'400':
description: Bad request
'401':
description: Not found
'404':
description: Unauthorized
default:
description: Unexpected error
components:
schemas:
Person:
type: object
properties:
name:
description: Name
type: string
surname:
description: Surname
type: string
securitySchemes:
BasicAuth:
type: http
scheme: basic
security:
- BasicAuth: []
- ontimize-examples
- projectwiki-api
- src
- main
- java
- com
- ontimize
- projectwiki
- api
- core
- service
- IUserService.java
- service
- core
- api
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- projectwiki-boot
- src
- main
- java
- com
- ontimize
- projectwiki
- ServerApplication.java
- projectwiki
- ontimize
- com
- resources
- application.yml
- java
- main
- pom.xml
- src
- projectwiki-model
- src
- main
- db
- templateDB.txt
- java
- com
- ontimize
- projectwiki
- model
- core
- dao
- UserDao.java
- UserRoleDao.java
- service
- UserService.java
- dao
- core
- model
- projectwiki
- ontimize
- com
- resources
- dao
- placeholders.properties
- UserDao.xml
- UserRoleDao.xml
- dao
- db
- main
- pom.xml
- src
- projectwiki-openapi
- src
- main
- resources
- public
- restapi
- openapi-rest.yml
- restapi
- public
- resources
- main
- pom.xml
- src
- projectwiki-ws
- src
- main
- java
- com
- ontimize
- projectwiki
- ws
- core
- rest
- MainRestController.java
- TestRestController.java
- UserRestController.java
- rest
- core
- ws
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- .gitignore
- pom.xml
- README.md
- projectwiki-api
Configure the OpenAPI system
This functionality can be enabled by creating the marker file marker-ws-ontimize-openapi-generator in the src/main/ontimize folder on the OpenAPI module. This file should only exist and be empty.
To comply with the project structure, we will generate the interfaces and the models in the package com.ontimize.projectwiki.openapi.core. Also, we will enable the bean validation functionality.
We can configure these functionalities adding the following properties it in the pom.xml file of the OpenAPI module (More information in this link).
pom.xml
...
<properties>
...
<ontimize.openapi.generator.maven.plugin.packageName>com.ontimize.projectwiki.openapi.core.service</ontimize.openapi.generator.maven.plugin.packageName>
<ontimize.openapi.generator.maven.plugin.modelPackageName>com.ontimize.projectwiki.openapi.core.dto</ontimize.openapi.generator.maven.plugin.modelPackageName>
<ontimize.openapi.generator.maven.plugin.useBeanValidation>true</ontimize.openapi.generator.maven.plugin.useBeanValidation>
</properties>
...
- ontimize-examples
- projectwiki-api
- src
- main
- java
- com
- ontimize
- projectwiki
- api
- core
- service
- IUserService.java
- service
- core
- api
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- projectwiki-boot
- src
- main
- java
- com
- ontimize
- projectwiki
- ServerApplication.java
- projectwiki
- ontimize
- com
- resources
- application.yml
- java
- main
- pom.xml
- src
- projectwiki-model
- src
- main
- db
- templateDB.txt
- java
- com
- ontimize
- projectwiki
- model
- core
- dao
- UserDao.java
- UserRoleDao.java
- service
- UserService.java
- dao
- core
- model
- projectwiki
- ontimize
- com
- resources
- dao
- placeholders.properties
- UserDao.xml
- UserRoleDao.xml
- dao
- db
- main
- pom.xml
- src
- projectwiki-openapi
- src
- main
- ontimize
- marker-ws-ontimize-openapi-generator
- resources
- public
- restapi
- openapi-rest.yml
- restapi
- public
- ontimize
- main
- pom.xml
- src
- projectwiki-ws
- src
- main
- java
- com
- ontimize
- projectwiki
- ws
- core
- rest
- MainRestController.java
- TestRestController.java
- UserRestController.java
- rest
- core
- ws
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- .gitignore
- pom.xml
- README.md
- projectwiki-api
Generate the interfaces
Now, we need to build the project to generate the interfaces and models, these interfaces will be placed in the target folder of the OpenAPI module.
ITestApi.java
package com.ontimize.projectwiki.openapi.core.service;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import org.springframework.validation.annotation.Validated;
import javax.validation.Valid;
import javax.validation.constraints.*;
@Validated
public interface ITestApi {
/**
* POST Test
* Develop purposes only.
* @param person (required)
* @return String
*
*/
@RequestMapping(path = "/test/test", method = RequestMethod.POST,
consumes = { "application/json" },
produces = { "text/plain" })
public ResponseEntity<String> postTest(@Valid @RequestBody com.ontimize.projectwiki.openapi.core.dto.Person person);
/**
* Test
* Develop purposes only.
* @return String
*
*/
@RequestMapping(path = "/test/test", method = RequestMethod.GET,
produces = { "text/plain" })
public ResponseEntity<String> testRest();
}
Person.java
package com.ontimize.projectwiki.openapi.core.dto;
import java.util.Objects;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.Valid;
import javax.validation.constraints.*;
/**
* Person
*/
@javax.annotation.Generated(value = "com.ontimize.openapi.ServerCodegen", date = "2024-04-09T11:09:49.679913+02:00[Europe/Madrid]")
public class Person {
private String name;
private String surname;
public Person name(String name) {
this.name = name;
return this;
}
/**
* Name
* @return name
*/
@ApiModelProperty(value = "Name")
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Person surname(String surname) {
this.surname = surname;
return this;
}
/**
* Surname
* @return surname
*/
@ApiModelProperty(value = "Surname")
public String getSurname() {
return surname;
}
public void setSurname(String surname) {
this.surname = surname;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
Person person = (Person) o;
return Objects.equals(this.name, person.name) &&
Objects.equals(this.surname, person.surname);
}
@Override
public int hashCode() {
return Objects.hash(name, surname);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("class Person {\n");
sb.append(" name: ").append(toIndentedString(name)).append("\n");
sb.append(" surname: ").append(toIndentedString(surname)).append("\n");
sb.append("}");
return sb.toString();
}
/**
* Convert the given object to string with each line indented by 4 spaces
* (except the first line).
*/
private String toIndentedString(Object o) {
if (o == null) {
return "null";
}
return o.toString().replace("\n", "\n ");
}
}
- ontimize-examples
- projectwiki-api
- src
- main
- java
- com
- ontimize
- projectwiki
- api
- core
- service
- IUserService.java
- service
- core
- api
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- projectwiki-boot
- src
- main
- java
- com
- ontimize
- projectwiki
- ServerApplication.java
- projectwiki
- ontimize
- com
- resources
- application.yml
- java
- main
- pom.xml
- src
- projectwiki-model
- src
- main
- db
- templateDB.txt
- java
- com
- ontimize
- projectwiki
- model
- core
- dao
- UserDao.java
- UserRoleDao.java
- service
- UserService.java
- dao
- core
- model
- projectwiki
- ontimize
- com
- resources
- dao
- placeholders.properties
- UserDao.xml
- UserRoleDao.xml
- dao
- db
- main
- pom.xml
- src
- projectwiki-openapi
- src
- main
- resources
- main
- target
- generated-sources
- java
- com
- ontimize
- projectwiki
- openapi
- core
- dto
- Person.java
- service
- ITestApi.java
- dto
- core
- openapi
- projectwiki
- ontimize
- com
- java
- generated-sources
- pom.xml
- src
- projectwiki-ws
- src
- main
- java
- com
- ontimize
- projectwiki
- ws
- core
- rest
- MainRestController.java
- TestRestController.java
- UserRestController.java
- rest
- core
- ws
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- .gitignore
- pom.xml
- README.md
- projectwiki-api
Implements the generated interfaces on the web services module
Once the interfaces have been generated, we need to add the OpenAPI module dependency to the web services module and implement the interface on the REST controller.
The request mapping annotations are declared on the generated interface and should not be declared again on the controller.
pom.xml
...
<dependencies>
<dependency>
<groupId>com.ontimize</groupId>
<artifactId>projectwiki-openapi</artifactId>
</dependency>
...
<dependencies>
...
TestRestController.java
package com.ontimize.projectwiki.ws.core.rest;
import com.ontimize.projectwiki.openapi.core.dto.Person;
import com.ontimize.projectwiki.openapi.core.service.ITestApi;
import org.springframework.http.HttpStatus;
//import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
//import org.springframework.web.bind.annotation.RequestMapping;
//import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
@RestController
//@RequestMapping("/test")
public class TestRestController implements ITestApi {
@Override
public ResponseEntity<String> postTest(Person person) {
return new ResponseEntity<>(String.format("Hi %s!", person.getName()), HttpStatus.OK);
}
//@RequestMapping(value = "/test", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
@Override
public ResponseEntity<String> testRest() {
return new ResponseEntity<>("It Works!", HttpStatus.OK);
}
}
- ontimize-examples
- projectwiki-api
- src
- main
- java
- com
- ontimize
- projectwiki
- api
- core
- service
- IUserService.java
- service
- core
- api
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- projectwiki-boot
- src
- main
- java
- com
- ontimize
- projectwiki
- ServerApplication.java
- projectwiki
- ontimize
- com
- resources
- application.yml
- java
- main
- pom.xml
- src
- projectwiki-model
- src
- main
- db
- templateDB.txt
- java
- com
- ontimize
- projectwiki
- model
- core
- dao
- UserDao.java
- UserRoleDao.java
- service
- UserService.java
- dao
- core
- model
- projectwiki
- ontimize
- com
- resources
- dao
- placeholders.properties
- UserDao.xml
- UserRoleDao.xml
- dao
- db
- main
- pom.xml
- src
- projectwiki-openapi
- src
- main
- ontimize
- marker-ws-ontimize-openapi-generator
- resources
- ontimize
- main
- pom.xml
- src
- projectwiki-ws
- src
- main
- java
- com
- ontimize
- projectwiki
- ws
- core
- rest
- MainRestController.java
- TestRestController.java
- UserRestController.java
- rest
- core
- ws
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- .gitignore
- pom.xml
- README.md
- projectwiki-api
Testing
To test this functionality we will use the Swagger tool provided by Ontimize.
Enable the Swagger User Interface
To enable the Swagger UI we will add the following property it in the pom.xml file of the OpenAPI module (More information in this link).
pom.xml
...
<properties>
...
<ontimize.openapi.swagger-ui.enabled>true</ontimize.openapi.swagger-ui.enabled>
</properties>
...
- ontimize-examples
- projectwiki-api
- src
- main
- java
- com
- ontimize
- projectwiki
- api
- core
- service
- IUserService.java
- service
- core
- api
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- projectwiki-boot
- src
- main
- java
- com
- ontimize
- projectwiki
- ServerApplication.java
- projectwiki
- ontimize
- com
- resources
- application.yml
- java
- main
- pom.xml
- src
- projectwiki-model
- src
- main
- db
- templateDB.txt
- java
- com
- ontimize
- projectwiki
- model
- core
- dao
- UserDao.java
- UserRoleDao.java
- service
- UserService.java
- dao
- core
- model
- projectwiki
- ontimize
- com
- resources
- dao
- placeholders.properties
- UserDao.xml
- UserRoleDao.xml
- dao
- db
- main
- pom.xml
- src
- projectwiki-openapi
- src
- main
- ontimize
- marker-ws-ontimize-openapi-generator
- resources
- ontimize
- main
- pom.xml
- src
- projectwiki-ws
- src
- main
- java
- com
- ontimize
- projectwiki
- ws
- core
- rest
- MainRestController.java
- TestRestController.java
- UserRestController.java
- rest
- core
- ws
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- .gitignore
- pom.xml
- README.md
- projectwiki-api
Redirect to the Swagger User Interface (Optional)
Now, we will add a custom index.html that will redirect to the Swagger UI when we open the application in the browser.
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>projectwiki</title>
<link rel="icon" type="image/x-icon" href="favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script type="application/javascript">
location.href = location.origin + "/swagger-ui/index.html";
</script>
</head>
<body>
</body>
</html>
- ontimize-examples
- projectwiki-api
- src
- main
- java
- com
- ontimize
- projectwiki
- api
- core
- service
- IUserService.java
- service
- core
- api
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- projectwiki-boot
- src
- main
- java
- com
- ontimize
- projectwiki
- ServerApplication.java
- projectwiki
- ontimize
- com
- resources
- public
- index.html
- application.yml
- public
- java
- main
- pom.xml
- src
- projectwiki-model
- src
- main
- db
- templateDB.txt
- java
- com
- ontimize
- projectwiki
- model
- core
- dao
- UserDao.java
- UserRoleDao.java
- service
- UserService.java
- dao
- core
- model
- projectwiki
- ontimize
- com
- resources
- dao
- placeholders.properties
- UserDao.xml
- UserRoleDao.xml
- dao
- db
- main
- pom.xml
- src
- projectwiki-openapi
- src
- main
- ontimize
- marker-ws-ontimize-openapi-generator
- resources
- ontimize
- main
- pom.xml
- src
- projectwiki-ws
- src
- main
- java
- com
- ontimize
- projectwiki
- ws
- core
- rest
- MainRestController.java
- TestRestController.java
- UserRestController.java
- rest
- core
- ws
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- .gitignore
- pom.xml
- README.md
- projectwiki-api
Allow to access to the API specification and to the Swagger User Interface
The API specification and the Swagger UI must be accesible withouth authentication. To do this, we must provide them as static resources and exclude them from the list of protected paths.
application.yml
...
ontimize:
...
security:
...
ignore-paths: '/index.html,/restapi/**,/swagger-ui/**'
...
spring:
...
resources:
...
static-locations: classpath:/public/
...
- ontimize-examples
- projectwiki-api
- src
- main
- java
- com
- ontimize
- projectwiki
- api
- core
- service
- IUserService.java
- service
- core
- api
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- projectwiki-boot
- src
- main
- java
- com
- ontimize
- projectwiki
- ServerApplication.java
- projectwiki
- ontimize
- com
- resources
- public
- index.html
- application.yml
- public
- java
- main
- pom.xml
- src
- projectwiki-model
- src
- main
- db
- templateDB.txt
- java
- com
- ontimize
- projectwiki
- model
- core
- dao
- UserDao.java
- UserRoleDao.java
- service
- UserService.java
- dao
- core
- model
- projectwiki
- ontimize
- com
- resources
- dao
- placeholders.properties
- UserDao.xml
- UserRoleDao.xml
- dao
- db
- main
- pom.xml
- src
- projectwiki-openapi
- src
- main
- ontimize
- marker-ws-ontimize-openapi-generator
- resources
- ontimize
- main
- pom.xml
- src
- projectwiki-ws
- src
- main
- java
- com
- ontimize
- projectwiki
- ws
- core
- rest
- MainRestController.java
- TestRestController.java
- UserRestController.java
- rest
- core
- ws
- projectwiki
- ontimize
- com
- java
- main
- pom.xml
- src
- .gitignore
- pom.xml
- README.md
- projectwiki-api
Once the changes has been applied, we must built and run the project, then we can access to the application by opening a web browser and navigating to http://localhost:33333):
We must open the authorization dialog by clicking on the Authorize button, provide the credentials and click on the Authorize button.
Now, we must close the authorization dialog, expand the POST section, click on the Try it out and the Execute buttons.
The Swagger UI will make the request to the API and will show the response message.