oo

Consuming GraphQL APIs

Liferay DXP contains GraphQL APIs for most of its applications. Here, you’ll learn how to consume them. This takes only 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.

You need a 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.112-ga112

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

Follow these steps:

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

  2. At the top-left of the screen that appears, pick headless-delivery from the selector. This is the category that contains the Blog posting API.

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

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

  5. 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.

  6. A list appears of the entire API use the search at the top or scroll down and find the call to createSiteBlogPosting:

    createSiteBlogPosting(
      blogPosting: InputBlogPosting
      siteKey: String!
      ): BlogPosting
    
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. For this reason, 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

Now you must find the Site ID:

  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 20122.

Make the Service Call using Credentials with Access to the Data

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

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 --request POST --url http://localhost:8080/o/graphql \ -u test@liferay.com:learn  --header 'content-type: application/json' --data '{"query":"query {blogPostings(filter: \"\", page: 1, pageSize: 10, search: \"\", siteKey: \"20122\", sort: \"\"){ page  items{ id articleBody headline  creator{ name }}}}"}'

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 --request POST --url http://localhost:8080/o/graphql -H "Authorization: Bearer d5571ff781dc555415c478872f0755c773fa159" --header 'content-type: application/json' --data '{"query":"query {blogPostings(filter: \"\", page: 1, pageSize: 10, search: \"\", siteKey: \"20122\", sort: \"\"){ page  items{ id articleBody headline  creator{ name }}}}"}'

Getting and Posting Data

In the top left window of the GraphQL client, place this code, which retrieves all blog entries:

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

Click the play button to run it, and you’ll see there aren’t any blog entries:

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

Now you’ll post a blog entry.

Posting a Blog Entry

The GraphQL schema revealed the call that must be made to post a blog entry.

  1. Construct a JSON document containing the entry you wish to publish:

    {
      "blog": {
          "articleBody": "This Blog entry was created by calling the GraphQL service!",
          "headline": "GraphQL Blog Entry"
      }
    }
    
  2. Construct the GraphQL query based on the schema documentation:

    mutation CreateBlog($blog: InputBlogPosting){
      createSiteBlogPosting(blogPosting: $blog, siteKey: "20122" ) {
        headline
        articleBody
        id
        friendlyUrlPath
      }
    
     }
    
  3. Make the request by visiting http://localhost:8080/o/api again. Click the Show GraphQL button.

  4. Paste your JSON document into the Query Variables box at the lower left.

  5. Paste your mutation in the unlabeled box at the top right.

  6. 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:

The GraphQL client makes it easy to call GraphQL services directly from your browser.

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

{
  "data": {
    "createSiteBlogPosting": {
      "headline": "GraphQL Blog Entry",
      "articleBody": "This Blog entry was created by calling the GraphQL service!",
      "id": 35541,
      "friendlyUrlPath": "graphql-blog-entry"
    }
  }
}
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: \"20122\" ) { 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:"20122",sort:"")
	{page
     items {
        id
  		articleBody
  		headline
  		creator
  			{name
            }
  }
  }
}

Liferay DXP returns JSON containing the blog entry you posted:

{
  "data": {
    "blogPostings": {
      "page": 1,
      "items": [
        {
          "id": 35541,
          "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 just the post you want:

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

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

{
  "data": {
    "blogPosting": {
      "id": 35541,
      "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: 35541)
}

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.

Capability: