developers samen naar scherm aan het kijken
CONTENT & SAMENWERKINGSOFTWARE DEVELOPMENTLIFERAY
22/02/2020 • Cedric Dunon

Hoe de Liferay 7.2 headless APIs gebruiken voor custom objecten

Introductie van jullie nieuwe plaatselijke pizzeria

Liferay 7.2 headless API's openen een breed scala aan mogelijkheden, zelfs als het gaat om aangepaste objecten. Stel je voor dat er net een nieuw restaurant in de stad is geopend en ze serveren de heerlijkste pizza's. Helaas hebben zij, aangezien zij pas zijn geopend, nog niet de tijd of de middelen gehad om te investeren in een gloednieuwe professionele website. Voorlopig heeft de zoon van de eigenaar, die nog studeert, een kleine Angular applicatie in elkaar gezet om hun menu online te zetten.

pizza shop

Deze applicatie is echter niet gekoppeld aan een repository of een back-end applicatie, wat betekent dat ze niets aan hun menu kunnen toevoegen of wijzigen. Dit is nogal lastig: vanwege de huidige pandemie moesten zij overschakelen op een bezorgsysteem en willen zij hun website regelmatig kunnen bijwerken.

Na het horen van dit kleine scenario, herinner je je net dat je ergens een Liferay 7.2 portal hebt draaien en je vraagt je af of je, gebruikmakend van de nieuwe headless API's, zou kunnen ingrijpen en hen helpen.

Toen je contact opnam met het restaurant, kwam je erachter dat hun eisen vrij simpel waren:

  • Zij hebben een overzicht nodig van hun werknemers die leveringen kunnen doen en moeten weten wanneer zij een vrije dag nemen.
  • Ze moeten items op hun menu kunnen toevoegen of wijzigen.

En toen was er Liferay 7.2 headless APIs

Er is al een interessante blogpost geschreven waarin dit onderwerp wordt geïntroduceerd. Maar in een notendop zou je kunnen zeggen dat deze headless API's veel van Liferay's ingebouwde functies en inhoud gemakkelijk beschikbaar maken, klaar voor gebruik in een aangepaste front-end applicatie, smart device, IoT apparaten, etc.

Alle beschikbare Liferay eindpunten worden geleverd met swagger documentatie. Die kun je hier vinden. Zoals je kunt zien zijn er veel verschillende domeinen die Liferay ons ter beschikking heeft gesteld. Voor het doel van deze blog zal ik echter een korte blik werpen op de Headless Admin User en Headless Delivery.

De requirements in kaart brengen

Het doel van deze oefening is met zo weinig mogelijk inspanning te voldoen aan de eisen van onze klant. Dat betekent natuurlijk dat we de beschikbare eindpunten en de ingebouwde functies van Liferay ten volle zullen benutten.

Het werknemersoverzicht

Dit overzicht zal alleen wat basisinformatie bevatten, zoals:

  • Volledige naam
  • Een e-mail adres
  • Hun vrije dag
  • Of ze wel of niet pizza's kunnen bezorgen

Als je de Headless Admin User van dichterbij bekijkt, zie je een eindpunt dat alle gebruikers-accounts van een bepaalde site ophaalt:

/o/headless-admin-user/v1.0/sites/{siteId}/user-accounts

Als we de werknemers behandelen als gebruikers van een site, kunnen we hun informatie delen met de Angular applicatie. Om aan de volledige eis te voldoen, zullen wij onze Gebruikers met 2 aangepaste velden moeten verrijken:

  • Vrije dag - dat kan een uitklaplijst zijn
  • Pizza bezorger - dat zal waarschijnlijk een waar/niet waar vlag zijn.

De headless endpoints blootstellen

Nu we een manier hebben bedacht om aan een van de eisen van het restaurant te voldoen, moeten we ervoor zorgen dat onze Angular applicatie dit ook daadwerkelijk kan doen zonder geblokkeerd te worden. We zullen een beetje configuratie moeten doen in ons portaal:

pizzashop app built in Liferay

Zoals je in dit voorbeeld kunt zien, heb ik alle eindpunten betreffende headless-delivery en headless-admin-user blootgelegd. Om voor de hand liggende redenen wil je dat natuurlijk beperken tot de eindpunten die je zichtbaar kunt laten.

Aanvullende informatie over geauthenticeerde verzoeken is te vinden op Liferay's officiële site.

Extractie van relevante informatie

