FlexiBee: Od desktopové aplikace k internetové službě

Minule jsme si řekli důvody, proč jsme migrovali naši aplikaci do cloudu. Nyní se podíváme na úpravy aplikace, které jsme museli provést, aby mohla být samotná aplikace provozována v cloudu a především formou webové aplikace. Tento článek bude technický a orientovaný na jazyk Java a technologie HTML.

Jen shrneme, že FlexiBee byla především desktopová aplikace do které jsme přidali programátorské rozhraní REST API (postavené na protokolu HTTP). A od tohoto rozhraní jsme se dostali až ke kompletně internetové službě, která je postavena právě na tomto systému.

Na první pohled se může zdát, že jsme vzali desktopovou aplikaci a v podstatě ji kompletně přepsali do formy internetové služby. Realitou však je, že už od začátku vývoje jsme s touto postupnou transformací počítali a použití REST API je toho důkazem.

Když jsme realizovali tuto službu, museli jsme provést mnoho změn v aplikace. Zde si shrňme základní:

  • doprogramovat webové rozhraní
  • zvýšit škálovatelnost a bezstavovost
  • přidat možnosti vícepronájmu
  • možnosti modifikace výstupu
  • rozšíření škálovatelnosti

Jak to bylo na začátku

FlexiBee byla klasická desktopová aplikace napsaná ve Swingu, používající ORM nástroj Hibernate a jako databázi používá otevřený PostgreSQL.

Velkou výhodou architektury je, že je vnitřně psána vícevrstvě a tak nebyl problém extrahovat logiku do vlastního aplikačního serveru a tu pak volat (což už stejně děláme v případě desktopové aplikace).

V aplikačním serveru jsme použili webový server Jetty a REST knihovnu Jersey. Tím jsme získali základ na kterém jsme vytvořili programátorské rozhraní REST API, které na základě metadat systému umožňuje importy, exporty a dotazování.

O samotném REST API jsme zde na zdrojáku již psali.

Nové webové rozhraní

První a současně nejsložitější věc, kterou jsme museli udělat bylo napsat alternativní webové rozhraní.

Každá stránka byla rozdělena na prohlížecí a editační. Struktura formulářů je dána popisnou strukturou ze které generujeme šablony pro knihovnu Freemarker. Vzhled formulářů je tedy řízen metadaty: díky tomu budeme v budoucnu schopni měnit strukturu formulářů pro klienty.

Editace je ovšem složitější. Abychom se vyhnuli duplicitnímu programování veškeré logiky, pomohli jsme si několika postupy a využili jsme maximálně existující aplikační server.

Asynchronní GUI

Protože logika aplikace jako je skrývání položek nebo změny souvisejících položek již byla naprogramovaná v desktopové aplikaci, pokusili jsme se ji maximálně využít. Proto jsme využili asynchroní GUI, kdy se vezmou data zadané uživatelem, zašlou se na server a zde dojde k reakci podobně jako v desktopové aplikace.

Díky tomuto použití jsme získali výhodu, že nemusíme formuláře programovat podruhé a veškeré vnitřní chování je jednotné v aplikaci i na webu. Nevýhodou je, že s tímto přístupem nebudeme mít možnost realizovat offline aplikaci (o tom níže) a také, že aplikace reaguje s malým zpožděním (cca 50 až 100 ms).

Když tedy vyplníte formulář (např. vyberete typ faktury), dojde k sestavení JSON dotazu, který je odeslán na aplikační server přes REST API. Součástí dotazu je i informace, kterou položku uživatel vyplnil. Na serveru dojde k importu záznamu, ale nedojde k jeho uložení do databáze. Systém zareaguje a pozmění související data (např. změní číselnou řadu a přidělí nové číslo faktury). Díky tomu je současně shodné chování webového přístupu a REST API.

Server dokáže reagovat těmito typy odpovědí:

  • seznam chyb
  • seznam nově změněných atributů (např. ono číslo faktury)
  • seznam skrytých nebo zobrazených atributů (když není doklad účetní nelze nastavovat zaúčtování)

Průvodce a akce

Protože je vše postavené na jednom systému, je pro nás poměrně jednoduché vytvářet další funkce. Příkladem může být přiznání DPH: uživatele se zeptáme na období, výstupní formát a na server pak už jen zavoláme metodu pro generování daňového přiznání.

Pokud se tedy změní daňové přiznání, nemusíme nic programovat podruhé, změna se projeví na obou místech. Tedy do té doby než se změní v míře, kdy je nutné změnit uživatelské rozhraní.

Škálovatelné SQL?

FlexiBee je postaveno na otevřené databázi PostgreSQL. SQL je v souvislosti s cloudem zmiňována jako dostatečně neškálovatelná technologie – reálně škáluje v jednotkách serverů. A obvykle jsou doporučovány alternativní databázové systémy obvykle označované jako NoSQL.

První myšlenou by bylo aplikaci přepsat právě do NoSQL. Proti tomuto rozhodnutí hraje několik věcí. První jsou vysoké náklady na přepsání. NoSQL je způsobem myšlení velmi odlišné od SQL. Druhým pak fakt, že s těmito systémy není příliš mnoho zkušeností pro tento typ systémů (ať už obecně tak i mezi našimi vývojáři). Jejich základem je totiž výrazné dotazování, včetně adhoc dotazů, které se v NoSQL špatně realizuje.

