[JAVA] How to create your own headless API using Liferay's REST Builder (Part 1)

Introduction

Recently I've been experimenting with Liferay's new headless API. Specifically, it's a React-based SAP that leverages headless delivery and headless user management modules. We'll cover the implementation four times, but this time we'll show you how to use the REST Builder tools to create your own headless API.

You may have the following questions here.

"_Why use REST Builder instead of your own REST based on traditional JAX-RS? _"

Liferay's REST Builder does more than just build an application that exposes endpoints. It also provides the following additional features: :

--Integration with Liferay's authentication pipeline --Integration with Liferay's handling of CORS --Headless facility to support integration with Liferay search, filtering, paging, etc. --JSON or XML generation function for caller request --Integration with the upcoming Liferay GraphQL endpoint for use via GraphQL without customizing the REST Builder API --Ensuring consistency for mobile and SPA application developers.

You don't have to use all of these, just use these features in the right place.

In this article, which marks the beginning of the blog series, we'll show you the main parts of the YAML file that sets up a project to use the new REST Builder and defines entry points. Since this article will be long, I will divide it into several parts, starting with the definition of the service path (entry point) and explaining the construction of the service.

Pre-work

Before you start, Liferay's official documentation on how to use REST Builder (https://portal.liferay.dev/docs/7-2/appdev/-/knowledge_base/a/generating-apis-with-rest- Please read builder). It doesn't take long to read the article, so please come back to this article after reading it.

Start the project

Run the following command to create a working project:

blade init -v 7.2 vitamins

This time, we named the project "** Vitamin **" to make it easier to imagine the structure of the project. This project consists of vitamins and minerals, which need to hold more vitamins and minerals than web content. Therefore, a custom service layer (Service Builder) is required in addition to the headless REST layer (REST Builder).

Then load your project into the IDE and follow these steps to edit the build.gradle file with the headless-vitamins-impl module (discussed later): https://portal.liferay.dev/docs/7-2/reference /-/ knowledge_base / r / rest-builder-gradle-plugin

You can verify that REST Builder is actually available by running the ./gradlew tasks command inside the headless-vitamins-impl module:

$ ./gradlew tasks

> Task :tasks

------------------------------------------------------------
All tasks runnable from root project
------------------------------------------------------------

Build tasks
-----------
assemble - Assembles the outputs of this project.
build - Assembles and tests this project.
buildCSS - Build CSS files.
buildDependents - Assembles and tests this project and all projects that depend on it.
buildLang - Runs Liferay Lang Builder to translate language property files.
buildNeeded - Assembles and tests this project and all projects it depends on.
buildREST - Runs Liferay REST Builder.
...abridgement...

I need a set of modules, so I put headless-vitamins-api,headless-vitamins in themodules / headless-vitamins folder in the workspace (I created this subdirectory to put the headless modules together). Create -impl, headless-vitamins-client, and headless-vitamins-test. The reference documentation doesn't mention creating these additional modules, but you'll need them, as we'll see later.

$ cd modules/headless-vitamins
$ blade create -t api -v 7.2 -p com.dnebinger.headless.vitamins headless-vitamins-api
Successfully created project headless-vitamins-api in vitamins/modules/headless-vitamins
$ blade create -t api -v 7.2 -p com.dnebinger.headless.vitamins headless-vitamins-impl
Successfully created project headless-vitamins-impl in vitamins/modules/headless-vitamins
$ blade create -t api -v 7.2 -p com.dnebinger.headless.vitamins headless-vitamins-client
Successfully created project headless-vitamins-client in vitamins/modules/headless-vitamins
$ blade create -t api -v 7.2 -p com.dnebinger.headless.vitamins headless-vitamins-test
Successfully created project headless-vitamins-test in vitamins/modules/headless-vitamins

Since I specified ʻapias the type when creating the module with the above command, some unnecessary packages and java files are also generated. It will take some time to clean up these. You also need to rename thesrc / mai directory in the headless-vitamins-testdirectory tosrc / testIntegration`.

For this project, REST Builder will generate some integration test cases, but you need the appropriate directories for them to work. The bnd.bnd file is updated with com.dnebinger.headless.vitamins.api and com.dnebinger.headless.vitamins.impl symbolic names, etc. to follow Liferay's standard naming conventions for bundles. The build.gradle file will require a lot of additions, but it's a breather.

Service definition

From here it will gradually become fun. Let's create a YAML file to define the service endpoint. If this is your first time doing this, you may find it daunting.

First of all, as a simple task. You need to add the rest-config.yamlfile insideheadless-vitamins-impl`.

apiDir: "../headless-vitamins-api/src/main/java"
apiPackagePath: "com.dnebinger.headless.vitamins"
application:
    baseURI: "/headless-vitamins"
    className: "HeadlessVitaminsApplication"
    name: "dnebinger.Headless.Vitamins"
