Internet Info, s.r.o. Lupa Root Měšec Podnikatel DigiZone Slunečnice Vitalianew Bomba Navrcholu Weblogy Jagg Woko Dobrý web Computer.cz SK: MojeLinky

Hlavní navigace

REST API jako rozhraní desktopové aplikace

Jedním z požadavků zákazníků na desktopový ekonomický systém WinStrom 10 bylo otevřené API. Původním zadáním rozhraní byla možnost importovat a exportovat data a provádět další operace. V tomto článku si ukážeme důvody, které nás vedly k implementaci technologií, které využívají čistě internetové servery, jako je Twitter či Google.

Při výběru technologie, která by nám měla umožnit přístup k ekonomickému systému, jsme měli několik možností. Nicméně naše požadavky byly trošku specifické. Potřebovali jsme:

  • umožnit síťový přístup k rozhraní,
  • jeho funkčnost napříč podporovanými operačními systémy (Windows, Linux a Mac OS X),
  • možnost volání z různých programovacích jazyků.

Před realizací jsme dále kladli velký důraz na jednoduchost a intuitivnost. Ideálem bylo pro nás takové rozhraní, které nepotřebuje dokumentaci.

Co používá konkurence

Před samotnou realizací jsem se porozhlédli co nabízí konkurence. V podstatě všechna studovaná řešení provádí výměnu dat vlastním formátem postaveným na XML. Ke komunikaci využívají následující rozhraní:

  • COM/DCOM/Acti­veX/OLE: technologie, které jsou velmi používané ve světě Windows. Jak už jsem ale psal, naše rozhraní musí fungovat i na Linuxu a Mac OS X a navíc má do jednoduchosti daleko (z historických důvodů). Proto jsme je rovnou zavrhli.
  • Pouštění z příkazové řádky: celkem originální postup, kdy připravíme XML a spustíme program, který si data naimportuje. Nevýhodou tohoto řešení je, že neumožňuje síťový přístup, anebo jen velmi omezeně.
  • RMI: protože je naše aplikace napsaná v Javě, zvažovali jsme také použití protokolu RMI. Nicméně toto rozhraní má jednak problémy s průchodem přes NAT (tj. zde nechodí automaticky) a za druhé je použitelné jen z programovacího jazyka Java.
  • WebServices: poměrně silný kandidát, který je dnes hojně využíván napříč programovacími jazyky a platformami. Slabou stránkou tohoto rozhraní je jednoduchost.
  • REST API: zvažujeme-li webové služby a protokol HTTP, logicky musíme dojít i k rozhraní postavené na REST API (Representational State Transfer). To je postavené na webových technologiích (HTTP) a je velmi jednoduché na používání. Pro jeho prozkoumání a také vyvolání stačí uživateli běžný webový prohlížeč. Protokol HTTP umožňuje velký rozsah funkcí. Mimo jiné nabízí autorizaci, cachování, expiraci či vysokou škálovatelnost. Více informací o REST najdete v článku REST: architektura pro webové API.

Po důkladné analýze jsme se nakonec rozhodli pro REST API.

Problémy, které jsme museli překonat

Základem REST je protokol HTTP (i když mohou být i jiné). Proto jsme potřebovali HTTP server. Obvykle se používá webový server Apache, který pak přistupuje k aplikaci (např. z PHP aplikace). Nicméně my jsme tento přístup nemohli použít, protože bychom komplikovali proces instalace a dalšího nastavení. A tak nám zbyla jen jedna možnost: desktopová aplikace musí sama o sobě podporovat HTTP server.

Pro tyto účely jsme zvolili implementaci HTTP serveru Jetty. Jetty je velmi malý a rychlý HTTP server, který startuje velmi krátce, a tudíž nezpomaluje spuštění aplikace. Měli bychom upřesnit, že naše aplikace používá architekturu klient/server/SQL server, a proto je obsluha HTTP součástí našeho serveru. Tato kombinace je používána i jako jednouživatelská instalace, a tak jsme nechtěli nijak prodloužit start a paměťové zatížení.

