REST Builder provides an easy way to develop your GraphQL and REST API for your new or existing web services. This services can be invoke through HTTP requests from external systems. Decoupling your service with an API gives you flexibility to integrate with different front-end technologies, mobile apps and 3rd party or legacy systems.
REST Builder is a code generation tool built by Liferay that allows developers to define custom APIs following the OpenAPI Specification (OAS) in a Design First approach.
Developers can define the API's contract using OpenAPI documents to describe what the API does and what resources handles in a language agnostic and human readable way, allowing both, machines and humans, to understand what the API is supposed to do.
REST Builder generates the API resources model layer and the API implementation layer using the JAX-RS specification, one of the JAVA EE standards, and the GraphQL servlet. The generation tool implements all the necessary code to access the API defined in the API contract and advanced features such as pagination, search, filter, batch support..., letting the developer focus in the service business logic, what makes this tool very powerful and valuable.
REST Builder generate a JAVA client to communicate with the API and an integration test module to test the API from the outside as a external application.
REST Builder tool generates code splitted in multiple modules in order to offer a clean and decoupled implementation of your GraphQL and REST APIs.
The default project structure is a parent folder with the name of the application, usually the artifact identifier, containing a subfolder with the API module, with -api suffix, and a subfolder with the implementation module, with the -impl sufix. If API client and integration tests are configured, the parent folder should contain two additional subfolders with -client and -test suffixes, where the client and test code will be generated.
Each module should contain the usual module configuration files: bnd.bnd and build.gradle or pom.xml depending on the desired build mechanism.
Finally, the implementation module should include the API configuration file and OpenAPI documents needed by the generation tool.
The resulting folder structure should be similar to the following:
In this section you'll learn how to configure the REST Builder generation with the API Configuration file and describe your API using the OpenAPI document (or set of documents).
The API Configuration file allows you to provide the required parameters and configuration to REST Builder tool, on which the generated code will depend.
The API configuration file uses YAML format and, by default, is located inside the implementation module with the name rest-config.yaml.
The configuration parameters are:
Field Name | Type | Description | Required |
---|---|---|---|
apiDir | string | Directory of the API module | true |
apiPackagePath | string | API package name | true |
application | Application Object | Information about the application | true |
author | string | Author name | true |
clientDir | string | Directory of the JAVA client module. If it is not set, the client will not be generated | false |
clientMavenGroupdId | string | Group identifier of the client module | false |
forceClientVersionDescription | boolean | Force adding a message to the description that reflects the last version of the client. Defaults to true |
false |
forcePredictableContentApplicationXML | boolean | Force the usage of XML media type in operation request bodies and responses. If no XML definition is provided, JSON definition will be used. Defaults to true |
false |
forcePredictableOperationId | boolean | Force setting a predictable operationId based on the path and the return type. Defaults to true |
false |
forcePredictableSchemaPropertyName | boolean | Force a consistent naming scheme for properties based on the schema returned. Defaults to true |
false |
generateBatch | boolean | Generate batch endpoints. Defaults to true |
false |
generateGraphQL | boolean | Generate GraphQL endpoints. Defaults to true |
false |
generateREST | boolean | Generate REST endpoints. Defaults to true |
false |
implDir | string | Directory where the generated code will be stored inside each module. Defaults to src/main/java |
false |
licenseName | string | Application license name. Defaults to Apache 2.0 |
false |
licenseUrl | string | License URL. Defaults to http://www.apache.org/licenses/LICENSE-2.0.html |
false |
testDir | string | Directory of the integration test module. If it is not set, the integration tests will not be generated | false |
warningsEnabled | boolean | Enable warnings during the REST Builder execution. Defaults to true |
false |
The Application object parameters are:
Field Name | Type | Description | Required |
---|---|---|---|
baseUri | string | Application base URI | true |
className | string | Name of the class with the JAX-RS application | true |
name | string | Application name | true |
security | Security Object | Information about application security | false |
The Security object parameters are:
Field Name | Type | Description | Required |
---|---|---|---|
basicAuth | string | Basic authentication | false |
guestAllowed | string | Allow guest access | false |
oAuth | string | oAuth authentication | false |
An example of a valid API Configuration file is:
apiDir: "../guestbook-api/src/main/java"
apiPackagePath: "com.liferay.guestbook"
application:
baseURI: "/guestbook"
className: "GuestbookApplication"
name: "Guestbook"
author: "John Doe"
clientDir: "../guestbook-client/src/main/java"
testDir: "../guestbook-test/src/testIntegration/java"
The OpenAPI Document describes what the API does and which are the resources to interact with. REST Builder is compatible with the OAS 3.*.* versions and support OpenAPI documents in YAML format.
The OpenAPI document uses YAML format and, by default, should be located inside the implementation module with the name rest-openapi.yaml
The most common fields are defined in the table below. For an exhaustive and detailed list of fields, please refer to the official OAS specification
Field Name | Type | Description | Required |
---|---|---|---|
components | Components Object | Contains the schema resources | false |
info | Info Object | Metadata about the API | true |
openapi | string | The semantic version number of the OpenAPI Specification version used in the document | true |
paths | Paths Object | The available paths and operations for the API | true |
The components field contains objects to be referenced from other places in the document by the assigned key. It usually contains the schema of the objects used in the API:
Field Name | Type | Description | Required |
---|---|---|---|
schema | Map[String, Schema Object] | A map with schema definitions | false |
The schema is defined by description, format, type and a set of properties that are also Schema Objects. To read a complete definition of the schema object refer to the specification.
The info object is composed by:
Field Name | Type | Description | Required |
---|---|---|---|
title | string | The title of the application | true |
description | string | A short description of the application | false |
license | License Object | The license information for the exposed API | false |
version | string | The version of the application | true |
The license object is defined by:
Field Name | Type | Description | Required |
---|---|---|---|
name | string | The license name | true |
licenseUrl | string | A URL to the license used for the API | false |
The paths object holds the information relative to the individual endpoints and their operations:
Field Name | Type | Description | Required |
---|---|---|---|
/{path} | Path Item Object | Information about an individual endpoint. The field name must begin with a slash | false |
The path item object is composed by:
Field Name | Type | Description | Required |
---|---|---|---|
summary | string | A summary, intended to apply to all operations in this path | false |
description | string | A description, intended to apply to all operations in this path | false |
get | Operation Object | A definition of a GET operation on this path | false |
put | Operation Object | A definition of a PUT operation on this path | false |
post | Operation Object | A definition of a POST operation on this path | false |
delete | Operation Object | A definition of a DELETE operation on this path | false |
patch | Operation Object | A definition of a PATCH operation on this path | false |
The operation object describes a single API operation on a path:
Field Name | Type | Description | Required |
---|---|---|---|
summary | string | A short summary of what the operation does | false |
description | string | A description of the operation behavior | false |
operationId | string | Unique string used to identify the operation. REST Builder use the operationId to uniquely identify an operation, therefore, it is recommended to follow common programming naming conventions | false |
parameters | [Parameter Object] | A list of parameters that are applicable for this operation | false |
requestBody | Request Body Object | The request body applicable for this operation | false |
responses | Responses Object | The list of possible responses as they are returned from executing this operation | true |
tags | [string] | A list of tags for the operation | false |
The parameter object describes a single operation parameter. A unique parameter is defined by a combination of a name and location.
There possible parameter locations specified by the in
field are:
- path - The parameter value is part of the operation's URL.
- query - The parameter is appended to the URL.
- header - Custom headers that are expected as part of the request.
- cookie - Used to pass a specific cookie value to the API.
The parameter is defined by:
Field Name | Type | Description | Required |
---|---|---|---|
name | string | The name of the parameter. Parameter names are case sensitive | true |
in | string | One of the possible parameter locations explained in the previous list | true |
description | string | A brief description of the parameter | false |
required | boolean | Determines whether this parameter is mandatory | true |
schema | Schema Object | The schema defining the type of the parameter | true |
The request body object describes a single request body:
Field Name | Type | Description | Required |
---|---|---|---|
description | string | A brief description of the request body | false |
content | Map[string, Media Type Object] | The content of the request body | true |
required | boolean | Determines if the request body is required in the request. Defaults to false |
false |
Each Media Type Object provides schema and examples for the media type identified by its key
Field Name | Type | Description | Required |
---|---|---|---|
schema | Schema Object | The schema defining the content of the request, response, or parameter | false |
A map from HTTP response code to the expected response. The Responses Object must contain at least one response code, and it should be the response for a successful operation call. It is not necessary to cover all possible HTTP response codes but is expected to cover a successful operation response and any known errors.
The default may be used as a default response object for all HTTP codes that are not covered individually by the specification.
Field Name | Type | Description | Required |
---|---|---|---|
default | Response Object | The documentation of responses other than the ones declared for specific HTTP response codes | false |
{HTTP Status Code} | Response Object | The expected response for that HTTP status code | false |
The response object describes a single response from an API Operation
Field Name | Type | Description | Required |
---|---|---|---|
description | string | A short description of the response | true |
content | Map[string, Media Type Object] | A map containing descriptions of potential response payloads | false |
An example of a simple but valid OpenAPI document is shown below:
components:
schemas:
Guest:
properties:
guestId:
format: int64
type: integer
name:
type: string
type: object
info:
description: "Guestbook API"
license:
name: "Apache 2.0"
url: "http://www.apache.org/licenses/LICENSE-2.0.html"
title: "Guestbook"
version: v1.0
openapi: 3.0.1
paths:
/guests:
get:
description:
Retrieves the guests
operationId: getGuestsPage
responses:
200:
content:
application/json:
schema:
items:
$ref: "#/components/schemas/Guest"
type: array
application/xml:
schema:
items:
$ref: "#/components/schemas/Guest"
type: array
tags: ["Guest"]
post:
description:
Adds a new guest
operationId: postGuest
requestBody:
content:
application/json:
schema:
$ref: "#/components/schemas/Guest"
application/xml:
schema:
$ref: "#/components/schemas/Guest"
responses:
200:
content:
application/json:
schema:
$ref: "#/components/schemas/Guest"
application/xml:
schema:
$ref: "#/components/schemas/Guest"
tags: ["Guest"]
/guests/{id}:
get:
description:
Retrieves the guest with given identifier
operationId: getGuest
parameters:
- in: path
name: id
required: true
schema:
type: string
responses:
200:
content:
application/json:
schema:
$ref: "#/components/schemas/Guest"
application/xml:
schema:
$ref: "#/components/schemas/Guest"
tags: ["Guest"]
Blade CLI is a command tool to help creating a new Liferay module. It creates the folder structure and necessary files to kick-start your project, allowing the developer to select between Gradle or Maven build tools.
Blade offers many project templates, including REST Builder, providing a scaffolding to your API web service.
To create your API web service inside your Liferay Workspace with blade you should go to the modules folder and execute:
blade create --template rest-builder guestbook
This command will set your API web service folder structure, build script files of the selected build tool, and rest-config.yaml and rest-openapi.yaml with basic structure and parameters.
More detailed information can be found in Blade CLI and Project Templates documentation.
Once you have the folder structure set and the API configuration file and OpenAPI documents defined, you can run REST Builder tool to generate the scaffolding for your API web service. This can be done using Maven or Gradle REST Builder plugins.
* To find out which version of the Gradle and Maven plugins to use, go to Maven Central or Maven Repository to get the latest available version published.
The REST Builder Gradle plugin lets you execute REST Builder to generate the source files of your API web service.
To use the REST Builder Gradle plugin you need to include it in your build.gradle file:
buildscript {
dependencies {
classpath group: "com.liferay", name: "com.liferay.gradle.plugins.rest.builder", version: "${REST.Builder.version}"
}
repositories {
maven {
url "https://repository-cdn.liferay.com/nexus/content/groups/public"
}
}
}
apply plugin: "com.liferay.portal.tools.rest.builder"
The plugin adds the buildRest
task to your project. This task has two arguments:
Parameter | Description | Required |
---|---|---|
copyrightFile | File with the Copyright header to be used in the generated code. Defaults to null |
false |
restConfigDir | Directory containing your API web service definition files, rest-config.yaml and rest-openapi.yaml. Usually the implementation module folder. Defaults to ${project.projectDir} |
false |
To run the task you need to use the Gradle Wrapper to execute gradlew buildRest
.
The task should finish successfully generating the source files of the configured modules. In case of error, a descriptive message should be provided to allow the developer to easily locate it and fix it.
REST Builder is also available in Maven with the REST Builder Maven plugin.
To use the plugin you need to include it in the project's root pom.xml file:
<build>
<plugins>
...
<plugin>
<groupId>com.liferay</groupId>
<artifactId>com.liferay.portal.tools.rest.builder</artifactId>
<version>${REST.Builder.version}</version>
<configuration>
</configuration>
</plugin>
...
</plugins>
</build>
The plugind adds the Maven Goal build-rest:build
to run the code generation. There are two optional parameters to be added in the configuration section:
Parameter | Description | Required |
---|---|---|
copyrightFile | File with the Copyright header to be used in the generated code. Defaults to null |
false |
restConfigDir | Directory containing your API web service definition files, rest-config.yaml and rest-openapi.yaml. Usually the implementation module folder. Defaults to ${project.projectDir} |
false |
To run the task execute the Maven goal command with mvn build-rest:build
. The goal should finish generating the source files or with a meaningful error.
The generated code is splitted at least in two modules, the API module and the implementation module.
The API module contains the model of your API, your DTOs (Data Transfer Objects) and resources.
The DTOs represents the objects defined in the components section of the OpenAPI Document. They are meant to be transferred in the API request and responses. So, as a developer, you need to use it in your business logic to process the API requests and return them as response when it is needed.
The resources package contains the representation of the API resources correspondent to the paths section of the OpenAPI Document. These resources are implemented in the implementation module and mapped to the specified path.
The two packages containing DTOs and resources are exported to be used by other modules, as the implementation module.
Code generated in the implementation module consists of JAX-RS main entities, the resource endpoints and the GraphQL servlet, queries and mutations.
The jaxrs package contains the JAX-RS Application class that register the API web service in the portal.
The resource package contains the resource endpoints defined in the OpenAPI paths section. Each resource has a base implementation called Base*ResourceImpl offering helper methods to implement the endpoint logic. This class is extended by the correspondent *ResourceImpl class where the developer should add the business logic. There is also a OpenAPIResourceImpl class that registers an endpoint in http://[host]:[port]/o/[APPLICATION_NAME]/[API_VERSION]/openapi.[type]
to obtain the OpenAPI document, the API contract, in JSON and YAML format.
The graphql package contains the GraphQL servlet and with the classes needed to access your API through GraphQL queries and mutations.
The client module will be generated if it is configured in the API configuration YAML file. It is a fully operative client for the API defined in your OpenAPI Document, with its own DTOs, resources, serializers, deserializers and the HttpInvoker class to make the HTTP requests.
The test module will be generated if it is configured in the API configuration YAML file. This module contains generated classes to test all the endpoints and methods defined in your API contract, making requests as a external service. It uses the client generated in the client module to make these requests.
Every endpoint has a Base*ResourceTestCase class that uses a Template Pattern, providing the general structure to test each endpoint method and letting the developer to fill just the specific code related to the business logic in the *ResourceTest class.
The entry points to implement your API are the *ResourceImpl classes inside the implementation module. This is where you need to add your business logic to be executed when somebody access your API web service.
It is important to remark that you should not add any code inside classes annotated as @Generated
as these classes will be recreated each time REST Builder is executed. This can be necessary if you need to modify the API definition or expand it.
If test module is configured you should also add the correspondent code to test your logic in the *ResourceTest classes.
Once you finished you can deploy your API web service and use it in the URL:
http://[host]:[port]/o/[APPLICATION_NAME]/[API_VERSION]/
For example, using your Guestbook API web service locally will be in the URL:
http://localhost:8080/o/guestbook/v1.0
To be sure your API web service is correctly deployed you can use the OSGi console to list all the JAX-RS endpoints with the command jaxrs:check
In the past, as we evolve the REST Builder we were not as careful as we should regarding compatibility. We have committed to improve this in the future, ensuring backwards compatibility in REST Builder.
For those that are using older versions of Liferay and REST Builder, please check the next matrix to check compatibility between versions.
Reference the table below to learn more about supported configurations with Liferay Developer Tools
Liferay Version | Liferay Portal Vulcan API | REST Builder | OpenAPI | Swagger Annotations | OSGi | Java Servlet API | JAX-RS (JSR 339) | Java Bean Validation (JSR 303) | Jackson JSON library |
---|---|---|---|---|---|---|---|---|---|
Liferay Portal DXP 7.1 SP4 | 5.6.0 | [1.0.80, 1.0.86] | 3.0.x | 2.0.x | OSGi Release 6 | Java Servlet API 3.0.1 | 2.1 | 2.0.x | 2.10.x |
Liferay Portal DXP 7.2 SP2 | 6.9.0 | [1.0.93, 1.0.95] | 3.0.x | 2.0.x | OSGi Release 6 | Apache Felix Servlet API 1.1.2 | 2.1 | 2.0.x | 2.10.x |
Liferay Portal CE 7.3 GA3 | 7.6.0 | [1.0.98, 1.0.114] | 3.0.x | 2.0.x | OSGi Release 6 | Apache Felix Servlet API 1.1.2 | 2.1 | 2.0.x | 2.10.x |
Liferay Portal CE 7.3 GA4 | 7.7.2 | 1.0.115 | 3.0.x | 2.0.x | OSGi Release 6 | Apache Felix Servlet API 1.1.2 | 2.1 | 2.0.x | 2.10.x |
Liferay Portal CE 7.3 GA6 | 7.10.3 | [1.0.136, ?] | 3.0.x | 2.0.x | OSGi Release 6 | Apache Felix Servlet API 1.1.2 | 2.1 | 2.0.x | 2.10.x |
Liferay Portal CE 7.3 GA7 | 7.15.2 | [?, ?] | 3.0.x | 2.0.x | OSGi Release 6 | Apache Felix Servlet API 1.1.2 | 2.1 | 2.0.x | 2.10.x |
Liferay Portal DXP 7.3 GA1 | 7.10.2 | [1.0.136, ?] | 3.0.x | 2.0.x | OSGi Release 6 | Apache Felix Servlet API 1.1.2 | 2.1 | 2.0.x | 2.10.x |
Liferay Portal DXP 7.3 SP1 | 7.15.1 | [?, ?] | 3.0.x | 2.0.x | OSGi Release 6 | Apache Felix Servlet API 1.1.2 | 2.1 | 2.0.x | 2.10.x |