Hledali jsme tedy jinou cestu. Chtěli jsme zachovat SQL, ale současně umožnit škálování.

Současný model, který používáme u klasických instalací, kde je jeden fyzický server pro jednu firmu, je, že každá firma má vlastní instalaci PostgreSQL a v ní vlastní databázi pro každou firmu. Toto řešení není pro internetové služby příliš vhodné. Na druhou stranu její změna by byla opět tak invazivní zásah do celého systému, že jsme se neodvážili jej realizovat a rozhodli jsme se s tímto omezením žíti. Toto omezení se současně ukázalo jako výhoda pro škálování: nikdy nepotřebujeme provádět dotazy mezi

Nevýhodou také je, že pro každého klienta musíme vytvořit vlastní databázi, do ní nahrát schéma a úvodní data. Nicméně tato operace trvá 15 vteřin (je to vidět při zakládání firmy v desktopové aplikaci). Klient webové aplikace, ale takto dlouho nevydrží a také by nám působil ve špičce souběh několika zakládání současně výkonnostní problémy. Proto jsme se rozhodli předvytvořit množství firem a při zakládání firmy ji prostě použít. Musíme tedy vytvořit dostatek firem pro všechny podporované státy a typy organizací (nyní je to 5 typů).

Toto řešení má i své výhody tohoto přístupu je, že pokud si klient stáhne zálohu firmy, dostane databázový dump PostgreSQL. Takže záloha, kterou může klient dále využívat je pro nás naopak velmi jednoduchá.

Hibernate

U webových aplikací je Hibernate často používán. V našem případě je ale komplikace díky více databází. Nemůžeme startovat Hibernate session factory pro každého klienta (to trvá 15 vteřin). Proto jsme se rozhodli, že budeme sdílet jednu session factory. Proto jsme vypnuli second level cache (jinak by docházelo k přenosu cachovaných dat mezi klienty). Obecně cachování v tomto rozsahu nemá moc velký přínos a je lepší data prostě nenačítat a nebo dotazy optimalizovat.

Další věc je, že pro každého klienta musíme mít vlastní JDBC spojení a nemůžeme tak používat Connection Pooling z Hibernate. Pro každého klienta vytvoříme Connection Pool, vezmeme z něj spojení a pro požadavek jej předáme Hibernate.

Tento způsob použití Hibernate je celkem neobvyklý a z počátku jsme měli obavy, ale vše se ukázalo jako bezproblémové.

Přidat možnosti vícepronájmu

Protože máme mnoho klientů na jednom serveru, je nutné umožnit, aby každý z nich mohl mít jinou variantu a tím mohl mít i různou cenu.

Proto jsme umožnili, aby každý klient měl jinou licenci. Technicky se jedná o XML, které je elektronicky podepsané dle standardu XMLSignature.

Možnost modifikace výstupu

Při přípravě pro službu Účtujte.cz jsme potřebovali, abychom mohli upravit výstup stránky pro danou službu. Ale nechtěli jsme modifikovat přímo aplikační server. A současně jsme potřebovali Single Sign On se serverem podnikatel.cz. Proto jsme vytvořili PHP proxy, která přeposílá požadavky klienta na aplikační server a pak výstup modifikuje.

Proto jsou do HTML stránky vloženy speciální značky: <!–FLEXIBEE:CSS:START–>. Díky tomu můžeme ovlivňovat vzhled stránky a různě umísťovat obsah.

Na první pohled se toto zdá jako náročný proces, ale díky tomuto systému nedochází ke změně HTML aplikačního serveru a tak stejný postup může použít i účetní firma při integraci naší aplikace do svých stránek.

Protože díky rozhraní REST mají URL jasnou strukturu, lze snadno měnit i obsah dle požadované stránky (např. stránka založení).

Rozšíření škálovatelnosti pro cloud

Protože jsme chtěli rozšířit možnosti škálování naší aplikace i nad rámec jednoho nebo dvou serverů řešili jsme, jak rozšířit škálovatelnost.

Zde se nakonec ukázalo, že oddělené databáze pro každého klienta jsou dobré řešení. Relační databáze (a SQL) obecně příliš dobře neškálují. My ale nikdy nepotřebujeme provádět dotazy napříč všemi klienty. Můžeme tedy teoreticky mít miliony jednotlivých databází.

Současně jsme se podívali na aplikační server. Ten je kompletně bezstavový. Stavová je pouze autorizace uživatele, hlídání počtu uživatelů a firem v licenci. Upravili jsme i obranu proti CSRF (Cross Site Request Forgery) tak, aby byla bezstavová (pomocí cookie).

PHP Proxy je kompletně bezstavová a tak není se škálováním problém.

Poslední věc, která zbývá je globální konfigurace, která mapuje uživatele, existující firmy, jejich aktuální polohu v cloudu a přístupy. Standardně je tato konfigurace uložena v PostgreSQL. Pro účely cloudu ale není tato databáze příliš vhodná. A protože je velmi jednoduchá (má pouze cca 6 tabulek), rozhodli jsme se implementovat ji pro použití v cloudu znovu. Pro běžné klienty bude tato konfigurace stále uložena v PostgreSQL.

Tuto oblast, ale zatím testujeme a nerad bych předbíhal.

Závěr

Při rozsáhlých úpravách systému jsme museli najít mnoho cest, abychom transformovali desktopovou aplikaci na internetovou službu. Věříme, že toto shrnutí pro vás bylo zajímavé a inspirující.

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *