Consuming GraphQL APIs

Liferay DXP contains GraphQL APIs for most of its applications. Here’s how to consume them in three steps:

  1. Identify the API you wish to consume.

  2. Identify the site containing the data you need.

  3. Make the API call using credentials that have access to the data.

Note

Liferay DXP’s GraphQL APIs are available at http://[host]:[port]/o/graphql.

Start by running Liferay DXP to call its GraphQL APIs.

Start a new Liferay instance by running

docker run -it -m 8g -p 8080:8080 liferay/portal:7.4.3.120-ga120

Sign in to Liferay at http://localhost:8080. Use the email address test@liferay.com and the password test. When prompted, change the password to learn.

Identify the Service to Consume

  1. Navigate to http://localhost:8080/o/api.

  2. Click GraphQL at the top-right of the screen to open Liferay’s GraphiQL browser.

    Access Liferay's GraphiQL through the API Explorer.

  3. Click the Docs link below the button you clicked. Now you can browse the API.

  4. GraphQL separates read and write operations by calling the first a query and the second a mutation. Since the first thing you want to do is post a blog entry, click mutation. The API list appears.

    Important

    Liferay DXP 2024.Q2+/Portal 7.4 GA120+ Use versioned namespaced GraphQL APIs to avoid naming conflicts between operations from different APIs, enhance readability and maintainability by clearly indicating the source and version of each API operation, and ensure that applications remain compatible with evolving APIs, reducing the risk of compatibility issues and the need for frequent updates.

    Versioned API calls work similarly to non-versioned ones. The only difference is the addition of a namespace level to the query. Examples of both appear below.

    While you can use both versioned and non-versioned GraphQL APIs, note that non-versioned APIs are deprecated and will be removed in the future.

  5. Use the search at the top or scroll down and find the call to createSiteBlogPosting:

    createSiteBlogPosting(
       siteKey: String!
       blogPosting: InputBlogPosting
       ): BlogPosting
    

    Liferay DXP 2024.Q2+/Portal 7.4 GA120+ Or you can find it under the headlessDelivery_v1_0/MutationHeadlessDelivery_v1_0 namespace.

Note

You can also discover your local installation’s APIs by requesting the schema directly:

curl 'http://localhost:8080/o/graphql' -H "Content-Type: application/json" --data '{"query":"query{ __schema{ queryType{ name fields{ name args{ name } description } } } }","variables":{}}'

This URL does not require authentication, but it’s quite cumbersome to manage the returned schema. It’s better to use the included GraphQL client.

The included GraphQL client has a schema documentation browser.

Since the API requires you to know the site containing the blog where the entry should be posted, you must find the site ID first.

Identify the Site Containing the Data

  1. Go to http://localhost:8080.

  2. Open the Global Menu Global Menu, click the Control Panel tab, and go to Sites → Sites.

  3. Click the Actions button Actions Button next to the Liferay site and choose Go to Site Settings.

  4. Go to Site Configuration.

The Site ID appears at the top of the Details section. It’s an integer, like 20117.

Make the Service Call using Credentials with Access to the Data

Now you have everything needed to make the call. All web services must be accessed using credentials that grant access to the data you’re requesting. The included GraphQL client authenticates through your browser. If you plan to write a standalone client, you should authorize users via OAuth2.

Important

During development, it’s much easier to use Basic Auth, which passes credential data in the URL. Since this is insecure, never use this method for production.

Calling a GraphQL API Using Basic Auth (During Development Only)

To call a service using Basic Auth, provide the credentials in the URL:

curl \
   http://localhost:8080/o/graphql \
   --data "{'query':'query {blogPostings(filter: \'\', page: 1, pageSize: 10, search: \'\', siteKey: \'20117\', sort: \'\'){ page  items{ id articleBody headline  creator{ name }}}}'}" \
   --header "content-type: application/json" \
   --request POST \
   --user test@liferay.com:learn \

Calling a Service Using OAuth2

Note

The use of GraphQL with OAuth2 is supported in Liferay DXP 7.4 U77+/Liferay Portal 7.4 GA77+

For production, create an OAuth2 application and use the OAuth2 process to get an authorization token. Once you have the token, provide it in the HTTP header:

curl \
   http://localhost:8080/o/graphql \
   --data '{"query":"query {blogPostings(filter: \"\", page: 1, pageSize: 10, search: \"\", siteKey: \"20117\", sort: \"\"){ page  items{ id articleBody headline  creator{ name }}}}"}' \
   --header "Authorization: Bearer d5571ff781dc555415c478872f0755c773fa159" \
   --header 'content-type: application/json' \
   --request POST \

Getting and Posting Data

At the top left window of the GraphQL client, place this code, which retrieves all blog entries (don’t forget to change the value for the siteKey!):

query {
   blogPostings(
      filter: ""
      page: 1
      pageSize: 10
      search: ""
      siteKey: "20117"
      sort: ""
   ) {
      page
      items {
         id
         articleBody
         headline
         creator {
            name
         }
      }
   }
}

Liferay DXP 2024.Q2+/Portal 7.4 GA120+ Or you can add the headlessDelivery_v1_0 namespace and write the query like this:

query {
   headlessDelivery_v1_0 {
      blogPostings(
         filter: ""
         page: 1
         pageSize: 10
         search: ""
         siteKey: "20117"
         sort: ""
      ) {
         page
         items {
         id
         articleBody
         headline
         creator {
            name
         }
         }
      }
   }
}

Click the play button to run it, and verify that there aren’t any blog entries:

{
   "data": {
      "blogPostings": {
         "page": 1,
         "items": []
      }
   }
}