Jak už bylo zmíněno, jako základ komunikace jsme použili XML. Pro zjednodušení práce s rozhraním REST API z JavaScriptu jsme přidali podporu formátu JSON. V našem případě provádíme automatickou konverzi z XML na JSON, a proto je struktura obou formátů shodná. Nakonec se ukázalo, že i v jazyce PHP je snazší pracovat s formátem JSON než s XML.

Protože rozhraní podporuje více formátů, využíváme podpory protokolu HTTP pro automatickou domluvu formátu pomocí hlavičky Accept. Když chce uživatel rozhraní soubor ve formátu XML, použije hlavičku: Accept: application/xml. Narazili jsme ovšem na problém: některé prohlížeče (např. ten v mobilech s Androidem) jako první uvádějí, že chtějí XML, a přitom myslí XHTML. Proto jsme museli vytvořit filtr, který pokud najde mezi požadovanými formáty text/html, tak jej zařadí na začátek. Stejně tak pokud prohlížeč pošle jen Accept: */* (tj. přijímám všechny formáty), posíláme implicitně HTML verzi. Pokud tedy chcete XML či JSON, je nejlepší uvést do hlavičky Accept jen tento formát. Protože dnešní prohlížeče uživateli neumožňují snadno ovlivnit tuto hlavičku, museli jsme navíc přidat podporu pro domluvu formátu dle přípony. Uživatel může použít URL GET /c/moje_firma/faktura-vydana.json, získat výstup ve formátu JSON a přitom nepotřebuje další nástroje.

Struktura URL

I když už aplikace podporuje protokol HTTP, jsme stále na začátku. Nyní musíme navrhnout strukturu URL, kterou bude naše aplikace používat. My jsme potřebovali standardní CRUD (Create/Read/Up­date/Delete) strukturu:

  • Výpis objektů: GET /c/moje_firma/faktura-vydana
  • Přečtení objektu: GET /c/moje_firma/faktura-vydana/1
  • Založení objektu: PUT /c/moje_firma/faktura-vydana
  • Změna objektu: PUT /c/moje_firma/faktura-vydana/1

U výpisu objektů potřebujeme zpracovávat další případy:

  • stránkování: ?limit=10&start=10
  • informace o počtu objektů kvůli stránkování: ?add-row-count=true přidá do generovaného dokumentu informace o počtu objektů
  • řazení: ?order=nazev případně vzestupně ( ?order=nazev@A) a sestupně ( ?order=nazev@D)
  • filtrace: vytvořili jsme jednoduchý filtrační jazyk s možností and/or, závorkování a podmínek: (datSplat < now() and uzivatel = me())

Winstrom

Výstupní formáty

Kromě již zmíněných XML, JSON a HTML jsme přidali podporu pro další formáty. Prioritou pro nás byl export do formátu PDF či do e-faktury ISDOC. Následně, kvůli integraci s dalšími aplikacemi, vznikl export do e-vizitky vCard a kalendáře iCal. Díky tomu si uživatelé mohou ve svém kalendáři zobrazit splatnosti neuhrazených faktur. Protože se jedná jen o výstupní formát, lze na něj aplikovat funkce pro výpis objektů jako je filtrace či řazení.

PDF

Identifikace objektů

Každému objektu (faktuře, kontaktu atd.) je vždy systémem přidělen jednoznačný číselný identifikátor. Ten je používán jako součást URL. Abychom si zjednodušili práci, používáme jako identifikátory i další symboly:

  • vnitřní ID, přidělované ekonomickým systémem: /c/moje_firma/adresar/1
  • kód firmy: /c/moje_firma/adresar/code:FIRMA
  • DIČ firmy: /c/moje_firma/adresar/vatid:CZ28019920
  • čárový kód EAN: /c/moje_firma/adresar/ean:8594040311025

Tyto identifikátory lze použít jako součást URL i jako součást importovaného XML (např. odkaz na firmu v adresáři nebo zboží v katalogu).

Přidali jsme také podporu tzv. externích ID, které umožňuje uložit identifikátor dalšího systému přímo k objektu v ekonomickém systému. Mapování mezi systémy tak může být přímo ve WinStromu. Externí ID je ve formě: ext:FAKTURACNI1:123, kde FAKTURACNI1 je identifikátor dalšího systému.

Aby nedocházelo ke vzniku duplicitního obsahu (stejný objekt pod různými typy identifikátorů), je při použití jiného než vnitřního ID použito HTTP přesměrování (302 Permanently Moved).

Aktualizace a validace

Programátorské rozhraní musí umožňovat nejen vytvoření objektu, ale i jeho změnu, nebo jen změnu jeho části (atributu). Pokud je uveden atribut (např. název firmy), dojde k jeho přepsání. Pokud není, ke změně nedojde a zůstane nastavena původní hodnota. Pokud chceme hodnotu vynulovat, uvedeme prázdný atribut.

To samé jsme aplikovali i na podobjekty (např. položky faktury). Podobjekty lze měnit, přidávat a mazat.

Neméně důležitou kapitolou je validace. Když přes rozhraní odešleme data do systému, chceme získat seznam validačních chyb nebo varování. Protože se některé položky umí automaticky vypočítat, může uživatel rozhraní chtít odeslat data na server, nechat zvalidovat a přijmout zpátky přepočtená. Pro tyto účely slouží testovací režim. Ten se zapíná parametrem ?dry-run=true. V takovém případě se data neukládají, ale jsou vrácena v takovém stavu, v jakém by byla uložena.

Zvyklosti v REST API

Při vývoji rozhraní jsme zkoušeli komunikovat s aplikacemi psanými v různých frameworcích a jazycích. Při těchto pokusech jsem naráželi na to, že REST je architektonický styl a nedefinuje žádný typy použití, jako je stránkování či filtrace. Z těchto důvodů každý nástroj očekává jiné parametry či data v jiném formátu.

Ukázkou může být typický požadavek z naší aplikace:

GET /c/moje_firma/faktura-vydana/(dic='CZ123456')
<winstrom version="1.0">
    <faktura-vydana>
        <id>1</id>
    </faktura-vydana>
</winstrom>

A v Ruby On Rails:

GET /c/moje_firma/faktury-vydane?dic=CZ123456
<faktury-vydane>
    <faktura-vydana>
        <id>1</id>
    </faktura-vydana>
</faktury-vydane>

Na předchozím příkladu je vidět, že ta samá věc může mít různé reprezentace. Problém jsme vyřešili tak, že se vždy snažíme podporovat více variant (např. různé URL, různé způsoby řazení, …). V těch případech, kdy to nejde, umožňujeme přepnutí režimu pomocí  ?mode=ruby.

Automatická dokumentace

Jedním z požadavků, které jsem na začátku uvedl, byla i jednoduchost použití pro vývojáře. Snažili jsme se vše vytvořit tak, aby základní vývojářská dokumentace byla vždy součástí produktu. Proto do všech generovaných XML dokumentů automaticky doplňujeme i komentáře o názvu položky, jejím typu, délce a seznamu povolených hodnot. Abychom generované dokumenty zbytečně nenafukovali, doplňujeme tuto informaci jen u prvního objektu. Pokud uživatel rozhraní dostane vygenerovaný XML, ihned vidí, co která položka znamená.

V jednoduchosti použití rozhraní jsme zašli ještě dále, a tak jsme do aplikace přidali možnost přepnout si stránky do vývojářského režimu. Díky tomu místo výpisu faktur dostaneme informaci o tom, co daná stránka zobrazuje, jaké je zapnuté stránkování a zda případně jaký je aplikován filtr. Je také možné si přepnout na seznam položek, kde je o každé položce zobrazeno mnohem více informací. Tyto informace je opět možné zobrazit ve formátu HTML, XML a JSON.

Budoucnost

Už jsme se zmínili o možnosti exportovat data do formátu iCal. Možností, které toto rozhraní přináší, je ovšem mnohem více. Mohli bychom si na iGoogle zobrazovat prodeje za poslední měsíc, v mapách zobrazovat prodeje pro jednotlivé oblasti a nebo jen seznam zákazníků v okolí nějakého místa kam se právě chystáme.

Všechny tyto možnosti nyní ale naráží na velký problém. Tím je autorizace přístupu. Standardně je používána HTTP autorizace (tedy jméno a heslo). Nicméně pokud bych chtěl Google kalendáři umožnit přístup k mým datům, narazím na problémy. I kdyby Google uměl přistupovat k zabezpečeným datům, otázka zní, zda bychom mu to vůbec chtěli umožnit. Kvůli takovéto drobnosti bychom mu vlastně umožnili kompletní přístup k celému systému (používal by náš účet). Když nad tímto problémem zapřemýšlíte, hned vás napadne: ale tohle už jsem přeci řešil u Facebooku a Twitteru. Zde také jednotlivým aplikacím povoluji přístup k datům a přitom jim nemusím předávat jméno a heslo. Proto bychom chtěli implementovat zabezpečení pomocí OAuth.

Do budoucna se chystáme dále rozšířit možnosti rozhraní a podpořit vývojáře, kteří jej budou používat. Chceme vytvořit ukázkové aplikace, které budou demonstrovat možnosti.

Petr Ferschmann

V současné době je vedoucí vývojového oddělení společnosti WinStrom s.r.o.

Přehled názorů

Reklama na WinStrom?
Jens.cz 9. 9. 2009 02:59
├ 
Re: Reklama na WinStrom?
Martin Malý 9. 9. 2009 10:06
└ 
Re: Reklama na WinStrom?
asi to jinak nejde 9. 9. 2009 11:01
Re: REST API jako rozhraní desktopové aplikace
--- 9. 9. 2009 06:35
├ 
Re: REST API jako rozhraní desktopové aplikace
Zorg 9. 9. 2009 09:35
│
└ 
Re: REST API jako rozhraní desktopové aplikace
Martin Malý 9. 9. 2009 10:08
└ 
Re: REST API jako rozhraní desktopové aplikace
q 9. 9. 2009 14:28
 
└ 
Re: REST API jako rozhraní desktopové aplikace
Martin Malý 9. 9. 2009 14:35
 
 
└ 
Re: REST API jako rozhraní desktopové aplikace
Prezdivky nikdy nebyly 9. 9. 2009 14:41
 
 
 
└ 
Re: REST API jako rozhraní desktopové aplikace
Martin Malý 9. 9. 2009 14:44
 
 
 
 
└ 
Re: REST API jako rozhraní desktopové aplikace
Přezdívka dvojtečka 9. 9. 2009 14:54
 
 
 
 
 
└ 
Re: REST API jako rozhraní desktopové aplikace
cgi 10. 9. 2009 10:30
Výborný článek z praxe!
davidmach14 9. 9. 2009 08:27
└ 
Re: Výborný článek z praxe!
alblaho 9. 9. 2009 08:53
 
└ 
Re: Výborný článek z praxe!
Lael Ophir 10. 9. 2009 05:39
Trapné PRko
Martin 9. 9. 2009 09:28
├ 
Re: Trapné PRko
Petr Ferschmann 9. 9. 2009 09:51
│
└ 
Re: Trapné PRko
Prezdivky nejsou 9. 9. 2009 14:37
│
 
└ 
Re: Trapné PRko
Petr Ferschmann 9. 9. 2009 14:56
│
 
 
└ 
Re: Trapné PRko
Přezdívka nikdy povinná nebude.... :) 9. 9. 2009 15:04
│
 
 
 
└ 
Re: Trapné PRko
Petr Ferschmann 9. 9. 2009 15:14
├ 
Re: Trapné PRko
Tomáš 9. 9. 2009 09:51
├ 
Re: Trapné PRko
Martin Malý 9. 9. 2009 10:21
│
└ 
Re: Trapné PRko
Přezdívky na rootu 9. 9. 2009 15:01
│
 
└ 
Re: Trapné PRko
Martin Malý 9. 9. 2009 15:08
│
 
 
└ 
Re: Trapné PRko
Prezdivky jednoduse povinne nejsou 9. 9. 2009 15:26
│
 
 
 
├ 
Re: Trapné PRko
Petr Ferschmann 9. 9. 2009 15:30
│
 
 
 
│
└ 
Re: Trapné PRko
Petr Ferschmann 30. 9. 2009 00:43
│
 
 
 
└ 
Re: Trapné PRko
Martin Malý 9. 9. 2009 15:35
│
 
 
 
 
└ 
Re: Trapné PRko
Prezdivka je blbost 9. 9. 2009 16:20
└ 
Re: Trapné PRko
Tomas 9. 9. 2009 14:27
Souhrnná odpověď
Martin Malý 9. 9. 2009 10:04
└ 
Re: Souhrnná odpověď
Peter Helcmanovsky 9. 9. 2009 10:10
 
└ 
Re: Souhrnná odpověď
Ján Letko 9. 9. 2009 11:39
 
 
└ 
Re: Souhrnná odpověď
Jens.cz 9. 9. 2009 12:38
 
 
 
├ 
Re: Souhrnná odpověď
Martin Malý 9. 9. 2009 12:49
 
 
 
├ 
Re: Souhrnná odpověď
Ján Letko 9. 9. 2009 12:52
 
 
 
│
└ 
Re: Souhrnná odpověď
Martin Malý 9. 9. 2009 13:04
 
 
 
├ 
Re: Souhrnná odpověď
Peter Helcmanovsky 9. 9. 2009 14:24
 
 
 
│
└ 
Re: Souhrnná odpověď
Martin Malý 9. 9. 2009 14:31
 
 
 
│
 
└ 
Re: Souhrnná odpověď
Jaro 11. 9. 2009 23:08
 
 
 
└ 
Re: Souhrnná odpověď
Ivan Nový 12. 9. 2009 10:33
pěkné
Michal Augustýn 9. 9. 2009 10:34
priklad z praxe je v poradku
uf 9. 9. 2009 10:56
Diky za realnou case-study a propagaci RESTful rozhrani u nas
karmi 9. 9. 2009 10:56
└ 
Re: Diky za realnou case-study a propagaci RESTful rozhrani u nas
Petr Ferschmann 9. 9. 2009 11:04
 
└ 
Re: Diky za realnou case-study a propagaci RESTful rozhrani u nas
karmi 9. 9. 2009 11:44
 
 
└ 
Re: Diky za realnou case-study a propagaci RESTful rozhrani u nas
Petr Ferschmann 9. 9. 2009 11:46
snaha informatiky byt neco vice
backup 9. 9. 2009 14:07
├ 
Re: snaha informatiky byt neco vice
uf 9. 9. 2009 20:10
└ 
Re: snaha informatiky byt neco vice
Kvík 10. 9. 2009 16:17
REST Knihovna a autentizace
Petr 9. 9. 2009 14:35
├ 
Re: REST Knihovna a autentizace
karmi 9. 9. 2009 15:14
│
└ 
Re: REST Knihovna a autentizace
karmi 9. 9. 2009 15:17
└ 
Re: REST Knihovna a autentizace
Petr Ferschmann 9. 9. 2009 16:06
 
└ 
Re: REST Knihovna a autentizace
Petr 10. 9. 2009 11:09
 
 
└ 
Re: REST Knihovna a autentizace
Petr Ferschmann 10. 9. 2009 11:13
Lokalnici
skrat 9. 9. 2009 15:13
└ 
Re: Lokalnici
Petr Ferschmann 9. 9. 2009 15:28
Poděkování za článek
Jirka Hradil 9. 9. 2009 16:18
pekne
uf 9. 9. 2009 20:22
└ 
Re: pekne
uf 9. 9. 2009 20:26
 
├ 
Re: pekne
uf 9. 9. 2009 22:20
 
├ 
Re: pekne
Karel 11. 9. 2009 16:49
 
└ 
Re: pekne
Peter Helcmanovsky 14. 9. 2009 16:20
díky
paranoiq 13. 9. 2009 21:32
Dotaz: jak se resi autentifikace u RESTful ?
uf 16. 9. 2009 13:40
└ 
Re: Dotaz: jak se resi autentifikace u RESTful ?
uf 5. 10. 2009 07:29
HTTP autorizace a CSRF
Jan Pejša 24. 9. 2009 08:07
WebDAV
xurfa 24. 9. 2009 21:41
└ 
Re: WebDAV
pk 30. 9. 2009 22:30
Sem s takovými "PR články"
Zdeněk Michálek, oXy Online 1. 10. 2009 21:42
Zabezpeceni
Kamil 2. 11. 2009 07:30
└ 
Re: Zabezpeceni
Uf 2. 11. 2009 20:23
       
Zasílat nově přidané příspěvky e-mailem