Java na webovém serveru: AJAX formuláře

Od minulého dílu umožňuje naše aplikace vkládat komentáře, ovšem ne příliš pohodlným způsobem. Dnes si proto ukážeme, jak uživatelům komentování zpříjemnit pomocí oblíbeného AJAXu. Využijeme k tomu knihovnu jQuery na straně klienta a servlety na straně serveru.
Seriál: Java na webovém serveru (16 dílů)
- Java na serveru: úvod 8. 1. 2010
- Java na webovém serveru: první web 15. 1. 2010
- Java na webovém serveru: práce s databází 29. 1. 2010
- Java na webovém serveru: práce s databází II 12. 2. 2010
- Java na webovém serveru: lokalizace a formátování 19. 2. 2010
- Java na webovém serveru: autorizace a autentizace 26. 2. 2010
- Java na webovém serveru: autorizace a autentizace II 5. 3. 2010
- Java na webovém serveru: porovnání Javy a PHP 10. 3. 2010
- Java na webovém serveru: Vlastní JSP značky a servlety 17. 3. 2010
- Java na webovém serveru: posílání e-mailů a CAPTCHA 24. 3. 2010
- Java na webovém serveru: píšeme REST API 7. 4. 2010
- Java na webovém serveru: SOAP webové služby 14. 4. 2010
- Java na webovém serveru: hlasování a grafy v SVG 28. 4. 2010
- Java na webovém serveru: Komentáře a integrace s Texy 9. 6. 2010
- Java na webovém serveru: AJAX formuláře 23. 6. 2010
- Java na webovém serveru: implementujeme Jabber 30. 6. 2010
Nálepky:
Implementace komentářů z minulého dílu byla sice funkční, ale značně nedokonalá. V případě, že uživatel udělal ve formátování komentáře chybu (zadal nepovolené XHTML značky atd.), dostal po odeslání od serveru chybovou hlášku, ale už neměl šanci chyby napravit – byl odkázán na funkci „zpět“ svého prohlížeče, u které není zaručeno, že se vyplněné údaje z formuláře neztratí. Pokud se mu naopak povedlo naformátovat komentář správně, mohlo snadno dojít k několikanásobnému odeslání (pokud by uživatel obnovil stránku).
Naším dnešním cílem proto bude, umožnit uživatelům zobrazit si náhled formátování komentáře a odeslat ho, aniž by se načítala celá stránka – místo klasického odesílání formuláře vyvoláme asynchronní požadavek javascriptem a odpověď serveru zobrazíme v rámci již načtené stránky.
Jako obvykle si nejprve si aktualizujeme zdrojové kódy aplikace pomocí Mercurialu:
$ hg pull $ hg up "15. díl"
Případně je můžete stáhnout jako bzip2 archiv přes web.
Na straně klienta
S implementací na straně klienta nám pomůže knihovna jQuery, kterou již ve své aplikaci používáme. Umožňuje snadnou práci s AJAXem a odstiňuje nás od odlišností jednotlivých prohlížečů. Klientský kód je stručný a naleznete ho v souboru komentare.js
:
komentare.nahled = function() { $("#formularKomentuj .vystup").load("komentare", $("#formularKomentuj form").serialize()); }; komentare.odeslat = function() { $("#formularKomentuj .vystup").load("komentare?odeslat=true", $("#formularKomentuj form").serialize()); };
jQuery funkce load()
vyvolá HTTP požadavek na dané URL (v našem případě komentare
– první parametr), pomocí nějž předá serveru obsah formuláře (ve standardním URL kódování). Odpověď serveru pak tato funkce vloží do elementu, který jsme si pro tento účel připravili. Javascriptové funkce nahled()
a odeslat()
navážeme na události formuláře místo klasického (synchronního) odeslání, které je spojeno s načtením celé nové stránky.
Formulář vymažeme až po úspěšném uložení komentáře na serveru – vložené údaje se tak uživateli neztratí, ani při dočasné chybě serveru nebo špatné syntaxi komentáře. Smazáním obsahu formuláře se pak vyhneme případnému opětovnému odeslání (komentář s nulovou délkou nelze vložit). Případně bychom mohli formulář skrýt nebo ho nechat třeba „odletět“ pomocí nějakého pěkného efektu, to už nechám na vás (začít můžete třeba u pluginů do jQuery jako je Flip!).
Na straně serveru
Na straně serveru teď potřebujeme nějak obsloužit požadavky, které přicházejí na URL /komentare
. K tomu využijeme technologii servletů, se kterou jsme se seznámili v devátém díle. Implementaci datové vrstvy a kontroly formátování máme hotovou už od minule a zapouzdřenou do EJB, takže jí přepisovat nemusíme – jediné, co je potřeba upravit, je relativně tenká vrstva, která se stará o překlad z HTTP parametrů na objekty a o vykreslení hlášek informujících uživatele o výsledku (původní implementace této vrstvy byla celá v JSP).
Servlety nám umožní příjemnější zápis dané logiky než JSP – přeci jen programovat v dokumentově orientovaném formátu XML cykly a podmínky není dvakrát zábavné ani pro milovníky XML.
Náš servlet se nachází ve třídě Komentare
a podstatná je jeho metoda doPost()
:
@Override protected void doPost(HttpServletRequest pozadavek, HttpServletResponse odpoved) throws ServletException, IOException { PodnikRemote ejb = hledac.getPodnikEJB(); /** Načteme HTTP parametry */ Komentar k = new Komentar(); k.setPodnik(Integer.decode(pozadavek.getParameter("podnik"))); k.setNadpis(pozadavek.getParameter("nadpis")); k.setKomentar(pozadavek.getParameter("komentar")); k.setTyp(Komentar.TYP.valueOf(pozadavek.getParameter("typ"))); boolean ulozit = Boolean.valueOf(pozadavek.getParameter("odeslat")); String jsp; try { /** Komentář odešleme do nižší vrstvy ke kontrole nebo rovnou k uložení */ k = ejb.komentuj(k, ulozit); pozadavek.setAttribute("komentar", k); if (ulozit) { jsp = "/WEB-INF/casti/ajaxKomentare/odeslano.jsp"; } else { jsp = "/WEB-INF/casti/ajaxKomentare/nahled.jsp"; } } catch (Exception e) { /** Objekty mezi servletem a JSP si můžeme předávat pomocí atributů požadavku */ pozadavek.setAttribute("chyba", e); jsp = "/WEB-INF/casti/ajaxKomentare/chyba.jsp"; } /** O vykreslení XHTML vyýstupu se už zase postará JSP */ RequestDispatcher rd = getServletContext().getRequestDispatcher(jsp); rd.forward(pozadavek, odpoved); }
Z HTTP požadavku si nejprve načteme parametry a tím provedeme i jejich základní typovou kontrolu. Nějaké uživatelsky přívětivé chybové hlášky v této fázi nemusíme řešit – pokud by např. v parametru podnik
nebyla celočíselná hodnota nebo parametr typ
neodpovídala našemu číselníku ( enum
), došlo by ke standardní chybě 500 Interní chyba serveru. To se ale stane jen v případě, že by se uživatel v aplikaci „vrtal“ a podstrkával jí ručně svoje parametry – na takového uživatele nemusíme brát zřetel a vyrábět pro něj přívětivé chybové hlášky.
Školení Javy
Java je multiplatformní programovací jazyk, který vytvořila a vyvíjí společnost Sun. Java je silný, objektově orientovaný jazyk se širokou komunitou, nabízející především vysokou produktivitu vývoje. Přijďte na školení Základy programovacího jazyka Java 7. 9. 2010 od 9:00, nebo na Pokročilejší kurz jazyka Java 8. 9. 2010 opět od 9:00.
V Javě se skvěle programuje, ale na druhou stranu se v ní špatně vytvářejí HTML dokumenty – mohli bychom k tomu sice použít HttpServletResponse.getWriter().print(String
a „lepit“ výsledné HTML z kousků textu, ale nejen že by to bylo nepohodlné, ale také by byla velká pravděpodobnost, že někde uděláme chybu a výsledný kód bude obsahovat např. neuzavřené značky. Naštěstí existuje způsob, jak skloubit programování v Javě a vytváření HTML v JSP dohromady. Pomocí
text);RequestDispatcher
u a jeho metody forward()
můžeme řetězit za sebe servlety a JSP (což jsou ve výsledku taky servlety) a díky tomu udělat část práce v javovském kódu a část v JSP.
V připojeném JSP máme k dispozici jednak původní GET/POST parametry, které dorazily na servlet a jednak JSPčku můžeme předávat další data (objekty) pomocí atributů požadavku – HttpServletRequest.setAttribute()
, které jsou identifikované jednoduše textovým klíčem.
Vytvořený servlet nezapomeneme přidat do souboru web.xml
a namapovat na požadované URL:
<servlet> <description>Odesílání a náhledy komentářů pomocí AJAXu.</description> <servlet-name>komentare</servlet-name> <servlet-class>cz.frantovo.nekurak.servlet.Komentare</servlet-class> </servlet> <servlet-mapping> <servlet-name>komentare</servlet-name> <url-pattern>/komentare</url-pattern> </servlet-mapping>
JSP, na které se v servletu odkazujeme, je velmi jednoduché a nám známé – nový je jen způsob, kterým přistupujeme k atributům požadavku (objektům). Ty se nacházejí v poli requestScope[]
pod námi zvoleným klíčem. Dále s těmito objekty pracujeme, jak jsme zvyklí (pomocí .komentar
přistupujeme k vlastnosti objektu – ve výsledku se volá metoda getKomentar()
třídy Komentar
).
<?xml version="1.0" encoding="UTF-8"?> <jsp:root xmlns:jsp="http://java.sun.com/JSP/Page" xmlns:c="http://java.sun.com/jsp/jstl/core" xmlns:fmt="http://java.sun.com/jsp/jstl/fmt" xmlns:fn="http://java.sun.com/jsp/jstl/functions" xmlns:nk="urn:jsptagdir:/WEB-INF/tags/nekurak" version="2.0"> <div> <p class="informacniHlaska"><fmt:message key="komentare.nahledNadpis"/>:</p> <!-- XHTML je už zkontrolované: → vypíšeme ho rovnou --> ${requestScope['komentar'].komentar} </div> </jsp:root>
Závěr
Dnes jsme vylepšili naši aplikaci tak, aby se formulář pro komentování odesílal AJAXem, což uživatelům zpříjemní práci s webem – tedy alespoň těm se zapnutým Javascriptem (pro ostatní je tu původní implementace s klasickým odesíláním HTML formuláře). Při tom jsme si prakticky ukázali, jak skloubit servlety a JSP a mít z obou to lepší – ze servletů programování a z JSP tvorbu HTML/XML dokumentů.
Odkazy
- jQuery serialize() – funkce pro URL-kódování formulářů.
- jQuery load() – jednoduchá funkce pro načítání AJAXových odpovědí do elementu.
- jQuery Ajax – plnohodnotné funkce pro práci s AJAXem.
- RequestDispatcher vs. sendRedirect – rozdíl RequestDispatcheru oproti HTTP přesměrování.
- Myslete, když navrhujete formulář – blogový zápisek s šikovnými tipy k našemu tématu.
- Použitelné a přístupné webové formuláře – další pojednání na téma formuláře.
Je to už onlajn na nekurak.net? :) Nějak to tam nevidím.
jj, je – jen je potřeba být přihlášený (to tam taky je napsané).
jméno: zdrojak.root.cz
heslo: heslo
P.S. a je potřeba mít zapnutý JS, protože jinak se ten AJAXový formulář neaktivuje a odesílá se klasicky (a pak nejde náhled – což by správně jít mělo, ale prostě to není implementované).
Tak to se omlouvám, zřejmě jsem to přehlédl. :)
Nic se neděje.
BTW: zatím je celá ta aplikace dělaná hlavně jako příloha k seriálu, technologie, na design a použitelnost zatím nebyl čas – ale i tak vítám návrhy a připomínky v tomto směru :-)
Neda mi to a musim zminit JSF 2.0, se kterymi je ajaxove odesilani formularu o mnoho jednodussi ;)
Ale je mi jasne, ze nebudes do projektu tahat Faces jen kvuli tomu ;)
Myslis nieco taketo?
http://zdrojak.root.cz/clanky/java-na-webovem-serveru-ajax-formulare/
http://www.developer.com/java/web/article.php/10935_3870686_2/Inside-JSF-20s-Ajax-and-HTTP-GET-Support.htm
A myslis to vazne?
Kde je tam nejaka RESTovskost?
Ako tam volam POST, alebo DELETE metodu?
Myslim ze JSF maju malo spolocneho s principmi Webu. :(
Nejak se nam to v hlavince pomichalo, ze? :)
Fanaticke cpani RESTu vzdycky a vsude je zcela kontraproduktivni a k nicemu. Delas z toho svatou valku a podstata veci ti unika. Necpu JSF vsude a vubec netvrdim, ze se na vsechno hodi. A stejne tak nema smysl to delat s klasickymi request-response RESTful rameworky.
Mene ideologie, vice pragmatismu.
Nejak se nam to v hlavince pomichalo, ze? :)
Ze sa Vam to v hlavicke pomiesalo som si vsimol a preto som sa pokusil Vam v tej hlvicke svojim prispevkom spravit poriadocek. :)
Fanaticke cpani RESTu vzdycky a vsude je zcela kontraproduktivni a k nicemu.
REST predstavuje fundamentalne principy na ktorych funguje Web, prosim dostudujte si to. Cim sa Vase riesenie vzdaluje viac od RESTu, vzdaluje sa od Webu.
REST == Web
Delas z toho svatou valku a podstata veci ti unika. Necpu JSF vsude a vubec netvrdim, ze se na vsechno hodi. A stejne tak nema smysl to delat s klasickymi request-response RESTful rameworky.
Mene ideologie, vice pragmatismu.
Tento Vas nazor je typickym pre tych, ktori neovladaju tie zakladne principy webu a myslia si, ze ked sa naucia nieco klikat v nejakom frameworku, tak vlastne rozumeju Webu. :(
Myslim ze o RESTe a Webe sa napisalo uz dost. Je cas aby ste si to precitali, pokusili sa to pochopit a zacali tie principy respektovat.
Vy si myslite, ze rozumiete Webu lepsie ako ti, ktori ho narhli? :)
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
No on je mozna trochu problem v tom, ze kdyz Web (resp. HTTP) vznikal, tak se nepocitalo s tim, ze se v tech samych technologiich budou psat tak „komplikovane“ aplikace, ktere na dnesnim Webu bezi, nemluve o ruznych intranetovych aplikacich a IS. Souhlasim s Danielem – je rada situaci, kdy stavovost (rozumej stateful aplikace) je nanejvys vhodna.
A jeste jedna poznamka: framework neznamena klikani.
Ak hovorime o Webovej aplikacii, je to aplikacia ktora je v zhode s principmi Webu, teda RESTu.
Ak pouzijete prehliadac a HTTP inym sposobom, je to na vas, ale potom to uz nie je Webova aplikacia. Je to taky „Webovy paskvil“. To su asi presne tie intranetove aplikacie a IS, o ktorych hovorite. Tie paskvily vacsinov robia „odbornici“ s nazormi ake ma Daniel Kvasnička ml., vacsinou bezia iba v IE6 a su napisane v JSF. :)
Poznamka: Nie som si isty, ci Daniel Kvasnička ml. si pod FW nepredstavuje prave nieco klikacie. :)
Nikomu, kto rozumie Webu nemoze vyhovovat JSF.
To je trochu definice kruhem :) IE6 je vsak podle me stejny nepritel jak pro tvurce „paskvilu“, tak pro tvurce „pravovernych“ webovych aplikaci, jako jste Vy.
Pánové, žádám vás: držte se tématu a nenechte rozhořčení cloumat svými majestáty. Děkuji.
http://www.youtube.com/watch?v=KrfpnbGXL70
úžasné video, díky :-)
„This video is private“
http://jz10.java.no/java-4-ever-trailer.html
Mozno maju nieco proti jehovistom :)