Oblíbená trojkombinace technologií v podobě aplikačního rámce Spring, DWR a jQuery nám umožňuje Javascriptem volat metody servisních tříd spravovaných Springem. To je poměrně efektivnější přístup než příprava podobných řešení přímo v duchu MVC. Ve Springu 3.0. je však nově implementována zjednodušená podpora pro Ajax v podobě mvc-ajax modulu, která by naší trojkombinaci mohla v určitých případech konkurovat. Vyzkoušíme a uvidíme. Integraci aplikačního rámce Spring, DWR a jQuery řešíme téměř na každém projektu. Požádali jsme kolegu Michala Chudého, aby toto téma jednou pro vždy zpracoval a nyní dáváme jeho část k dispozici i vám.

Úvod

Knižnica DWR (Direct Web Remoting) je technológia postavená na konceptoch AJAX-u (Asynchronous JavaScript and XML) umožňujúca volanie Java metód z klientského JavaScriptu za pomoci asynchrónnych požiadaviek na server a umožňujúca prevod Java objektov na štruktúry používané JavaScritpom a naopak. DWR je tak isto schopné vyvolávať JavaScritpové funkcie na klientovi z Java kódu na serveri, čo je prínosom napríklad pri implementácii chatu.

Nasadenie do aplikácie, integrácia so Spring-om a konfigurácia

Konfigurace

Existuje viac spôsobov nasadenie DWR do aplikácie používajúcej Spring 2.x a vyšší. Prvou je nadefinovanie servletu a mapovania vo web.xml:

<servlet>
  <servlet-name>dwr</servlet-name>
  <servlet-class>org.directwebremoting.spring.DwrSpringServlet</servlet-class>
  <init-param>
    <param-name>debug</param-name>
    <param-value>true</param-value>
  </init-param>
</servlet>

