{"id":27810,"date":"2024-05-27T05:00:00","date_gmt":"2024-05-27T03:00:00","guid":{"rendered":"https:\/\/sii.pl\/blog\/?p=27810"},"modified":"2024-05-27T08:14:48","modified_gmt":"2024-05-27T06:14:48","slug":"modulowosc-adobe-experience-manager","status":"publish","type":"post","link":"https:\/\/sii.pl\/blog\/modulowosc-adobe-experience-manager\/","title":{"rendered":"Modu\u0142owo\u015b\u0107 Adobe Experience Manager"},"content":{"rendered":"\n<p>Przejrzysta i zrozumia\u0142a architektura to jeden z kluczy do sukcesu w tworzeniu <a href=\"https:\/\/ieeexplore.ieee.org\/document\/6417020\" target=\"_blank\" aria-label=\"oprogramowania (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >oprogramowania<\/a><a id=\"_ftnref1\" href=\"#_ftn1\" rel=\"nofollow\" >[1]<\/a>. Architekci i deweloperzy podejmuj\u0105 dziesi\u0105tki decyzji architektonicznych dziennie. W skomplikowanym \u015brodowisku, w kt\u00f3rym miesza si\u0119 wiele technologii, takie dzia\u0142ania poch\u0142aniaj\u0105 si\u0142y umys\u0142owe pracownik\u00f3w. Adobe Experience Manager bez w\u0105tpienia nale\u017cy do kategorii \u201eskomplikowane\u201d. <\/p>\n\n\n\n<p>W tym artykule przedstawi\u0119 <strong>koncepcj\u0119 modu\u0142\u00f3w i granic pomi\u0119dzy nimi<\/strong>, dzi\u0119ki czemu w d\u0142u\u017cszej perspektywie dostarczanie dopasowanego systemu komponent\u00f3w w ramach AEM jest mniej stresuj\u0105ce i \u0142atwiejsze do zmiany.<\/p>\n\n\n\n<p>Do\u015bwiadczenie Sii w dostarczaniu system\u00f3w zarz\u0105dzania tre\u015bci\u0105 opartych na Adobe Experience Manager nauczy\u0142o nas my\u015blenia o stworzonym oprogramowaniu jako o zbiorze ruchomych cz\u0119\u015bci, kt\u00f3re mog\u0105 si\u0119 ze sob\u0105 \u0142\u0105czy\u0107 i konstruowa\u0107 rozwi\u0105zanie. Poni\u017cej przedstawi\u0119 Ci ten spos\u00f3b my\u015blenia: <strong>mistycyzm projektowania dobrej architektury bez zbytniego obci\u0105\u017cenia umys\u0142u zb\u0119dnymi decyzjami.<\/strong><\/p>\n\n\n\n<p>Ten wpis nie jest przeznaczony wy\u0142\u0105cznie dla specjalist\u00f3w AEM, ale tak\u017ce dla os\u00f3b, kt\u00f3re projektuj\u0105 wi\u0119ksze rozwi\u0105zania, w kt\u00f3rych AEM odgrywa rol\u0119 \u2013 os\u00f3b z rol\u0105 <em>solution architect<\/em> i podobnych.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Kr\u00f3tko o Adobe Experience Manager<\/strong><\/h2>\n\n\n\n<p>AEM to najlepsze rozwi\u0105zanie CMS na rynku, o ogromnej liczbie funkcji i zastosowa\u0144, obecnie dostarczane jako us\u0142uga w chmurze. W przesz\u0142o\u015bci firma Adobe udost\u0119pnia\u0142a AEM jako oprogramowanie uruchamiane na serwerach w\u0142a\u015bciciela licencji, a kilka lat p\u00f3\u017aniej klienci zainteresowali si\u0119 rozwi\u0105zaniem hybrydowym \u2013 <em>Adobe Managed Services<\/em> \u2013 w kt\u00f3rym firma Adobe hostowa\u0142a aplikacj\u0119 we w\u0142asnej chmurze.<\/p>\n\n\n\n<p>Mo\u017cna by pomy\u015ble\u0107, \u017ce te drastyczne zmiany w metodach wdra\u017cania powa\u017cnie wp\u0142yn\u0119\u0142y na rzeczywist\u0105 architektur\u0119 wewn\u0119trzn\u0105 AEM. Tak si\u0119 jednak nie sta\u0142o \u2013 Adobe postawi\u0142o sobie za cel utrzymanie jej w tej samej formie. W zwi\u0105zku z tym, w artykule wspominam o elementach, kt\u00f3re <strong>istniej\u0105 od wyj\u0105tkowo dawna<\/strong>, wi\u0119c nie musisz sprawdza\u0107, z kt\u00f3r\u0105 wersj\u0105 aktualnie pracujesz.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>AEM w oczach specjalist\u00f3w<\/strong><\/h3>\n\n\n\n<p><em>Solution architect<\/em> powinien my\u015ble\u0107 o AEM jako o serwerze WWW. Og\u00f3lnie rzecz bior\u0105c, AEM zapewnia interfejs u\u017cytkownika do tworzenia tre\u015bci, kt\u00f3re serwer udost\u0119pnia jako HTML\/JSON\/XML\/*.<\/p>\n\n\n\n<p>Architekt odpowiedzialny za implementacj\u0119 lub programista powinni my\u015ble\u0107 o nim, jako o zestawie komponent\u00f3w, kt\u00f3rymi mo\u017cna uformowa\u0107 stron\u0119 z kawa\u0142k\u00f3w o oczekiwanym formacie, pami\u0119taj\u0105c o poni\u017cszych istotnych faktach dotycz\u0105cych komponent\u00f3w:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><em>Content authors<\/em> lub inne bezosobowe podmioty, takie jak systemy zewn\u0119trzne, wype\u0142niaj\u0105 komponenty danymi \u2013 dzi\u0119ki czemu mo\u017cemy traktowa\u0107 komponent jako typ informacji, a komponent jako tre\u015b\u0107 okre\u015blonego typu.<\/li>\n\n\n\n<li>Komponenty mog\u0105 mie\u0107 wewn\u0105trz inne komponenty, wliczaj\u0105c w to siebie (ten sam typ komponentu).<\/li>\n\n\n\n<li>Komponent oddzia\u0142uje z innymi obiektami poza \u015bwiatem komponent\u00f3w \u2013 wyja\u015bni\u0119 to ni\u017cej:<\/li>\n<\/ul>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/page_structure.png\"><img decoding=\"async\" width=\"831\" height=\"348\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/page_structure.png\" alt=\"Komponenty zagnie\u017cd\u017cone w celu renderowania strony\" class=\"wp-image-27811\" style=\"object-fit:cover\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/page_structure.png 831w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/page_structure-300x126.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/page_structure-768x322.png 768w\" sizes=\"(max-width: 831px) 100vw, 831px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 1 Komponenty zagnie\u017cd\u017cone w celu renderowania strony<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Struktura przyk\u0142adowej strony<\/strong><\/h3>\n\n\n\n<p>Powy\u017cszy diagram przedstawia struktur\u0119 przyk\u0142adowej strony. Jest to oczywi\u015bcie bardzo uproszczony, ale wa\u017cny widok na ca\u0142\u0105 architektur\u0119 zastosowan\u0105 w AEM. Zagnie\u017cd\u017canie w komponentach mo\u017ce by\u0107 wymuszone (tak, aby komponent w \u015brodku by\u0142 \u201epodany\u201d przez rodzica) lub swobodne (to jest decyzja autora tre\u015bci, aby zagnie\u017adzi\u0107 ten lub inny komponent).<\/p>\n\n\n\n<p>W ten spos\u00f3b generuje si\u0119 HTML strony. G\u0142\u00f3wny <em>servlet <\/em>domy\u015blny wywo\u0142uje na najwy\u017cszym komponencie akcj\u0119 wyrenderowania siebie, a wywo\u0142any proces komponentu dodatkowo wywo\u0142a zagnie\u017cd\u017cone komponenty, je\u017celi takie istniej\u0105.<\/p>\n\n\n\n<p>Aby zweryfikowa\u0107 rozumienie tego konceptu, spr\u00f3bujmy co\u015b zepsu\u0107. Je\u015bli utworzysz komponent A, kt\u00f3ry zagnie\u017cd\u017ca B, a B zagnie\u017cd\u017ca si\u0119 z powrotem A, sko\u0144czy si\u0119 to niesko\u0144czon\u0105 p\u0119tl\u0105. Nie martw si\u0119 o \u015bmier\u0107 JVM-a \u2013 implementacja ma maksymaln\u0105 liczb\u0119 komponent\u00f3w wywo\u0142ywanych w ramach \u017c\u0105dania. Niemniej, jest to ciekawy eksperyment my\u015blowy, kt\u00f3ry sprawdzi zrozumienie tego mechanizmu.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/kill_aem.png\"><img decoding=\"async\" width=\"298\" height=\"388\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/kill_aem.png\" alt=\"Spos\u00f3b wprowadzenia p\u0119tli niesko\u0144czonej za pomoc\u0105 metody zagnie\u017cd\u017cania komponent\u00f3w \" class=\"wp-image-27813\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/kill_aem.png 298w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/kill_aem-230x300.png 230w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/kill_aem-170x220.png 170w\" sizes=\"(max-width: 298px) 100vw, 298px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 2 Spos\u00f3b wprowadzenia p\u0119tli niesko\u0144czonej za pomoc\u0105 metody zagnie\u017cd\u017cania komponent\u00f3w<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Komponenty<\/strong><\/h3>\n\n\n\n<p>Ta wiedza jest kluczowa do przetrawienia nast\u0119pnej sekcji \u2013 roz\u0142o\u017cymy komponent na czynniki pierwsze, dziel\u0105c pod wzgl\u0119dem u\u017cytej technologii.<\/p>\n\n\n\n<p>Je\u015bli spr\u00f3bujesz wyobrazi\u0107 sobie swoj\u0105 pierwsz\u0105 stron\u0119 <em>hello world<\/em> zaprojektowan\u0105 przy u\u017cyciu komponent\u00f3w \u2013 prawdopodobnie jest to komponent strony g\u0142\u00f3wnej, kt\u00f3ry b\u0119dzie renderowa\u0142 niezb\u0119dne tagi HTML i tekstowy, kt\u00f3ry wy\u015bwietla tekst.<\/p>\n\n\n\n<p><strong>Czy tak rzeczywi\u015bcie powinno by\u0107?<\/strong><\/p>\n\n\n\n<p>C\u00f3\u017c, do pewnego stopnia \u2013 tu m\u00f3wimy o najwi\u0119kszej zalecie AEM \u2013 poniewa\u017c Adobe Experience Manager zawiera naprawd\u0119 solidny zestaw gotowych do u\u017cycia komponent\u00f3w, zwanych <em><a href=\"https:\/\/www.aemcomponents.dev\/\" target=\"_blank\" aria-label=\"Core Components (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Core Components<\/a><\/em><a id=\"_ftnref1\" href=\"#_ftn1\" class=\"ek-link\" rel=\"nofollow\" >[2]<\/a>. Z mojego do\u015bwiadczenia klienci implementuj\u0105 statyczne tre\u015bci tymi gotowymi do u\u017cycia komponentami, z niewielkim dostosowaniem pod ich potrzeby i dopisaniem CSS. Nie brzmi to jak wyzwanie dla architekt\u00f3w czy deweloper\u00f3w, prawda?<\/p>\n\n\n\n<p>Prawdziwa zabawa zaczyna si\u0119, gdy musimy zapewni\u0107 <strong>naprawd\u0119 unikalne zachowanie na stronie<\/strong> \u2013 takie jak tre\u015b\u0107 wynikaj\u0105ca z innych tre\u015bci umieszczonych poza stron\u0105, bardziej z\u0142o\u017cone przetwarzanie danych utworzonych przez <em>content authors<\/em>, zmiana informacji w czasie lub korzystanie z innych \u017ar\u00f3de\u0142 danych poza AEM. Te ostatnie nazywamy integracjami (ang. <em>external system integration)<\/em>.<\/p>\n\n\n\n<p>Rzu\u0107my okiem na poj\u0119cie modu\u0142\u00f3w komponent\u00f3w w AEM \u2013 roz\u0142\u00f3\u017cmy komponent na cz\u0119\u015bci, kt\u00f3re mo\u017cemy zrozumie\u0107, podzieli\u0107 prac\u0119 w zespole i, co wa\u017cniejsze, zaprojektowa\u0107 \u2013 nie wchodz\u0105c w koszty implementacji, przynajmniej na jaki\u015b czas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Modu\u0142y komponentu w AEM<\/strong><\/h2>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/CoreDiagram.png\"><img decoding=\"async\" width=\"796\" height=\"589\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/CoreDiagram.png\" alt=\"Typy modu\u0142\u00f3w w programie Adobe Experience Manager i ich zale\u017cno\u015bci\" class=\"wp-image-27815\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/CoreDiagram.png 796w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/CoreDiagram-300x222.png 300w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/CoreDiagram-768x568.png 768w\" sizes=\"(max-width: 796px) 100vw, 796px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 3 Typy modu\u0142\u00f3w w programie Adobe Experience Manager i ich zale\u017cno\u015bci<\/figcaption><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>\u015awiaty Java, JavaScript i AEM<\/strong><\/h3>\n\n\n\n<p>Ten diagram mo\u017ce wydawa\u0107 si\u0119 zbyt skomplikowany, zatem przeanalizujmy go po kolei, zaczynaj\u0105c od poszczeg\u00f3lnych \u015bwiat\u00f3w (<em>worlds<\/em>):<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Java \u2013 zawiera dowolne oprogramowanie w j\u0119zyku programowania Java. To przestrze\u0144, w kt\u00f3rej zwykle rz\u0105dzi <em>back-end<\/em> deweloper.<\/li>\n\n\n\n<li>JavaScript \u2013 podobna przestrze\u0144 co Java, tylko przy u\u017cyciu JavaScript, z t\u0105 r\u00f3\u017cnic\u0105, \u017ce mo\u017ce by\u0107 zar\u00f3wno po stronie serwera, jak i po stronie przegl\u0105darki. Osoby zajmuj\u0105ce si\u0119 tym \u015bwiatem nazywane s\u0105 zazwyczaj <em>front-end<\/em> deweloperami.<\/li>\n\n\n\n<li>AEM World \u2014 <strong>ziemia niczyja<\/strong>, niespotykana poza AEM. Zazwyczaj jest to zestaw komponent\u00f3w lub ich okien dialogowych (kt\u00f3re r\u00f3wnie\u017c s\u0105 komponentami!), kt\u00f3re mog\u0105 by\u0107 obs\u0142ugiwane jako konfiguracje XML, pliki HTL oraz podstawowa jednostka wdro\u017ceniowa \u2013 pakiet. Zasadniczo zajmuj\u0105 si\u0119 nimi zar\u00f3wno <em>back-end<\/em> jak i <em>front-end<\/em> deweloperzy, w zale\u017cno\u015bci od przekazanego im zadania.<\/li>\n<\/ul>\n\n\n\n<p>Ta separacja \u015bwiat\u00f3w pomaga architektowi zrozumie\u0107 podzia\u0142 pracy pomi\u0119dzy in\u017cynier\u00f3w specjalizuj\u0105cych si\u0119 w r\u00f3\u017cnych dziedzinach. Rzadko zdarza si\u0119, aby jeden in\u017cynier by\u0142 w stanie profesjonalnie opanowa\u0107 wszystkie te trzy \u015bwiaty r\u00f3wnocze\u015bnie. Architekt musi wi\u0119c zebra\u0107 dru\u017cyn\u0119, aby wyruszy\u0107 w t\u0119 podr\u00f3\u017c.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Komunikacja mi\u0119dzy \u015bwiatami<\/strong><\/h3>\n\n\n\n<p>Prze\u015bled\u017amy, jak \u015bwiaty komunikuj\u0105 si\u0119 ze sob\u0105:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Java Use lub JS Use w skryptach \u2013 w ten spos\u00f3b mo\u017cemy uzyska\u0107 dost\u0119p do \u015bwiat\u00f3w Java\/JavaScript z AEM. Skrypt mo\u017ce wywo\u0142ywa\u0107 metody obiekt\u00f3w lub funkcje modu\u0142\u00f3w do renderowania odpowiedzi.<\/li>\n\n\n\n<li>Do\u0142\u0105czenie biblioteki klienta (z AEM do JavaScript) do skryptu w celu do\u0142\u0105czenia \u0142\u0105cza do zasobu CSS lub JS dla przegl\u0105darki.<\/li>\n\n\n\n<li>Wywo\u0142anie serwisu OSGi z JavaScript Use \u2013 JavaScript do Java<\/li>\n<\/ul>\n\n\n\n<p>Innymi s\u0142owy, obiekty r\u00f3\u017cnych \u015bwiat\u00f3w komunikuj\u0105 si\u0119 <strong>poprzez identyfikatory i wywo\u0142ywanie funkcji\/metod<\/strong> na dost\u0119pnych abstrakcjach.<\/p>\n\n\n\n<p><strong>Na marginesie:<\/strong> istniej\u0105 inne sposoby komunikowania si\u0119 mi\u0119dzy \u015bwiatami (takie jak dost\u0119p do danych za po\u015brednictwem obiekt\u00f3w <em>Session<\/em> lub <em>ResourceResolver<\/em> i ich przechowywanie), jednak nie s\u0105 one cz\u0119\u015bci\u0105 zwyk\u0142ego renderowania, dlatego nie s\u0105 zalecane ani u\u017cywane w rozwi\u0105zywaniu problem\u00f3w zwykle obecnych w AEM.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Komponent AEM<\/strong><\/h3>\n\n\n\n<p>Przyjrzyjmy si\u0119 teraz najwa\u017cniejszej abstrakcji w AEM \u2013 komponentowi AEM. Wyr\u00f3\u017cniaj\u0105 go nast\u0119puj\u0105ce cechy:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Zagnie\u017cd\u017canie<\/strong>. Komponent mo\u017ce zagnie\u017cd\u017ca\u0107 inny komponent.<\/li>\n\n\n\n<li><strong>Tworzenie skrypt\u00f3w<\/strong>. Komponent mo\u017ce wskaza\u0107, jaki rodzaj skryptu renderuje dane wyj\u015bciowe (zwykle HTML). Istniej\u0105 inne opcje skrypt\u00f3w, takie jak JSP, jednak nie zaleca si\u0119 ich u\u017cywania \u2013 s\u0105 przestarza\u0142\u0105 metod\u0105 skryptow\u0105.<\/li>\n\n\n\n<li><strong>Konfigurowanie<\/strong>. Sk\u0142adnik ma swoje okno dialogowe, kt\u00f3re umo\u017cliwia autorom tre\u015bci wprowadzanie danych (takich jak tekst lub inne informacje, kt\u00f3re maj\u0105 wp\u0142yw na renderowanie sk\u0142adnika.<\/li>\n<\/ul>\n\n\n\n<p>Wspomnia\u0142em w powy\u017cszych akapitach, jak wa\u017cna jest rola komponentu. Je\u015bli uznamy komponent za korze\u0144 pewnego zestawu komponent\u00f3w, otrzymamy struktur\u0119 drzewa, kt\u00f3ra dobrze wsp\u00f3\u0142gra z HTML i podobnymi strukturami danych. Zagnie\u017cd\u017canie jest funkcj\u0105, kt\u00f3ra jest ca\u0142kowicie kontrolowana przez sam komponent. Istnieje dodatkowe rozszerzenie: komponent o nazwie &#8222;parsys&#8221; (system akapit\u00f3w), ale generalnie architekt powinien wiedzie\u0107, \u017ce jest spos\u00f3b na wskazanie miejsca, w kt\u00f3ry mo\u017cna umie\u015bci\u0107 inne komponenty na etapie tworzenia tre\u015bci.<\/p>\n\n\n\n<p>T\u0105 sam\u0105 funkcj\u0119 architekt mo\u017ce zaprojektowa\u0107 jako komponent zagnie\u017cd\u017caj\u0105cy lub kompletnie samodzielny, tj. bez zagnie\u017cd\u017cania innych komponent\u00f3w. Ci\u0119\u017cko jest oceni\u0107 u\u017cyteczno\u015b\u0107 struktury, nie uwzgl\u0119dniaj\u0105c kontekstu i standardu domeny klienta.<\/p>\n\n\n\n<p>Nie wyobra\u017cam sobie komponentu galerii bez wewn\u0119trznych komponent\u00f3w reprezentuj\u0105cych poszczeg\u00f3lne kafelki, cho\u0107 i takie implementacje maj\u0105 czasem zastosowanie. Z drugiej strony, komponent tekstowy nie powinien mie\u0107 zagnie\u017cd\u017conego innego komponentu, chyba, \u017ce nie interesuje nas poniesienie dodatkowych koszt\u00f3w utrzymania takiego rozwi\u0105zania.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>AEM Packages<\/strong><\/h3>\n\n\n\n<p>Dos\u0142ownie <em>AEM<\/em> <em>packages <\/em>(paczki AEM-owe) s\u0105 plikami ZIP, kt\u00f3re zawieraj\u0105 dane JCR, ale z naszej perspektywy architektonicznej pakiet zawiera zestaw komponent\u00f3w, kt\u00f3re mo\u017cna z\u0142o\u017cy\u0107 w jeden pakiet instalacyjny. Paczki maj\u0105 swoje wersje i nazwy, co pozwala na prost\u0105 aktualizacj\u0119 podczas wdra\u017cania, tj. zast\u0105pienie tych samych komponent\u00f3w innymi wersjami.<\/p>\n\n\n\n<p>W naszym przypadku paczka instaluje przygotowane komponenty w \u015brodowisku AEM.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Skrypt<\/strong><\/h3>\n\n\n\n<p>Skrypt jest zwykle kodem HTL (jak wspomnia\u0142em wcze\u015bniej: rzadziej JSP), kt\u00f3ry przekszta\u0142ca si\u0119 w odpowied\u017a HTML. Wykonywanie skryptu jest oparte na webowym <em>request-response<\/em>, co oznacza, \u017ce mo\u017ce mie\u0107 warunki specyficzne dla kontekstu przetwarzania zapytania.<\/p>\n\n\n\n<p>Rozwa\u017cmy ten przyk\u0142ad:<\/p>\n\n\n<div class=\"wp-block-syntaxhighlighter-code \"><pre class=\"brush: xml; title: ; notranslate\" title=\"\">\n&lt;sly data-sly-use.related=&quot;com.sii.RelatedPages&quot;&gt;\n${properties.name}\n    &lt;ul data-sly-list.page=&quot;${related.list}&quot;&gt;\n        &lt;li&gt;&lt;a href=&quot;${related.path}&quot;&gt;${page.name}&lt;\/a&gt;&lt;\/li&gt;\n    &lt;\/ul&gt;\n&lt;\/sly&gt;\n<\/pre><\/div>\n\n\n<p>Wygl\u0105da to jak zwyk\u0142y fragment kodu HTML z dodatkowym <em>sly<\/em> tagiem i dodatkowymi atrybutami<em> data-sly-*<\/em> . Te dodatkowe tagi przetwarzane s\u0105 na pozomie backendu i wykonuj\u0105 dodatkowe dzia\u0142ania na HTML. W powy\u017cszym przyk\u0142adzie otrzymujemy Sling Model lub Java Use (w tym momencie tego nie wiemy) i otrzymujemy z niego list\u0119 za pomoc\u0105 metody <em>list<\/em> i wy\u015bwietlamy ka\u017cdy link do strony z jego nazw\u0105 na li\u015bcie nieuporz\u0105dkowanej. <em>Properties<\/em> jest obiektem domy\u015blnym zawieraj\u0105cy zapisane informacje, kt\u00f3re <em>content author<\/em> wprowadza bezpo\u015brednio w instancji komponentu.<\/p>\n\n\n\n<p>Jest to <strong>podstawowa koncepcja wykorzystywania skrypt\u00f3w w AEM<\/strong> \u2013 wchod\u017a w interakcj\u0119 z innymi \u015bwiatami, definiuj warunki renderowania i uruchamiaj je.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Sling Model \/ Java Use \/ JavaScript Use<\/strong><\/h3>\n\n\n\n<p>Te trzy rodzaje obiekt\u00f3w opieraj\u0105 si\u0119 na r\u00f3\u017cnych technologiach, ale realizuj\u0105 ten sam przypadek u\u017cycia. S\u0105 one przeznaczone do interakcji innych \u015bwiat\u00f3w w skryptach. G\u0142\u00f3wnym problemem architekta jest <strong>rozwi\u0105zanie dylematu odpowiedzialno\u015bci<\/strong>: czy te obiekty powinny by\u0107 wy\u0142\u0105cznie po\u015brednikami do innych \u015bwiat\u00f3w, czy same powinny przetwarza\u0107 dane i realizowa\u0107 logik\u0119 komponent\u00f3w. W innym przypadku te zadania mo\u017cna przekaza\u0107 bardziej og\u00f3lnym modu\u0142om JS lub klasom Java.<\/p>\n\n\n\n<p>Zazwyczaj projektanci system\u00f3w wykorzystuj\u0105 fakt, \u017ce mog\u0105 zaimplementowa\u0107 wi\u0119kszo\u015b\u0107 funkcji przetwarzania danych w tych obiektach i s\u0105 one \u015bci\u015ble zwi\u0105zane z komponentami, kt\u00f3re ich u\u017cywaj\u0105. Z drugiej strony przydatne jest, gdy Twoje <em>Sling Models<\/em>, klasy <em>Java Use<\/em> i modu\u0142y <em>JS Use<\/em> s\u0105 wsp\u00f3\u0142dzielone przez wiele komponent\u00f3w, o ile ma to sens, i mog\u0105 by\u0107 tylko po\u015brednikami dla bardziej skomplikowanego kodu napisanego w kodzie niezale\u017cnym od AEM. Wtedy mo\u017cesz u\u017cywa\u0107 takiego kodu \u201ewolnego od framework\u00f3w\u201d w wielu systemach przygotowywanego rozwi\u0105zania.<\/p>\n\n\n\n<p><strong>Klasy Sling Models i Java Use<\/strong> to w zasadzie ta sama koncepcja, przy czym <em>Java Use<\/em> jest starszym bratem tego pierwszego. W dzisiejszych czasach programi\u015bci tworz\u0105 wi\u0119cej <em>Sling Models<\/em>, jednak z pewno\u015bci\u0105 znajdziesz zastane klasy Java Use w systemach o d\u0142ugim terminie przydatno\u015bci i we\u017amiesz je pod uwag\u0119 w swojej architekturze.<\/p>\n\n\n\n<p>Inn\u0105 podstawow\u0105 funkcjonalno\u015bci\u0105 z naszego architektonicznego punktu widzenia jest to, \u017ce obiekty te mog\u0105 komunikowa\u0107 si\u0119 z serwisami OSGi, kt\u00f3re to nie maj\u0105 bezpo\u015bredniego zwi\u0105zku z \u017cadnym komponentem. Jest to punkt, w kt\u00f3rym architekci mog\u0105 <strong>przenie\u015b\u0107 odpowiedzialno\u015b\u0107 z komponent\u00f3w<\/strong> i, co wa\u017cniejsze, prowadzi\u0107 interakcje z systemami spoza JVM-a AEM.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Serwis OSGi<\/strong><\/h3>\n\n\n\n<p>W telegraficznym skr\u00f3cie, OSGi jest sposobem na uruchamianie odseparowanych od siebie modu\u0142\u00f3w \u0142aduj\u0105cych klasy w<a href=\"https:\/\/en.wikipedia.org\/wiki\/OSGi\" target=\"_blank\" aria-label=\" Java Runtime Environment (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" > Java Runtime Environment<\/a><a id=\"_ftnref1\" href=\"#_ftn1\" class=\"ek-link\" rel=\"nofollow\" >[3]<\/a>. AEM, a w zasadzie jego g\u0142\u00f3wny framework \u2013 Sling, korzysta z tego rozwi\u0105zania, ale sam OSGi jest samodzielnym bytem, u\u017cywanym w innych programach opartych na JVM, np. Eclipse IDE. Architekci uwa\u017caj\u0105, \u017ce OSGi jest szczeg\u00f3lnie interesuj\u0105cy ze wzgl\u0119du na <strong>dodatkow\u0105 izolacj\u0119 mi\u0119dzy uruchomionymi <em>bundles<\/em><\/strong> \u2013 paczkami, kt\u00f3re mog\u0105 zawiera\u0107 r\u00f3\u017cne klasy z tym samym <em>qualified name<\/em>, co zwykle bez dodatkowej, w\u0105tpliwej zabawy z <em>class loaders<\/em> jest niemo\u017cliwe.<\/p>\n\n\n\n<p>Opisywanie funkcjonalno\u015bci OSGi to w zasadzie temat na inny wpis, je\u015bli nie ca\u0142\u0105 ksi\u0105\u017ck\u0119, dlatego polecam zajrze\u0107 do <a href=\"https:\/\/docs.osgi.org\/specification\/osgi.core\/8.0.0\/toc.html\" target=\"_blank\" aria-label=\"oficjalnej dokumentacji (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >oficjalnej dokumentacji<\/a><a id=\"_ftnref2\" href=\"#_ftn2\" class=\"ek-link\" rel=\"nofollow\" >[4]<\/a>, by dowiedzie\u0107 si\u0119 wi\u0119cej.<\/p>\n\n\n\n<p>Z naszego punktu widzenia pakiety OSGi s\u0105 prawie jak pakiety AEM \u2013 zestawem klas Java, kt\u00f3re mo\u017cna zainstalowa\u0107 w okre\u015blonej wersji w instancji AEM. Te paczki pozwalaj\u0105 nam kontrolowa\u0107, jakie inne zale\u017cno\u015bci s\u0105 u\u017cywane w naszym kodzie. Ze strategicznego punktu widzenia przyczynia si\u0119 to do poprawy \u0142atwo\u015bci utrzymania takiego kodu \u2013 <em>bundle<\/em> mo\u017ce definiowa\u0107 zaw\u0119\u017cenie u\u017cywanych pakiet\u00f3w (tj. zestawu \u015bcie\u017cek klas Java), z kt\u00f3rymi komunikuje si\u0119 nasz kod.<\/p>\n\n\n\n<p>Opr\u00f3cz izolacji, OSGi dostarcza spos\u00f3b na uruchamianie instancji klas \u2013 obiekt\u00f3w Java \u2013 zarz\u0105dzaj\u0105c ich cyklem \u017cycia. Takie obiekty nazywane s\u0105 komponentami \u2013 tym razem b\u0119d\u0105 to <strong>OSGi <em>Components<\/em><\/strong>. Mo\u017cna je utworzy\u0107 na podstawie konfigurowalnych warunk\u00f3w, zatrzyma\u0107 i uruchomi\u0107 dodatkowy kod aktywacyjny. Na przyk\u0142ad, je\u015bli potrzebujemy obiektu, kt\u00f3ry po uruchomieniu naszego <em>bundle<\/em> zapisze wiadomo\u015b\u0107 na wyj\u015bcie standardowe, mo\u017cemy skonfigurowa\u0107 definicj\u0119 klasy tak, aby sta\u0142a si\u0119 komponentem OSGi, kt\u00f3rego metoda <em>activate<\/em> wykonuje taki w\u0142a\u015bnie kod.<\/p>\n\n\n\n<p><strong>Niewyobra\u017calnie trudn\u0105 sytuacj\u0105<\/strong> by\u0142by brak komunikacji pomi\u0119dzy komponentami. OSGi wprowadza koncepcj\u0119 serwisu OSGi (<em>OSGi Service<\/em>), kt\u00f3ra mo\u017ce zadeklarowa\u0107, \u017ce dany interfejs zostanie dostarczony do innych komponent\u00f3w, u\u017cywaj\u0105c takiej a takiej implementacji. Zasadniczo ten proces wstrzykni\u0119cia serwisu odbywa si\u0119 dynamicznie lub podczas tworzenia innego komponentu. Innymi s\u0142owy, <strong>komponenty mog\u0105 agregowa\u0107 serwisy OSGi i w razie potrzeby wywo\u0142ywa\u0107 ich metody.<\/strong><\/p>\n\n\n\n<p>Co w przypadku, gdy chcieliby\u015bmy jednak obs\u0142u\u017cy\u0107 webowe zapytania poza komponentami AEM?<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Servlets i Filters<\/strong><\/h3>\n\n\n\n<p>Architekci pracuj\u0105 w ograniczonych \u015brodowiskach, ograniczeniach i standardach, kt\u00f3rych nale\u017cy przestrzega\u0107. Czasami jeste\u015bmy zmuszeni wyj\u015b\u0107 poza ramy zwykle stosowanych rozwi\u0105za\u0144 i doda\u0107 co\u015b kompletnie unikatowego do oklepanej koncepcji. Niekt\u00f3rzy nazywaj\u0105 to sztuk\u0105, inni \u201ewyj\u0105tkiem potwierdzaj\u0105cym regu\u0142\u0119\u201d.<\/p>\n\n\n\n<p>Rozwa\u017cmy scenariusz, w kt\u00f3rym musimy wprowadzi\u0107 JSON endpoint, aby zasili\u0107 komponent dost\u0119pno\u015bci towaru dynamicznie pozyskiwanymi danymi z innego, zwykle wewn\u0119trznego \u017ar\u00f3d\u0142a. Wy\u017cej zaobserwowali\u015bmy standardow\u0105 sytuacj\u0119, w kt\u00f3rej komponenty s\u0105 producentami fragment\u00f3w HTML. Obecnie architekci powinni projektowa\u0107 intensywnie odwiedzane strony HTML jako statyczne, przetrzymywane w <em>cache<\/em> jak najbli\u017cej u\u017cytkownika ko\u0144cowego za pomoc\u0105 <strong>Content Delivery Network <\/strong>(CDN).<\/p>\n\n\n\n<p>Jak na razie podej\u015bcie modu\u0142owo\u015bci AEM nie daje mo\u017cliwo\u015bci po\u0142\u0105czenia tych dw\u00f3ch wymaga\u0144 ze sob\u0105, chyba, \u017ce mo\u017cemy mie\u0107 dodatkowe rozszerzenie wy\u0142\u0105cznie dla tego komponentu i go wyrenderowa\u0107 na podstawie indywidualnej \u015bcie\u017cki. Czasami, bior\u0105c pod uwag\u0119 fakt, \u017ce mo\u017cemy utkn\u0105\u0107 ze zbyt d\u0142ugimi \u015bcie\u017ckami, nie wchodzi to w gr\u0119 i musimy zrobi\u0107 krok wstecz \u2013 u\u017cy\u0107 popularnego mechanizmu serwera WWW w \u015bwiecie Javy, jakim jest <strong><em>Servlet<\/em>.<\/strong><\/p>\n\n\n\n<p>Je\u015bli jeste\u015b dobrze zakorzeniony w Java, to wiesz, \u017ce <em>Servlet<\/em> poci\u0105ga ze sob\u0105 inn\u0105 koncepcj\u0119 \u2013 <em>Filter<\/em>. Je\u015bli nie brzmi to znajomo, zalecam przeczytanie dokumentacji o <em>Java<\/em> <em>Servlets<\/em> i poeksperymentowanie z nimi <a href=\"https:\/\/www.baeldung.com\/intro-to-servlets\" target=\"_blank\" aria-label=\"poza AEM (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >poza AEM<\/a><a id=\"_ftnref1\" href=\"#_ftn1\" class=\"ek-link\" rel=\"nofollow\" >[5]<\/a>.<\/p>\n\n\n\n<p><strong>R\u00f3\u017cnica mi\u0119dzy zwyk\u0142ymi <em>Servlets<\/em> a AEM-owymi<\/strong> polega na tym, \u017ce wszystkie s\u0105 serwisami OSGi \u2013 mog\u0105 komunikowa\u0107 si\u0119 z innymi serwisami, w efekcie z reszt\u0105 systemu AEM. Architekt powinien wykorzysta\u0107 ten fakt podczas projektowania zwi\u0119z\u0142ych rozwi\u0105za\u0144, aby unikn\u0105\u0107 powtarzania tej samej implementacji funkcjonalno\u015bci w <em>Servlets<\/em> i <em>Sling Models<\/em>, wprowadzaj\u0105c albo wsp\u00f3\u0142dzielone klasy Java, albo serwisy OSGi.<\/p>\n\n\n\n<p>W ostatecznym rozrachunku, nawet przy tak wielu warstwach izolacji, system jest warto\u015bci\u0105 dodan\u0105 samych bezpo\u015brednich i po\u015brednich relacji mi\u0119dzy cz\u0119\u015bciami, a nie wy\u0142\u0105cznie sum\u0105 ich cz\u0119\u015bci.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Client Library<\/strong><\/h2>\n\n\n\n<p>Strony internetowe to nie tylko pliki HTML czy dane JSON przekazywane u\u017cytkownikowi ko\u0144cowemu. Wygl\u0105d strony jest r\u00f3wnie wa\u017cny jak tre\u015b\u0107, co wi\u0119cej w literaturze wygl\u0105d i styl jest nieroz\u0142\u0105czn\u0105 <a href=\"https:\/\/lubimyczytac.pl\/ksiazka\/4842659\/web-content-management-systems-features-and-best-practices\" target=\"_blank\" aria-label=\"cz\u0119\u015bci\u0105 tre\u015bci (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >cz\u0119\u015bci\u0105 tre\u015bci<\/a><a id=\"_ftnref1\" href=\"#_ftn1\" class=\"ek-link\" rel=\"nofollow\" >[6]<\/a>. Architekt nie mo\u017ce pomin\u0105\u0107 tej cz\u0119\u015bci planowania projektu strony internetowej i komponent\u00f3w.<\/p>\n\n\n\n<p>Pomy\u015bl na razie o plikach CSS \u2013 czy powinny by\u0107 na stale zespawane z komponentami AEM? Innymi s\u0142owy, <strong>czy niekt\u00f3re CSS mog\u0105 by\u0107 tak samo wielokrotnego u\u017cytku jak komponenty<\/strong>? Bior\u0105c pod uwag\u0119 fakt mo\u017cliwo\u015bci ponownego u\u017cycia, komponenty powinny zachowywa\u0107 modyfikowalny wygl\u0105d i styl. Arkusze styl\u00f3w s\u0105 bardziej cz\u0119\u015bci\u0105 strony (szablonu, kt\u00f3rego nie poruszyli\u015bmy w tym wpisie na blogu) ni\u017c komponentem.<\/p>\n\n\n\n<p>A co ze skryptami JS? Zachowanie komponent\u00f3w \u2013 zw\u0142aszcza tych, kt\u00f3re dynamicznie si\u0119 zmieniaj\u0105 lub z kt\u00f3rymi mo\u017cna wchodzi\u0107 w interakcje bez \u0142adowania strony \u2013 wydaje si\u0119 by\u0107 znacznie bli\u017csze komponentom sensu stricte ni\u017c ich wygl\u0105dowi.<\/p>\n\n\n\n<p>Bior\u0105c pod uwag\u0119 t\u0119 rozbie\u017cno\u015b\u0107, <strong>powinni\u015bmy my\u015ble\u0107 o zachowaniu i wygl\u0105dzie jako o lu\u017ano powi\u0105zanych ze sob\u0105<\/strong>. W realnych systemach niekt\u00f3re s\u0105 ze sob\u0105 silnie po\u0142\u0105czone i nie mo\u017cna ich rozdzieli\u0107, jednak jest to raczej przypadek wyj\u0105tkowy ni\u017c powszechny.<\/p>\n\n\n\n<figure class=\"wp-block-image aligncenter size-full\"><a href=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/clientlibs.png\"><img decoding=\"async\" width=\"413\" height=\"195\" src=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/clientlibs.png\" alt=\"Struktura Biblioteki Klienta\" class=\"wp-image-27817\" srcset=\"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/clientlibs.png 413w, https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/clientlibs-300x142.png 300w\" sizes=\"(max-width: 413px) 100vw, 413px\" \/><\/a><figcaption class=\"wp-element-caption\">Ryc. 4 Struktura Biblioteki Klienta<\/figcaption><\/figure>\n\n\n\n<p>W AEM wprowadzono mechanizm agregacji i zale\u017cno\u015bci plik\u00f3w CSS i JS. Jest on identyfikowany przez ci\u0105g znak\u00f3w zwanym kategori\u0105 (ang. <em>category<\/em>). Przegl\u0105darka \u0142aduje wszystkie te pliki w tym samym kontek\u015bcie strony (wy\u0142\u0105czaj\u0105c z tego Shadow DOM), wi\u0119c architekt powinien rozwa\u017cy\u0107 \u0142adowanie <em>Client Libraries<\/em> tylko w komponencie reprezentuj\u0105cym stron\u0119 HTML.<\/p>\n\n\n\n<p><em>Client Libraries<\/em> <strong>mog\u0105 definiowa\u0107 inne kategorie, kt\u00f3re maj\u0105 by\u0107 zale\u017cne lub w kt\u00f3rych maj\u0105 by\u0107 osadzone<\/strong>. Daje to pot\u0119\u017cn\u0105 mo\u017cliwo\u015b\u0107 definiowania wymaganych bibliotek do za\u0142adowania JS lub CSS, ale bez zrzucania odpowiedzialno\u015bci za do\u0142adowanie brakuj\u0105cych bibliotek na konsument\u00f3w biblioteki. Dodatkowo, nie musisz niczego zmienia\u0107 na stronie, je\u015bli niekt\u00f3re zale\u017cno\u015bci b\u0119d\u0105 przestarza\u0142e i b\u0119dziesz musia\u0142 zmieni\u0107 kategori\u0119 zale\u017cno\u015bci we w\u0142asnej bibliotece.<\/p>\n\n\n\n<p>Co zaskakuj\u0105ce, mo\u017cna nazwa\u0107 wiele bibliotek t\u0105 sam\u0105 nazw\u0105 kategorii i wszystkie zostan\u0105 za\u0142adowane na stron\u0119 (w losowej kolejno\u015bci, ale jednak). Ta funkcja mo\u017ce by\u0107 przydatna dla architekt\u00f3w wykorzystuj\u0105cych <strong>mo\u017cliwo\u015b\u0107 dodania dodatkowego CSS lub JS dla okre\u015blonej kategorii<\/strong>, bez zmiany zawarto\u015bci strony i szablonu. Pomy\u015bl o tym jak o <em>aspect programming<\/em>, gdzie mo\u017cesz wprowadzi\u0107 dodatkowy kod CSS lub JS pomi\u0119dzy ju\u017c istniej\u0105cy.<\/p>\n\n\n\n<p>Nie ma skodyfikowanych zasad strukturyzacji lub projektowania <em>Client Libraries<\/em>, jednak logicznym rozwi\u0105zaniem wydaje si\u0119 utworzenie jednego do obs\u0142ugi istotnego zachowania komponent\u00f3w, a innego do wygl\u0105du strony.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Podsumowanie<\/strong><\/h2>\n\n\n\n<p>Te koncepcje s\u0105 podstaw\u0105 ka\u017cdego porz\u0105dnego systemu opracowanego w \u015brodowisku AEM. Nie daj si\u0119 jednak zwie\u015b\u0107 \u2013 to dopiero pocz\u0105tek Twojej podr\u00f3\u017cy przez jego funkcje. Niemniej jednak to w\u0142a\u015bnie odmienne podej\u015bcie do przetwarzania i architektury by\u0142o pierwotnym powodem, dla kt\u00f3rego <strong>AEM jest obecnie najbardziej innowacyjnym systemem CMS na rynku<\/strong>. Sprawia, \u017ce struktura jest znacznie bli\u017csza tre\u015bci ni\u017c podej\u015bcie oparte wy\u0142\u0105cznie na szablonach. Nie wyobra\u017casz sobie swojej strony bez szablon\u00f3w? Nie martw si\u0119, <strong>w AEM te\u017c s\u0105 szablony<\/strong>, ale zdecydowanie nie graj\u0105 pierwszych skrzypiec, je\u017celi chodzi o tworzenie tre\u015bci.<\/p>\n\n\n\n<p>Adobe Experience Manager to du\u017cy system CMS. W tym artykule nie odnosi\u0142em si\u0119 do funkcjonalno\u015bci dost\u0119pnych w systemie od razu po wyj\u0119ciu z pude\u0142ka \u2013 chodzi\u0142o mi o to, aby przedstawi\u0107 narz\u0119dzia my\u015blowe, kt\u00f3rych u\u017cywam do planowania pracy tworzenia komponent\u00f3w, kt\u00f3rych tam jeszcze nie ma lub nie mo\u017ce by\u0107, bior\u0105c pod uwag\u0119 fakt, \u017ce z definicji biznes klient\u00f3w rozwi\u0105zuje problemy w unikalny spos\u00f3b.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Czas po\u0107wiczy\u0107!<\/strong><\/h2>\n\n\n\n<p>Korzystaj\u0105c wy\u0142\u0105cznie z tego wpisu, powiniene\u015b by\u0107 w stanie zbudowa\u0107 architektur\u0119 odpowiedni\u0105 dla naprawd\u0119 interesuj\u0105cych przypadk\u00f3w. Je\u015bli obecnie ich nie masz, podam Ci kilka pomys\u0142\u00f3w, wyobra\u017a sobie:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Witryn\u0119 biblioteki, w kt\u00f3rej ka\u017cda ksi\u0105\u017cka jest stron\u0105 i mo\u017ce agregowa\u0107 strony zar\u00f3wno wed\u0142ug kategorii, kt\u00f3re s\u0105 naturalne i statyczne (jak gatunki), jak i tymczasowe, dynamiczne (np. \u201epolecane dla Ciebie\u201d).<\/li>\n\n\n\n<li>Instytut naukowy publikuj\u0105cy ka\u017cdego tygodnia setki stron, na kt\u00f3rych trzeba zaimplementowa\u0107 komponenty, kt\u00f3re tworz\u0105 po\u0142\u0105czenie z zewn\u0119trzn\u0105 sztuczn\u0105 inteligencj\u0105, ustalaj\u0105c\u0105 relacje pomi\u0119dzy tymi artyku\u0142ami (zaplanuj po\u0142\u0105czenie do ChatGPT API).<\/li>\n\n\n\n<li>Firm\u0119 w sektorze finansowym, w kt\u00f3rej musisz wprowadzi\u0107 komponent oparty na pozosta\u0142ej cz\u0119\u015bci strony, kt\u00f3ry daje wskaz\u00f3wki dotycz\u0105ce potencjalnych opcji inwestycyjnych u\u017cywaj\u0105cy AI lub silnikiem BI skonstruowany wewn\u0105trz firmy. Zauwa\u017c, \u017ce u\u017cywanie zewn\u0119trznego API i wewn\u0119trznego ma ogromne konsekwencje w tworzeniu wewn\u0119trznego interfejsu do jego obs\u0142ugi, a tak\u017ce wprowadzenia dodatkowych <em>bundles<\/em>.<\/li>\n<\/ul>\n\n\n\n<p>Projektowanie architektury dla rozwi\u0105za\u0144 opartych na AEM to \u015bwietna zabawa, kiedy ma si\u0119 odpowiednie narz\u0119dzia my\u015blowe i du\u017co \u0107wiczy. Masz ju\u017c narz\u0119dzia, mo\u017cesz si\u0119 wzi\u0105\u0107 za trening!<\/p>\n\n\n\n<p><\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p><a id=\"_ftn1\" href=\"#_ftnref1\" rel=\"nofollow\" >[1]<\/a> N. Nan i S. Kumar, &#8222;<a href=\"https:\/\/ieeexplore.ieee.org\/document\/6417020\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Joint Effect of Team Structure and Software Architecture in Open Source Software Development<\/a>&#8222;, w: IEEE Transactions on Engineering Management, tom 60, nr 3, s. 592-603, sierpie\u0144 2013 r.<\/p>\n\n\n\n<p><a id=\"_ftn1\" href=\"#_ftnref1\" class=\"ek-link\" rel=\"nofollow\" >[2]<\/a> <a href=\"https:\/\/www.aemcomponents.dev\/\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >https:\/\/www.aemcomponents.dev\/<\/a><\/p>\n\n\n\n<p><a id=\"_ftn1\" href=\"#_ftnref1\" class=\"ek-link\" rel=\"nofollow\" >[3]<\/a> <a href=\"https:\/\/en.wikipedia.org\/wiki\/OSGi\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >https:\/\/en.wikipedia.org\/wiki\/OSGi<\/a><\/p>\n\n\n\n<p><a id=\"_ftn2\" href=\"#_ftnref2\" class=\"ek-link\" rel=\"nofollow\" >[4]<\/a> <a href=\"https:\/\/docs.osgi.org\/specification\/osgi.core\/8.0.0\/toc.html\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >https:\/\/docs.osgi.org\/specification\/osgi.core\/8.0.0\/toc.html<\/a><\/p>\n\n\n\n<p><a id=\"_ftn1\" href=\"#_ftnref1\" class=\"ek-link\" rel=\"nofollow\" >[5]<\/a> <a href=\"https:\/\/www.baeldung.com\/intro-to-servlets\" target=\"_blank\" aria-label=\" (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >https:\/\/www.baeldung.com\/intro-to-servlets<\/a><\/p>\n\n\n\n<p><a id=\"_ftn1\" href=\"#_ftnref1\" class=\"ek-link\" rel=\"nofollow\" >[6]<\/a> Barker, Deane. <a aria-label=\" (opens in a new tab)\" href=\"https:\/\/lubimyczytac.pl\/ksiazka\/4842659\/web-content-management-systems-features-and-best-practices\" target=\"_blank\" rel=\"noreferrer noopener\" class=\"ek-link\" rel=\"nofollow\" >Zarz\u0105dzanie tre\u015bci\u0105 internetow\u0105: systemy, funkcje i najlepsze praktyki<\/a>. &#8222;O&#8217;Reilly Media, Inc.&#8221;, 2016.<\/p>\n\n\n\n<p>***<\/p>\n\n\n\n<p>Je\u015bli interesuj\u0105 Ci\u0119 rozwi\u0105zania Adobe, zajrzyj koniecznie r\u00f3wnie\u017c <a href=\"https:\/\/sii.pl\/blog\/wyszukiwarka\/adobe\/\" target=\"_blank\" aria-label=\"do innych artyku\u0142\u00f3w naszych ekspert\u00f3w (opens in a new tab)\" rel=\"noreferrer noopener\" class=\"ek-link\">do innych artyku\u0142\u00f3w naszych ekspert\u00f3w<\/a>. <\/p>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;27810&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;4&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;5&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;11&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;5\\\/5 ( votes: 4)&quot;,&quot;size&quot;:&quot;18&quot;,&quot;title&quot;:&quot;Modu\u0142owo\u015b\u0107 Adobe Experience Manager&quot;,&quot;width&quot;:&quot;139.5&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} ( {votes}: {count})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 139.5px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 11px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 18px; height: 18px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 14.4px;\">\n            5\/5 ( votes: 4)    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>Przejrzysta i zrozumia\u0142a architektura to jeden z kluczy do sukcesu w tworzeniu oprogramowania[1]. Architekci i deweloperzy podejmuj\u0105 dziesi\u0105tki decyzji architektonicznych &hellip; <a class=\"continued-btn\" href=\"https:\/\/sii.pl\/blog\/modulowosc-adobe-experience-manager\/\">Continued<\/a><\/p>\n","protected":false},"author":638,"featured_media":27820,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_editorskit_title_hidden":false,"_editorskit_reading_time":0,"_editorskit_is_block_options_detached":false,"_editorskit_block_options_position":"{}","inline_featured_image":false,"footnotes":""},"categories":[1314],"tags":[1546,1512,1218],"class_list":["post-27810","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development-na-twardo","tag-przeglad-narzedzi","tag-poradnik","tag-adobe-experience-manager"],"acf":[],"aioseo_notices":[],"republish_history":[],"featured_media_url":"https:\/\/sii.pl\/blog\/wp-content\/uploads\/2024\/05\/Modulowosc-Adobe-Experience-Manager.jpg","category_names":["Development na twardo"],"_links":{"self":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/27810"}],"collection":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/users\/638"}],"replies":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/comments?post=27810"}],"version-history":[{"count":2,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/27810\/revisions"}],"predecessor-version":[{"id":27852,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/posts\/27810\/revisions\/27852"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media\/27820"}],"wp:attachment":[{"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/media?parent=27810"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/categories?post=27810"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sii.pl\/blog\/wp-json\/wp\/v2\/tags?post=27810"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}