author: "Dave Nebinger"
clientDir: "../headless-vitamins-client/src/main/java"
testDir: "../headless-vitamins-test/src/testIntegration/java"

It's a collection of the elements you've created that Liferay's headless needs to work. The last two entries refer to the client and the test. Therefore, this work should be done first.

Then work with the rest-openapi.yaml file. This file is also created inside the headless-vitamins-impl module. Instead of throwing everything away at once, here's a step-by-step understanding of the details. All file structures can be found in this repository (https://github.com/dnebing/vitamins).

Each OpenAPI YAML file consists of three sections, ** Meta **, ** Paths ** (endpoints) and ** Reusable Components ** (type definitions), and is no different from the one created this time.

My meta section is:

openapi: 3.0.1
info:
  title: "Headless Vitamins"
  version: v1.0
  description: "API for accessing Vitamin details."

We are making good progress so far.

Type definition

Next, share the reusable component you just created. These don't work on their own, but they do lighten the burden of covering Paths later.

My main type and "vitamin" type:

components:
  schemas:
    Vitamin:
      description: Contains all of the data for a single vitamin or mineral.
      properties:
        name:
          description: The vitamin or mineral name.
          type: string
        id:
          description: The vitamin or mineral internal ID.
          type: string
        chemicalNames:
          description: The chemical names of the vitamin or mineral if it has some.
          items:
            type: string
          type: array
        properties:
          description: The chemical properties of the vitamin or mineral if it has some.
          items:
            type: string
          type: array
        group:
          description: The group the vitamin or mineral belongs to, i.e. the B group or A group.
          type: string
        description:
          description: The description of the vitamin or mineral.
          type: string
        articleId:
          description: A journal articleId if there is a web content article for this vitamin.
          type: string
        type:
          description: The type of the vitamin or mineral.
          enum: [Vitamin, Mineral, Other]
          type: string
        attributes:
          description: Health properties attributed to the vitamin or mineral.
          items:
            type: string
          type: array
        risks:
          description: Risks associated with the vitamin or mineral.
          items:
            type: string
          type: array
        symptoms:
          description: Symptoms associated with the vitamin or mineral deficiency.
          items:
            type: string
          type: array
        creator:
          $ref: "#/components/schemas/Creator"
      type: object

The above is the YAML format. Indentation represents a hierarchy, with rows of deeper indentation being its children and rows of the same hierarchy meaning siblings.

The "vitamin" type has many properties. Properties range from simple ones such as name and id to more complex ones. The type property is String, but it is limited by the enumeration of possible values. The creator is a reference to another object ($ ref is this) in this file.

If you see $ ref in the same file, it means you need to include a reference. The creator types of "vitamins" copied from Liferay's headless-delivery file are:

    Creator:
      description: Represents the user account of the content's creator/author. Properties follow the [creator](https://schema.org/creator) specification.
      properties:
        additionalName:
          description: The author's additional name (e.g., middle name).
          readOnly: true
          type: string
        familyName:
          description: The author's surname.
          readOnly: true
          type: string
        givenName:
          description: The author's first name.
          readOnly: true
          type: string
        id:
          description: The author's ID.
          format: int64
          readOnly: true
          type: integer
        image:
          description: A relative URL to the author's profile image.
          format: uri
          readOnly: true
          type: string
        name:
          description: The author's full name.
          readOnly: true
          type: string
        profileURL:
          description: A relative URL to the author's user profile.
          format: uri
          readOnly: true
          type: string
      type: object

That's all for the type description.

Summary

Is it too early to put together? Certainly the work is still incomplete! Rest assured that the next part has already been published.

In this part, we showed you how to create a new Liferay Gradle Workspace with custom headless services and the required modules. I also skipped the Path section and touched on the Meta section to define the "Vitamin" project and creator objects to better understand the reusable components, including the OpenAPI YAML file.

Next time will identify Paths (entry points) See you in the next part!

https://github.com/dnebing/vitamins

Recommended Posts

How to create your own headless API using Liferay's REST Builder (Part 4)
How to create your own headless API using Liferay's REST Builder (Part 1)
How to create your own annotation in Java and get the value
Let's create a REST API using WildFly Swarm.
[Rails] How to create a graph using lazy_high_charts
How to implement optimistic locking in REST API
How to create hierarchical category data using ancestry
[Java] How to operate List using Stream API
How to create docker-compose
[Forge] How to register your own Entity and Entity Render in 1.13.2
How to create a placeholder part to use in the IN clause
How to deploy jQuery in your Rails app using Webpacker
How to create a service builder portlet in Liferay 7 / DXP
How to play MIDI files using the Java Sound API
How to create an application
How to use Chain API
How to use @Builder (Lombok)
Create your own Java annotations
Introduction to EHRbase 2-REST API
How to create a method
How to authorize using graphql-ruby
[Rails 6] How to create a dynamic form input screen using cocoon
Easy way to create a mapping class when using the API