Cześć! W dzisiejszym wpisie chciałbym poruszyć temat migracji projektów Liferayowych między wersjami, a dokładniej przedstawić bolączki z tym związane w oparciu o własne doświadczenia. Osobiście uczestniczyłem w migracji kilku projektów - zarówno z wersji 6.2 do 7.x jak i z wersji 7.0 do 7.2 (tutaj dodatkowo z wersji CE na wersje DXP). Dodatkowo migracje te obejmowały całe spektrum "przypadków" jeśli chodzi o wielkość - były to małe moduły z dosłownie kilkoma portletami, średnie projekty z kilkoma encjami bazodanowymi i kilkunastoma portletami, ale także był jeden projekt, który zawierał dużo ponad 100 portletów i encji bazodanowych.
Właśnie na bazie tych doświadczeń chciałbym pokazać kilka przykładów tego na jakie problemy możemy się natknąć podczas migracji. Chciałbym przez to uczulić Ciebie na to, aby nie ufać w to, że automatycznie uda Ci się zmigrować projekt bo najprawdopodobniej tak nie będzie. Powiem więcej - sam musiałem w niektórych przypadkach debugować kod Liferaya bo niestety w wielu przypadkach nie pomagała ani dokumentacja, ani istniejące tematy na forum ani nawet zadanie własnego pytania. Oczywiście jeśli masz wersje DXP to jest szansa, że otrzymasz oficjalne wsparcie, aczkolwiek z doświadczenia wiem, że niewielka część portali oparta jest na płatnej wersji co, ze względu na koszty, jest całkiem zrozumiałe.
Od razu ostrzegam, że nie będzie w tym wpisie zbyt dużo kodu czy rzeczywistych przykładów bo po prostu odtworzenie ich zajęłoby zbyt dużo czasu, a kodu produkcyjnego przy którym moje problemy wystąpiły z oczywistych względów pokazać nie mogę. Niemniej jednak mam nadzieję, że uda Ci się wynieść coś pożytecznego z kilku minut poświęconych na przeczytanie poniższego tekstu.
Uwaga! W trakcie pisania okazało się, że tekstu wyszło na tyle dużo, że zdecydowałem się podzielić go na dwie części. Druga część pojawi się niebawem - po prostu przy pisaniu tego wpisu, który miał być całością uznałem, że jest już tego za dużo, a nawet nie doszedłem do "głównej" części, o której chciałem napisać czyli migracji modułów :)
Uwaga! Dostępna jest już także druga część artykułu o problemach, które mogą nas spotkać podczas migracji kodu. Zachęcam do przeczytania w następnej kolejności: Dlaczego migracje projektów Liferayowych na wyższą wersje nie są proste cz. 2
Dlaczego w ogóle aktualizować wersje?
Warto najpierw zadać sobie pytanie - po co w ogóle migrujemy? Odpowiedzi jest kilka - przede wszystkim bezpieczeństwo. Wystarczy spojrzeć na tzw. "known vulnerabilities", aby zobaczyć, że stare wersje Liferaya zawierają sporo niedociągnięć.
Inną sprawą mogą być nowości, które oferują nowsze wersje używanej technologii. W przypadku Liferaya idealnie widać to na przykładzie wersji 6.2 i 7.x (nawet 7.0) - przeskok był ogromny chociażby ze względu na przejście na OSGI.
Jak wygląda migracja w Liferayu
Tak jak pisałem wcześniej - wpis ten nie będzie instrukcją przeprowadzenia migracji bo od tego jest oficjalna dokumentacja. Nie ukrywam, że prawdopodobnie można by to przedstawić dużo lepiej niż w oficjalnej dokumentacji, ale to raczej byłby temat na cały kurs, a nie wpis na blogu ;)
Gdybyś jednak na ten moment nie był zainteresowany przedzieraniem się przez całą dokumentacje to możesz póki co przyjąć, że migracja sprowadza się w uproszczeniu do kilku punktów:
- Przygotowanie naszego portalu - wszelkie kopie zapasowe, usunięcie duplikatów czy nieużywanych artykułów itp
- Aktualizacja bazy danych - za pomocą skryptu
- Migracja naszych modułów na nowe wersje - w przypadku migracji z 6.2 najprawdopodobniej będzie też potrzebne rozbicie aplikacji na jakiekolwiek moduły
- Testy, testy i jeszcze więcej testów
I na pierwszych trzech skupię się opisując co może nam się przydarzyć.
Przygotowanie portalu
Przygotowanie portalu jest krokiem, który jest zalecany w oficjalnej dokumentacji, choć wydawałoby się, że można go pominąć? No niestety okazuję, się, że nie zawsze. Standardowo to przygotowanie portalu ma na celu oszczędzenie miejsca oraz przyspieszenie procesu migracji, aczkolwiek istnieje także drugie dno - Liferay nie zawsze radzi sobie poprawnie z starymi referencjami. Czym jest stara referencja? Przykładowo może być to jakiś stary webcontent, którego już nie używamy i dawno o nim zapomnieliśmy. W pewnym momencie ktoś usunął zdjęcie, którego ten WebContent używał. Wydaję się, że nic złego nie może się wydarzyć bo to standardowe zachowanie - nikt przecież nie analizuje zawartości wszystkich artykułów przed usunięciem zdjęcia i rzeczywiście nic złego się nie dzieje w takim wypadku.
Przechodzimy jednak do migracji naszego portalu na wyższą wersje, wszystko się nam zmigrowało, portal działa aż pewnego razu pobieramy całego LARa z serwera, żeby lokalnie odtworzyć portal i... kończymy z tak zwanym "infinite loop". Brzmi nieprawdopodobnie? A jednak, taka właśnie sytuacja mi się przydarzyła. Dodam, że pierwotnie portal był w wersji 7.0.6 CE a zmigrowany został do wersji 7.2.1 DXP. Całą historie można zobaczyć (wraz z poradami, które otrzymałem) na forum Liferaya: https://liferay.dev/forums/-/message_boards/message/119669178. Dodam tylko, że oprócz proponowanych tam rozwiązań z logami (które bardzo pomogły!) musiałem debugować kod Liferaya.
A chodziło tylko o usuniętę zdjęcie... Na obronę przyznam jedynie, że przypadek ten był specyficzny - nie zawsze usuniętę zdjęcie cokolwiek zepsuje (wręcz raczej nigdy), ale z tego co zauważyłem jedynie wtedy kiedy wrzucimy zdjęcie bezpośrednio do treści z edytora, pomijając documents & media. Może nawet muszą zajść jeszcze jakieś dodatkowe przypadki bo zdjęć miałem w tym migrowanym portalu bardzo dużo (tysiące), a tylko jedno okazało się problematyczne.
Jak szukać takich zepsutych zdjęć? Generalnie ja nie wiedziałem, że taki problem istnieje i stąd tak jak wspomniałem skończyłem na degowaniu kodu Liferaya wraz z czytaniem logów na poziomie DEBUG (sporo tego) i tak znalazłem mój zepsuty WebContent. Niemniej jednak gdybym takich przypadków miał więcej to najprawdopodobniej spróbowałbym jakiegoś narzędzia do szukania "Broken references" - generalnie chodziłoby o przeszukanie naszej strony w poszukiwaniu miejsc gdzie mamy zepsute zdjęcia (wiecie - taka mała ikonka zdjęcia, które się nie załadowało przez zły src). Niestety nie zadziała to jeśli nasz webcontent nie jest nigdzie wstawiony - wtedy można pokusić się o napisanie jakiegoś małego programu do szukania tego.
Aktualizacja bazy danych
Jeśli chodzi o aktualizacje samej bazy danych to przyznam, że jest nieźle. Twórcy tak zwanego tak zwanego "upgrade tool" zrobili dobrą robote bo nie spotkałem się z większymi problemami i to mimo migrowania naprawdę dużych baz danych (jedna z około 8 wirtualnymi instancjami a druga nawet z około 20). Napotkałem tak naprawdę jedynie dwa problemy związane stricte z migracją bazy danych, ale nie były one tragiczne w skutkach - biorąc pod uwagę jak wiele mogło się zepsuć np. w WebContentach
Wpisy konfiguracyjne JAX-RS
W jednej z migrowanych aplikacji (7.0.6 -> 7.2.1 DXP), w której użyty był JAX-RS (o którym w kontekście Liferaya można poczytać tutaj) pojawił się błąd przy starcie aplikacji i wyglądał mniej więcej tak:
Związany był z niepoprawnymi wpisami w tabeli Configuration_. Wyglądały one mniej więcej tak:
- com.liferay.portal.remote.rest.extender.configuration.RestExtenderConfiguration.e7c762dd-9fed-4956-8bbf-a89ec9e3a1b8
- com.liferay.portal.remote.rest.extender.configuration.RestExtenderConfiguration.factory
Było ich więcej (jeden dla "Factory" i po jednym dla każdego rejestrowanego endpointu). Numerki też będą inne (w przypadku tego pierwszego) więc najłatwiej ich poszukać zapytaniem:
select * from Configuration_ WHERE configurationId like '%com.liferay.portal.remote.rest.extender.configuration.RestExtenderConfiguratio%'
Rozwiązanie? Wystarczy usunąć te wpisy i się nimi na etapie migracji bazy danych. Gdy zmigrujemy nasze moduły związane z JAX-RS i je uruchomimy wszystko będzie działać poprawnie
Tabela release_
Drugim problemem, z którym się spotkałem były niewłaściwe wpisy w tabeli Release_, która krótko mówiąc przechowuję informacje o wersjach aplikacji czy modułów. Problem pojawiał się przy migracji z wersji 6.2 GA2 na wersje 7.3 GA1 - tabela release nie migrowała się poprawnie, aczkolwiek wystarczyło porównać jej zawartość z "świeżą" bazą stworzoną pod 7.3.1 i "podmienić" wpisy i wszystko działało poprawnie.
Na koniec
Tak jak wspominałem w wstępie jest to pierwszy artykułów z dwóch na temat problemów migracyjnych. W drugim wpisie opiszę temat migracji modułów gdzie problemów jest o wiele więcej - tam na pewno wręcz nie opiszę wszystkich, z którymi się spotkałem bo jest ich sporo, choć wiele z nich wynika raczej z ubogiej dokumentacji (i braków w tak zwanych "Breaking changes"), ale w większości nie są aż tak trudne do naprawienia.
I na koniec - powodzenia! :)
PS
Gdybyś w swojej firmie szukał pomocy przy takich migracjach to zawsze zapraszam do kontaktu. Mogę pomóc przy małych migracjach jak i tych dużych, gdzie w zależności od skali możemy porozmawiać o większym zespole który mogę zaproponować.