Now, post a blog entry.

Posting a Blog Entry

  1. Make the request by visiting http://localhost:8080/o/api again. Click GraphQL.

  2. Construct a JSON document containing the entry you wish to publish and place it into the Query Variables box at the lower left (1) (you may have to scroll down and click on Query Variables to expand the box).

    {
       "blog": {
          "articleBody": "This Blog entry was created by calling the GraphQL service!",
          "headline": "GraphQL Blog Entry"
       }
    }
    
  3. Construct the GraphQL query based on the schema documentation and place it in the query area at the top left window of the GraphQL client (2).

    mutation CreateBlog($blog: InputBlogPosting) {
       createSiteBlogPosting(blogPosting: $blog, siteKey: "20117") {
          headline
          articleBody
          id
          friendlyUrlPath
       }
    }
    

    Liferay DXP 2024.Q2+/Portal 7.4 GA120+ Or you can add the headlessDelivery_v1_0 namespace and write the query like this:

    mutation CreateBlog($blog: InputBlogPosting) {
       headlessDelivery_v1_0 {
          createSiteBlogPosting(blogPosting: $blog, siteKey: "20117") {
             headline
             articleBody
             id
             friendlyUrlPath
          }
       }
    }
    
  4. Run your query by clicking the play button at the top.

    The blog entry you added now appears in the GraphQL client’s right pane (3).

Liferay DXP returns a JSON representation of your blog entry that contains the fields you requested in the mutation:

{
   "data": {
      "headlessDelivery_v1_0": {
         "createSiteBlogPosting": {
         "headline": "GraphQL Blog Entry",
         "articleBody": "This Blog entry was created by calling the GraphQL service!",
         "id": 32198,
         "friendlyUrlPath": "graphql-blog-entry-3"
         }
      }
   }
}

The JSON document goes into the Query Variables box and the mutation goes into the query area. As a result, the created blog entry information appears in the GraphQL client's right pane.

Note

You can make these requests with any web client, such as cURL:

curl --request POST --url http://localhost:8080/o/graphql -u test@liferay.com:learn --header 'content-type: application/json' --data '{"query":"mutation CreateBlog($blog: InputBlogPosting){ createSiteBlogPosting(blogPosting: $blog, siteKey: \"20117\" ) { headline articleBody id friendlyUrlPath } } ","variables":{"blog":{"articleBody":"This Blog entry was created by using cURL to call the GraphQL service!","headline":"cURL GraphQL Blog Entry"}},"operationName":"CreateBlog"}'

Getting All Blog Entries

Now you can repeat the first query you did:

query {
   blogPostings(
      filter: ""
      page: 1
      pageSize: 10
      search: ""
      siteKey: "20117"
      sort: ""
   ) {
      page
      items {
         id
         articleBody
         headline
         creator {
            name
         }
      }
   }
}

Liferay DXP 2024.Q2+/Portal 7.4 GA120+ Or you can add the headlessDelivery_v1_0 namespace and write the query like this:

query {
   headlessDelivery_v1_0 {
      blogPostings(
         filter: ""
         page: 1
         pageSize: 10
         search: ""
         siteKey: "20117"
         sort: ""
      ) {
         page
         items {
            id
            articleBody
            headline
            creator {
               name
            }
         }
      }
   }
}

Liferay DXP returns JSON containing the blog entry you posted:

{
   "data": {
      "blogPostings": {
         "page": 1,
         "items": [
         {
            "id": 32010,
            "articleBody": "This Blog entry was created by calling the GraphQL service!",
            "headline": "GraphQL Blog Entry",
            "creator": {
               "name": "Test Test"
            }
         }
         ]
      }
   }
}

Getting a Single Blog Entry

The API call from the GraphQL schema for getting a single Blog entry has only one parameter:

blogPosting(
   blogPostingId: Long
): BlogPosting

Since the query above revealed your Blog post’s ID, you can retrieve only the post you want:

query {
   blogPosting(blogPostingId: 32010) {
      id
      headline
      articleBody
   }
}

Liferay DXP 2024.Q2+/Portal 7.4 GA120+ Or you can add the headlessDelivery_v1_0 namespace and write the query like this:

query {
   headlessDelivery_v1_0 {
      blogPosting(blogPostingId: 32010) {
         id
         headline
         articleBody
      }
   }
}

Paste this into the query area at the top left window of the client and click the Play button. It returns the same blog entry:

{
   "data": {
      "blogPosting": {
         "id": 32010,
         "headline": "GraphQL Blog Entry",
         "articleBody": "This Blog entry was created by calling the GraphQL service!"
      }
   }
}

Deleting a Blog Entry

Deleting a blog entry, like creating one, is a mutation. Its call is almost the same as getting a single blog entry:

deleteBlogPosting(
  blogPostingId: Long
): Boolean

Using the client, you can make the call like this:

mutation {
   deleteBlogPosting(blogPostingId: 32010)
}

Liferay DXP 2024.Q2+/Portal 7.4 GA120+ Or you can add the headlessDelivery_v1_0 namespace and write the query like this:

mutation {
   headlessDelivery_v1_0 {
      deleteBlogPosting(blogPostingId: 32010)
   }
}

This call returns a Boolean in a JSON document denoting success or failure:

{
   "data": {
      "deleteBlogPosting": true
   }
}

Congratulations! You’ve now learned how to call Liferay DXP’s GraphQL services. Remember that the examples above use Basic Auth: for production, use OAuth2 to call services in a secure way.

Capabilities

Product

Contact Us

Connect

Powered by Liferay
© 2024 Liferay Inc. All Rights Reserved • Privacy Policy