<servlet-mapping>
  <servlet-name>dwr</servlet-name>
  <url-pattern>/dwr/*</url-pattern>
</servlet-mapping>

túto metódu je vhodné použiť keď nepoužívame Spring MVC modul. Druhou metódou je použite namespace (menných priestorov). Spring od verzie 2.x poskytuje XML Namespace Handler, ktorý zaručí, že ak pridáme do hociktorého <beans> tagu v hociktorom aplikačnom kontexte, v ktorom sa nachádza aspoň jeden dwr tag, nasledujúce riadky, budú DWR volania fungovať.


xmlns:dwr="http://www.directwebremoting.org/schema/spring-dwr"
xsi:schemaLocation="http://www.directwebremoting.org/schema/spring-dwr
http://www.directwebremoting.org/schema/spring-dwr-3.0.xsd"

DWR requesty sú mapované na DispatcherServlet vo web.xml:

<servlet>
  <servlet-name>web</servlet-name>
  <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
  <init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/webApplicationContext*.xml</param-value>
  </init-param>
</servlet>
 .
 .
 .
<servlet-mapping>
  <servlet-name>web</servlet-name>
  <url-pattern>/dwr/*</url-pattern>
</servlet-mapping>
 .
 .
 .

Pri konfigurácii a špecifikácii metód volaných cez DWR máme tak isto viac možností. Na prvom mieste je potrebné spomenúť, že v každom Spring aplikačnom kontexte, kde budú konfigurované beany je potrebné špecifikovať hoci aj prázdy <dwr:configuration> tag. Prvou možnosťou konfigurácie a špecifikácie je definícia metód, ktoré budú dostupné DWR volaniami, v definícii beanov.

<bean id="timeConvert" class="com.mycompany.ui.util.TimeConvert">
    <dwr :remote javascript="AjaxTimeConvert">
      <dwr :include method="convert" />
    </dwr>
</bean>

Tag <dwr:remote> nám určí pod akým názvom bude dostupné javasriptové rozhranie obsahujúce našu volanú metódu (atribút “javascript”) a tag <dwr:include/> označuje metódu danej Java triedy, ktorú bude možné prostredníctvom DWR volať. Názov metódy je špecifikovaný atribútom “method”. Druhým spôsobom je použitie anotácií. Majme príklad Java triedy:


@Service
@RemoteProxy
public class MyBean {

@RemoteMethod
public String hello(String name) {
return "Hello " + name;
}
}

Anotáciu @Service nemusíme predstavovať, nás zaujímajú @RemoteProxy a @RemoteMethod. @RemoteProxy oznamuje DWR enginu, že chceme aby tento bean bol dostupný z klienta (v predchádzajúcej špecifikácii tag <dwr:remote>).

Pomocou nepovinného atribútu “name” môžme špecifikovať iné meno ako je meno beany (napr. @RemoteProxy(name = “Hello”). @RemoteMethod označuje metódu, ktorú bude možné volať z JavaScriptu (v predchádzajúcej špecifikácii tag <dwr:include>). Len metódy anotované touto anotáciuou budú klientovi vystavené. V aplikačnom kontexte musíme špecifikovať skenovanie anotácií:

<dwr :configuration/>
<!-- požiada DWR aby skenoval Springovské beany a hľadal anotácie  -->
<dwr :annotation-config/>
<!-- požiada DWR aby namapoval util.js a engine.js na dwrController -->
<dwr :url-mapping/>
<!-- špecifikuje dwrController -->
<dwr :controller id="dwrController" debug="true" />
Ďalšími dôležitými prvkami DWR konfigurácie sú konvertory. Špecifikujú, ako budú Java objekty prevádzané na javascriptové štruktúry a opačne. Pre základné primitívne Java typy a ich objektové wrappery existujú automatické konvertory, tak ako aj pre java.util.Date a polia a kolekcie spomenutých typov. Ak chceme použiť objekt, ktorý nemá defaultný konvertor, musíme tento konvertor špecifikovať v tagu <dwr:configuration/> napríklad nasledovne:
<dwr:configuration>
    <dwr:convert type="bean" class="myApp.web.dwr.dto.Item"></dwr:convert>
<dwr:configuration/>
kde trieda Item vyzerá nasledovne:

public class Item {

private String name;
private String surname;
private Integer number;

// + gettry / settery pre vsetky polia

Konvertor funguje tak, že prejde všetky get / set metódy objektu a vytvorí ich javascriptovú reprezentáciu v podobe asociatívneho poľa. V prípade, že je vyhodená výnimka v Java kóde, objaví sa v prehliadači javascriptový alert a v ňom zobrazená chybová hláška výnimky. Ak nie je hláška špecifikovaná zobrazí sa len jednoduchý text “A server error has occured”.

Javascript

Vo všetkých webových stránkach kde používame DWR musí byť includovaný skript engine.js. Tento súbor zaobaľuje základnú funkcionalitu DWR a bez neho by vzdialené volania metód nefungovali. Každý bean, označený ako @RemoteProxy alebo definovaný ako <dwr:remote javascript=”…”> a jeho remote metódy sú preložené na JS skripty a ak ich chceme používať musíme ich naincludovať do stránky. Pre príklad si vezmime anotáciami konfigurovaný bean (MyBean). Itegrácia DWR rozhrania do stránky bude vyzerať takto:

<script src='/<cesta>/dwr/interface/MyBean.js' type="text/javascript"></script>

Používanie DWR

Používanie DWR na klientovi je veľmi jednoduché. V nejakej JS funkcii zavoláme Java metódu pomocou názvu rozhrania nasledovne:


function sayHello(name) {
MyBean.hello(name, function(data) {
// do something
});
}

Atribút name sme získali napríklad pomocou jQuery z inputu, kde užívateľ zadal svoje meno (napr. Michal) a Java metóda nám vráti reťazec “Hello Michal”. Najjednoduchšie spracovanie vrátených hodnôt je pomocou javascriptovej callback funkcie, v ktorej môžme napríklad vypísať daný reťazec na stránku.

Reverse AJAX

Ďalšou zaujímavou funkcionalitou je takzvaný Reverse AJAX. V tomto prípade nie je smer asynchrónneho volania klient -> server ale opačný. DWR poskytuje nasledujúce typy Reverse AJAXu:

  • Comet – je spojenie server – klient s dlhou dĺžkou života. Po jeho uzavretí je vytvorené nové spojenie, čo sa už nemusí podariť. Nevýhodou je, že je to veľká záťaž pre server v prípade, že je pripojených veľa klientov. Proxy alebo antivírusové programy môžu držať dáta až kým sa spojenie neukončí, takže by sa dáta zobrazovali až po nejakom čase.
  • PiggyBack – ak má server dáta pre klienta, čaká, pokiaľ sa klient najbližšie nepripojí a v tomto momente zasiela dáta spolu s odpoveďou, o ktorú klient žiadal.
  • Polling – v tomto prípade je smer requestu opačný (klient -> server). Klient periodicky zasiela request na server, či sa neobjavila nejaká zmena. Ak áno, dáta su mu zaslané.