Using Relationship REST APIs
Liferay 7.4 U70+/GA70+
When you add relationships to custom or system objects, Liferay generates REST endpoints for accessing those relationships. You can relate and disassociate entries, as well as return an entry’s related entries. These endpoints are added to the parent object in one-to-many relationships and to both objects in many-to-many relationships.
To proceed, set up a new Liferay 7.4 instance and prepare the provided tutorial code. Then, run the scripts to create object entries and manage their relationships with one another.
Setting Up a Liferay Instance
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.
Next, create three related custom objects:
-
Open the Global Menu (), go to the Control Panel tab, and click Objects.
-
Create three object drafts.
First Object:
Field Value Label Able
Plural Label Ables
Name Able
Second Object:
Field Value Label Baker
Plural Label Bakers
Name Baker
Third Object:
Field Value Label Charlie
Plural Label Charlies
Name Charlie
-
Add the
name
field to each object draft.Label Field Name Type Required Name
name
Text ✔ -
Add these relationships to the able object:
Label Relationship Name Type Object Able to Baker
ableToBaker
One to Many Baker Able to Charlie
ableToCharlie
One to Many Charlie -
Publish each object.
Once published, you can access their REST APIs, including the following relationship APIs:
Object | HTTP Method | HTTP Endpoint | Java Method |
---|---|---|---|
Able | GET | /{ableId}/ableToBaker | getAbleAbleToBakerBakerPage |
Able | GET | /{ableId}/ableToCharlie | getAbleAbleToCharlieCharliePage |
Able | DELETE | /{ableId}/ableToBaker/{bakerId} | deleteAbleAbleToBakerBaker |
Able | PUT | /{ableId}/ableToBaker/{bakerId} | putAbleAbleToBakerBaker |
Able | DELETE | /{ableId}/ableToCharlie/{charlieId} | deleteAbleAbleToCharlieCharlie |
Able | PUT | /{ableId}/ableToCharlie/{charlieId} | putAbleAbleToCharlieCharlie |
Able | PUT | /by-external-reference-code/{ableERC}/ableToBaker/{bakerERC} | putAbleAbleToBakerBaker |
Able | PUT | /by-external-reference-code/{ableERC}/ableToCharlie/{charlieERC} | putAbleAbleToCharlieCharlie |
Charlie | GET | /{charlieId}/ableToCharlie | getCharlieAbleToCharlieAblePage |
Charlie | DELETE | /{charlieId}/ableToCharlie/{ableId} | deleteCharlieAbleToCharlieAble |
Charlie | PUT | /{charlieId}/ableToCharlie/{ableId} | putCharlieAbleToCharlieAble |
Charlie | PUT | /by-external-reference-code/{ableERC}/ableToCharlie/{charlieERC} | putCharlieAbleToCharlieAble |
For a complete list of APIs generated for site and company objects, see Objects Headless Framework Integration. You can view and test custom Object APIs via the Liferay API Explorer at [server]:[port]/o/api
(e.g., localhost:8080/o/api
). Click REST Applications and select an API.
Preparing the Sample Code
Run these commands to download and unzip the provided sample code:
curl https://resources.learn.liferay.com/dxp/latest/en/building-applications/objects/understanding-object-integrations/using-custom-object-apis/liferay-f9m2.zip -O
unzip liferay-f9m2.zip
The sample code includes commands for creating entries for each object and using their relationship APIs.
Using the Sample Code
Use the REST APIs to add object entries and manage their relationships:
-
Navigate to the
curl
folder in theliferay-f9m2
project.cd liferay-f9m2/curl
-
Run
POST
commands to create three entries for each object. These entries have predefined external reference codes (ERCs) following the[objectname]-[number]
naming pattern (e.g.,able-one
)../Able_POST_Batch.sh
./Baker_POST_Batch.sh
./Charlie_POST_Batch.sh
-
Run
Able_PUT_AbleToBaker_ByExternalReferenceCode
with theable-one
ERC and all three baker ERCs../Able_PUT_AbleToBaker_ByExternalReferenceCode.sh able-one baker-one baker-two baker-three
This relates the able entry with the baker entries and prints the response.
{ ... "externalReferenceCode" : "baker-one", "id" : 42427, ... "name" : "Baker 1", "r_ableToBaker_c_ableId" : 42421, "r_ableToBaker_c_ableERC" : "able-one" } { ... "externalReferenceCode" : "baker-two", "id" : 42429, ... "name" : "Baker 2", "r_ableToBaker_c_ableId" : 42421, "r_ableToBaker_c_ableERC" : "able-one" } { ... "externalReferenceCode" : "baker-three", "id" : 42431, ... "name" : "Baker 3", "r_ableToBaker_c_ableId" : 42421, "r_ableToBaker_c_ableERC" : "able-one" }
-
Run
Able_DELETE_AbleToBaker_ById
with two IDs: the ID forable-one
and the ID forbaker-three
../Able_DELETE_AbleToBaker_ById.sh {able-entry-id} {baker-entry-id}
This disassociates the entries.
-
Run
Able_GET_AbleToBaker_ById
with the same able ID to confirm they are no longer related../Able_GET_AbleToBaker_ById.sh {able-entry-id}
{ ... "externalReferenceCode" : "baker-two", "id" : 42429, ... "name" : "Baker 2", "r_ableToBaker_c_ableId" : 42421, "r_ableToBaker_c_ableERC" : "able-one" }, { ... "externalReferenceCode" : "baker-one", "id" : 42427, ... "name" : "Baker 1", "r_ableToBaker_c_ableId" : 42421, "r_ableToBaker_c_ableERC" : "able-one" }
-
Run
Able_PUT_AbleToCharlie_ByExternalReferenceCode
with theable-one
ERC and all three charlie ERCs../Able_PUT_AbleToCharlie_ByExternalReferenceCode.sh able-one charlie-one charlie-two charlie-three
This relates the able entry with the charlie entries and prints the response.
{ ... "externalReferenceCode" : "charlie-one", "id" : 42433, ... "name" : "Charlie 1" } { ... "externalReferenceCode" : "charlie-two", "id" : 42435, ... "name" : "Charlie 2" } { ... "externalReferenceCode" : "charlie-three", "id" : 42437, ... "name" : "Charlie 3" }
-
Run
Charlie_GET_AbleToCharlie_ById
with the ID forcharlie-one
../Charlie_GET_AbleToCharlie_ById.sh {charlie-entry-id}
This returns a list of all able entries related to the specified charlie entry.
{ ... "items" : [ { ... "externalReferenceCode" : "able-one", "id" : 42421, ... "name" : "Able 1" } ], "lastPage" : 1, "page" : 1, "pageSize" : 1, "totalCount" : 1 }
-
Run
Charlie_PUT_AbleToCharlie_ByExternalReferenceCode
with thecharlie-one
andable-two
ERCs../Charlie_PUT_AbleToCharlie_ByExternalReferenceCode.sh charlie-one able-two
This relates the charlie entry to another able entry.
{ ... "externalReferenceCode" : "able-two", "id" : 42423, ... "name" : "Able 2" }
-
Run
Charlie_GET_AbleToCharlie_ById
with the ID forcharlie-one
and confirm there are now two related able entries../Charlie_GET_AbleToCharlie_ById.sh {charlie-entry-id}
{ ... "items" : [ { ... "externalReferenceCode" : "able-two", "id" : 42423, ... "name" : "Able 2" }, { ... "externalReferenceCode" : "able-one", "id" : 42421, ... "name" : "Able 1" } ], "lastPage" : 1, "page" : 1, "pageSize" : 2, "totalCount" : 2 }
-
Run
Able_GET_ById
with the ID forable-one
../Able_GET_ById.sh {able-entry-id}
This command uses the
nestedFields
parameter to return all related baker and charlie entries.{ "externalReferenceCode" : "able-one", "id" : 42421, ... "ableToCharlie" : [ { ... "externalReferenceCode" : "charlie-one", "id" : 42433, ... "name" : "Charlie 1" }, { ... "externalReferenceCode" : "charlie-two", "id" : 42435, ... "name" : "Charlie 2" }, { ... "externalReferenceCode" : "charlie-three", "id" : 42437, ... "name" : "Charlie 3" } ], "name" : "Able 1", "ableToBaker" : [ { ... "externalReferenceCode" : "baker-one", "id" : 42427, ... "name" : "Baker 1", "r_ableToBaker_c_ableId" : 42421, "r_ableToBaker_c_ableERC" : "able-one" }, { ... "externalReferenceCode" : "baker-two", "id" : 42429, ... "name" : "Baker 2", "r_ableToBaker_c_ableId" : 42421, "r_ableToBaker_c_ableERC" : "able-one" } ] }
See Using nestedFields to Query Related Entries for more information on the
nestedFields
parameter.
Examining the Code
Charlie_PUT_AbleToCharlie_ByExternalReferenceCode
curl \
"http://localhost:8080/o/c/charlies/by-external-reference-code/${1}/ableToCharlie/${2}" \
--header "Content-Type: application/json" \
--request "PUT" \
--user "test@liferay.com:learn"
Charlie_GET_AbleToCharlie_ById
curl \
"http://localhost:8080/o/c/charlies/${1}/ableToCharlie" \
--header "Content-Type: application/json" \
--user "test@liferay.com:learn"
Able_DELETE_AbleToBaker_ById
curl \
"http://localhost:8080/o/c/ables/${1}/ableToBaker/${2}" \
--header "Content-Type: application/json" \
--request "DELETE" \
--user "test@liferay.com:learn"
Able_GET_ById.sh
curl \
"http://localhost:8080/o/c/ables/${1}/?nestedFields=ableToBaker,ableToCharlie" \
--user "test@liferay.com:learn"