Als we alle gebruikers van onze gewenste site ophalen, krijgen we het volgende antwoord voor elke gebruiker:

pizzashop app liferay code

Zoals je ziet, bevat dit antwoord alle informatie die wij nodig hebben, maar ook een heleboel overbodige informatie. We kunnen ons antwoord beperken tot alleen de velden die we nodig hebben door ze toe te voegen aan ons verzoek:

/o/headless-admin-user/v1.0/sites/{siteId}/user-accounts?fields=alternateName,customFields,emailAddress,name

Dat resulteert in het volgende antwoord voor elke gebruiker:

pizzashop app liferay code

Met behulp van dit antwoord kan de Angular applicatie het vereiste overzicht genereren:

liferay response in angular

Een nadeel van deze aanpak is dat je beperkt bent tot het domein model van Liferay. Je zult de JSON-respons handmatig moeten parsen of je model aan dat van Liferay moeten aanpassen, wat in het geval van deze aangepaste velden een heel gedoe kan zijn.

Creëer je aangepaste objecten?

Om het medewerkersoverzicht te maken, maakten we gebruik van de Liferay Users, die we in dit geval perfect konden aansluiten op de vraag van onze klant. Hoewel Liferay een grote verscheidenheid aan eindpunten biedt die gebruikt kunnen worden om aan de eisen van je klant te voldoen, zal dit niet altijd het geval zijn.

Neem bijvoorbeeld de pizza's op ons menu. Die zouden de volgende informatie moeten bevatten:

  • De naam van de pizza
  • Een korte beschrijving
  • Hoe pikant
  • Extra toppings
  • Of de pizza wel of niet bezorgd kan worden

Er is geen manier om deze informatie op een bestaand Liferay object te plaatsen. We zullen dus zelf zo'n object moeten maken. Bij voorkeur willen we deze objecten via de headless API blootstellen met zo weinig mogelijk inspanning. Aangezien Liferay ons nog niet gezegend heeft met de mogelijkheid om aangepaste objecten te maken met hun API's, zullen we hier een omweg moeten vinden.

Die goede oude web inhoudsartikelen

Als je bekend bent met Liferay's web inhoudsartikelen, dan weet je dat een web inhoudsartikel gebruik maakt van een 'Structure'. Een structuur is iets wat we zelf kunnen creëren en zo de velden ervan kunnen definiëren. We zouden bijvoorbeeld de volgende pizzastructuur kunnen maken:

pizzashop app structure in Liferay

Met deze structuren zijn wij in staat om onze verschillende pizza's te creëren in de vorm van web inhoudsartikelen. Aangezien een web inhoudsartikel een ingebouwde functie van Liferay is, moet er wel een eindpunt zijn dat ze blootstelt, namelijk:

/o/headless-delivery/v1.0/content-structures/{contentStructureId}/structured-contents

Maar, en je raadt het waarschijnlijk al, ook dit geeft ons een hoop overbodige informatie. We zullen dus de relevante velden aan het verzoek moeten toevoegen:

/o/headless-delivery/v1.0/content-structures/{contentStructureId}/structured-contents?fields=contentFields.name,contentFields.value.data

Dat resulteert in het volgende antwoord:

pizzashop app liferay code

Met behulp van dit antwoord genereert de Angular applicatie het vereiste menu:

pizzashop app response in Angular application

Is er geen manier om een aangepaste reactie te maken?

Zoals je misschien hebt opgemerkt, hebben we in het bovenstaande voorbeeld nog steeds te maken met het nadeel van het handmatig parsen. Idealiter zouden we ook het antwoord kunnen definiëren. En toevallig kunnen we dat... zij het met een omweg. Web inhoudsartikelen maken niet alleen gebruik van structuren, maar ook van sjablonen. En net als bij structuren, kunnen we ook deze sjablonen definiëren.

Onze plaatselijke pizzeria heeft besloten om pasta's op het menu te zetten. Bovendien willen we ons deze keer niet meer bezighouden met handmatig parsen. We zouden graag gebruik maken van Angular's interfaces om dit automagisch te doen. Stel je voor dat de volgende interface in je Angular applicatie is:

pizzashop custom response liferay code

We zouden in Liferay een sjabloon "Pasta" kunnen definiëren dat overeenkomt met deze interface, bijvoorbeeld:

pizzashop app pasta option added in liferay

Nu hebben we alleen nog een eindpunt nodig dat ons sjabloon gebruikt en gelukkig voor ons bestaat dat:

headless-delivery/v1.0/structured-contents/{structuredContentId}/rendered-content/{templateId}

Dat resulteert in het volgende antwoord...

pizzashop app endpoint template code

... dat gebruikt kan worden om het menu in te vullen in de Angular applicatie:

pizzashop app angular application with endpoint template

Filteren, sorteren en zoeken

Een andere geweldige ingebouwde functie is de mogelijkheid om een filter, sortering of zoekopdracht toe te voegen aan een verzoek. Dat betekent dat Liferay's headless API dit voor je regelt. Hier zijn enkele voorbeelden:

Sorteren op titel

/o/headless-delivery/v1.0/content-structures/{contentStructureId}/structured-contents?sort=title:desc

Zoeken naar artikelen met 'Bolognese'

/o/headless-delivery/v1.0/content-structures/{contentStructureId}/structured-contents?search='Bolognese'

Filteren op titel

/o/headless-delivery/v1.0/content-structures/{contentStructureId}/structured-contents?filter=title eq 'Pizza Palermitana'

Door de velden leeg te laten wordt alleen de pagineringsinformatie teruggegeven, inclusief het totale aantal objecten dat door het verzoek is gevonden.

/o/headless-delivery/v1.0/content-structures/{contentStructureId}/structured-contents?fields=

Meer informatie over filteren, sorteren en zoeken vind je hier. Disclaimer: Filteren, sorteren en zoeken kunnen niet gebruikt worden wanneer je je eigen sjabloon gebruikt. Daar is echter ook een workaround voor, zij het met het nadeel dat je 1 + n verzoeken moet doen: Je kunt je items sorteren/filteren/zoeken met behulp van de standaard respons van Liferay, die een URL bevat die je naar je aangepaste respons zal leiden:

/o/headless-delivery/v1.0/content-structures/{contentStructureId}/structured-contents?fields=renderedContents.renderedContentURL'

Hoe zit het met de contentstructureId en de templateId?

Het is waar dat wanneer je een nieuwe structuur of een nieuw sjabloon maakt, de Id ervan on the fly wordt gegenereerd. Maar voor elk klein probleem is er een oplossing. Voor dit probleem in het bijzonder, zijn er twee mogelijke benaderingen:

  • je structuur en sjabloon programmatisch aanmaken, wat betekent dat je de ID van je structuur en sjabloon kunt definiëren;
  • of met behulp van content sets, wat een nieuwe ingebouwde functie is van Liferay 7.2.

Aangezien we zo weinig mogelijk moeite willen doen, gaan we voor optie nummer 2: inhoudsets.

Zonder al te veel in detail te treden, inhoudsets zijn in wezen wat ze lijken: een verzameling inhoud die door een beheerder kan worden gedefinieerd. Gelukkig voor ons kunnen wij bijvoorbeeld een verzameling maken van alle web inhoudsartikelen op basis van één of meer structuren. Dit betekent dat we van al onze pizza's en pasta's een inhoudsset kunnen maken, waarmee je ook filtering en bestelling via het bedieningspaneel kunt toevoegen.

pizzashop app built-in feature liferay 7.2.

Je voelt misschien al waar ik heen wil. Ja, er is ook een eindpunt dat ons in staat stelt om de web inhoudsartikelen te krijgen via de content set:

o/headless-delivery/v1.0/sites/{siteId}/content-sets/by-key/{key}/content-set-elements

De sleutel wordt gegenereerd op basis van de naam van de inhoudset, waarbij de spaties worden vervangen door een koppelteken. Gesorteerde pizza's en pasta's zou de sleutel "gesorteerde-pizza's-en-pasta's" genereren. Meer informatie en hoe je een inhoudsset kunt maken, vind je hier.

Liferay 7.2 headless APIs: conclusie

Zonder twijfel hebben Liferay 7.2 headless API's het potentieel om aangepaste oplossingen te verrijken met de Liferay functies die we hebben leren kennen en liefhebben. Echter, met de introductie van deze headless API's had ik gehoopt dat we een ingebouwde mogelijkheid zouden hebben om gemakkelijk onze eigen aangepaste objecten te maken en de mogelijkheid om ze bloot te stellen via speciale API's. Dat gezegd hebbende, de mogelijkheid om deze functie enigszins te reproduceren door middel van web inhoudsartikelen en hun headless APIs getuigt van de flexibiliteit en uitbreidbaarheid van Liferay zelf.

Ik kijk al uit naar wat ze nog meer voor ons in petto hebben!