Web Application Frameworks

Z FI WIKI
Přejít na: navigace, hledání


Šablony a průchod aplikací

Webové rámce vznikly proto, aby usnadnily vývoj webových Java aplikací. Jsou nadstavbou nad základní vrstvou pro obsluhu HTTP protokolu, Servlety. Obvykle řeší jednu nebo obě problémové oblasti webových aplikací, kterými jsou

  • řízení průchodu aplikací
  • generování webových stránek ze šablon

Tato řešení mohou, ale nemusí, být nezávislá.

Pro generování webových stránek jsou určeny zejména tyto nástroje:

Je možné je kombinovat s různými rámci pro řízení průchodu aplikací.

Pro řízení průchodu aplikací jsou určeny zejména:

Existují i rámce, které poskytují vlastní řešení pro obé a nelze je kombinovat s jinými rámci:

Generování ze šablon

Spojení dat a šablony

Freemarker overview.png

Dynamicky generované stránky ve webových aplikacích typicky vznikají sloučením šablony, obsahující statický text a značky pro vložení dat, s aktuálními daty. JSP i FreeMarker pro tento účel používají shodnou syntaxi, převzanou z jazyka JavaScript. Šablona vypadá nějak takto:

<html>
 <head>
  <title>${titul}</title>
 </head>
 <body>
 Jste ${uzivatel.jmeno} a máte na účtu č. ${uzivatel.ucet.cislo} celkem ${uzivatel.ucet.stav} Kč
 </body>
</html>

Výhodou JSP je, že jsou integrované v každém servletovém kontejneru. Výhodou FreeMarkeru zase je, že jeho šablony je možné použít pro generování i jiných dokumentů než jsou webové stránky, např. e-mailů nebo statických souborů.

Data jsou jednoduché datové struktury, využívající kombinaci hešovacích tabulek (asociativních polí indexovaných řetězci), sekvencí (klasických polí indexovaných čísly) a skalárních hodnot (řetězců, čísel, booleanů, časových údajů). Pro šablonu z příkladu výše by tedy šlo použít např. strukturu (v JSON zápisu):

{
  "titul": "Stav účtu",
  "uzivatel": {
    "jmeno": "Pepa Novák",
    "ucet": {
      "cislo": "1234567/0100",
      "stav":  10000000
    } 
  }
}


Kromě značek pro doplňování dat jsou nutné ještě řídící konstrukce pro podmíněné větvení, cykly, escapovaní HTML znaků a podobně. JSP pro to využívá JSP značky, zejména standardizovanou knihovnu značek JSTL. Cyklus v JSP/JSTL pak vypadá např.

<c:forEach items="${uzivatel.deti} var="dite">
  ${dite.jmeno}
</c:forEach>

a ve FreeMarkeru takto:

<#list uzivatel.deti as dite>
  ${dite.jmeno}
</#list>

Jednotný vzhled stránek

Obvyklým požadavkem na webové stránky je, aby měly jednotný vzhled, tj. hlavičku, patičku, navigační menu, proužek s reklamami atd. a měnil se jen obsah.

Include

Nejjednodušší je použít prostého vkládání jedné šablony do druhé, tj. nějaké direktivy include.

V JSP můžeme použít direktivy @include, která vloží jinou JSP stránku v době překladu:

 
<%@include file="hlavicka.jsp" %>
 
<!-- tělo stránky -->
 
<%@include file="paticka.jsp" %>

nebo JSP tag <jsp:include>, který vloží jinou JSP stránku nebo servlet v době běhu pomocí volání getRequestDispatcher(stranka).include(request,response):

 
<jsp:include page="hlavicka.jsp"/>
 
<!-- tělo stránky -->
 
<jsp:include page="paticka.jsp"/>

Ovšem v okamžiku, kdy je třeba provést složitější změnu, může být nevyhnutelné editování všech existujících šablon stránek.

Tiles

Existují i chytřejší řešení. Průkopníkem byl rámec Tiles, který byl původně samostatný, pak získal popularitu jako součást rámce Apache Struts, a dnes je opět samostatný, viz Tiles 3.0.

Je v něm možné pomocí speciálního konfiguračního souboru definovat základní nadšablonu, která obsahuje části společné všem stránkám, se značkami pro doplnění měnících se částí. Konkrétní stránky pak doplňují jen jednu její část (zvanou třeba body).

Stripes Layout Tags

Hlavní článek: Stripes Layout Tags

Ještě lepší řešení obsahuje rámec Stripes, který nepotřebuje speciální konfigurační soubor. Stačí vytvořit JSP stránku se šablonou stránky v souboru s pevným umístěním, např. /layout.jsp :

 
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %>
 
<s:layout-definition>
 <html>
 <head>
   <title><f:message key="${klicTitulkuStranky}"/></title>
   <link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/default.css"/>
 </head>
 <body>
  ... menu atd. ...
  <s:layout-component name="contents"/>
 </body>
</html>
</s:layout-definition>

a v JSP stránkách se lze na tuto šablonu odkazovat:

 
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %>
<s:layout-render name="/layout.jsp" klicTitulkuStranky="seznam">
  <s:layout-component name="contents">
      ... obsah stránky ...
  </s:layout-component>
</s:layout-render>

V podstatě značka <s:layout-render> zavolá značku <s:layout-definition>, která tiskne na výstup svoje tělo a přitom nahrazuje značky <s:layout-component> za obsah odpovídajících značek ve volající značce.

Všechny atributy tagu <s:layout-render> jsou předány šabloně jako atributy, která je může využít.

Vlastní JSP tag s fragmentovým parametrem

Obdobného efektu jako Stripes tag lze dosáhnout i pomocí vlastních tagů. Je třeba vytvořit adresář WEB-INF/tags a do něj umísťovat soubory s příponou .tag.

Pokud vytvoříme například soubor WEB-INF/tags/layout.tag s obsahem

 
<!DOCTYPE html>
<%@ tag pageEncoding="utf-8" dynamic-attributes="dynattrs" trimDirectiveWhitespaces="true" %>
<%@ attribute name="title" required="true" %>
<%@ attribute name="head" fragment="true" %>
<%@ attribute name="body" fragment="true" required="true" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
 
<html>
<head>
    <title><c:out value="${title}"/></title>
    <jsp:invoke fragment="head"/>
</head>
<body>
<h1><c:out value="${title}"/></h1>
   ... menu atd. ...
<jsp:invoke fragment="body"/>
</body>
</html>

vytvoříme tím vlastní JSP tag, který má jeden normální atribut title a dva tzv. fragmentové atributy nazvané zde head a body.

Tento tag pak můžeme volat v JSP stránkách a předávat mu atributy. Fragmentové atributy mohou obsahovat libovolný JSP kód:

 
<%@ page contentType="text/html;charset=UTF-8" pageEncoding="utf-8" %>
<%@ taglib tagdir="/WEB-INF/tags" prefix="my" %>
 
<my:layout title="Nadpis"> 
    <jsp:attribute name="head">
        ... obsah přidaný do hlavičky stránky ...
    </jsp:attribute>
    <jsp:attribute name="body">
        ... obsah přidaný do těla stránky ...
    </jsp:attribute>
</my:layout>

i18n a lokalizace

Webová aplikace by měla být schopná komunikovat se svými uživateli v jejich jazyce, tedy být internacionalizovaná. Pokud používáme JSP, zcela postačujícím řešením je JSTL knihovna Formatting, zpřístupňující standadní podporu i18n obsaženou v knihovnách JDK.

 
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
 
<f:setBundle basename="Texty" />
 
<f:message key="ted_je_prave" />: 
 
<f:formatDate value="${ted}" type="both" dateStyle="full" timeStyle="full" timeZone="${zona}" />

Nastavit ResourceBundle s texty lze buď přímo v každé stránce pomocí značky <f:setBundle>, nebo můžeme provést nastavení pro celou aplikaci pomocí inicializačního parametru v souboru WEB-INF/web.xml:

 
    <context-param>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>cz.muni.fi.pa165.ukazka.Texty</param-value>
    </context-param>

Průchod aplikací

Uživatel interaguje s aplikací klikáním na hyperlinky a odesíláním formulářů. Aplikace pak musí řešit, jak zareaguje, zda např. při odeslání formuláře má znovu zobrazit formulář s výzvou k opravě chyb, nebo už následující stránku.

Dále je obvyklý požadavek, aby data vyplněná uživatelem do formuláře ve formuláři zůstávala, aby je uživatel nemusel zadávat stále znovu. Vyplněná data je nutné i zkontrolovat, zda např. údaj na místě čísla je opravdu číslo.

Rámce řešící průchod aplikací poskytují pro tyto řešení hotové nástroje.

MVC a rámce pro tvorbu webových aplikací

Myšlenka MVC, že funkcionalita aplikace má být oddělena do Modelu, zatímco funkcionalita uživatelského rozhraní má být oddělena do Controlleru a View, je při využití rámců předpokládána, ale ne vynucována. Například při použití Apache Struts nám nikdo nezabrání psát veškerou funkcionalitu aplikace přímo do implementace akcí. Ale takový design jdoucí proti principu MVC se projeví ve špatné udržovatelnosti aplikace.

Doporučovaný postup při tvorbě aplikace tedy je:

  • vytvořte nejdříve jen Model, bez uživatelského rozhraní, a otestujte jeho funkci unit testy
  • vyberte si rámec pro tvorbu Controlleru webové aplikace (třeba Stripes nebo Spring MVC)
  • pokud lze, vyberte si technologii pro tvorbu View (třeba JSP+JSTL, nebo FreeMarker)
  • vytvořte uživatelské rozhraní

ArchWebAplikace.PNG

Rámce pro tvorbu webových aplikací

Zde si uveďme přehled rámců (frameworks, česky asi udělátek :-) ) pro tvorbu webových aplikací. lze je rozdělit do dvou velkých rodin - rámce zaměřené na zpracování HTTP požadavků a rámce zaměřené na vizuální komponenty.

Rámců na platformě Java jsou desítky, viz např. seznam na http://java-source.net/open-source/web-frameworks .

Web frameworks history.png

Rámce zaměřené na vizuální komponenty skládají stránky z komponent, reagujících na události, podobně jako se aplikace s grafickým rozhraním skládají z grafických komponent (buttony, scrollbary, selection listy, atd.) reagujících na události typu pohyb myši, kliknutí myší, zmáčknutí klávesy. Vývoj zaměřený na vizuální komponenty může být lépe podporován vývojovými prostředími a proto jednodušší, ale ztrácíme tím část kontroly na výslednými webovými stránkami aplikace.

(Why the bias against JSF?)

Naproti tomu rámce zaměřené na zpracování HTTP požadavků nám dávají totální kontrolu nad přesným vzhledem stránek a veškerým HTTP provozem, ale jsou o něco náročnější na vývoj.

V poslední době získaly popularitu rámce založené na myšlence, že konvence má přednost před konfigurací, psané v dynamicky typovaných jazycích, zejména Ruby-on-Rails (jazyk Ruby) a jeho napodobeniny,např. Grails (jazyk Groovy). V JavaSE 6 přibylo Java Scripting API, a pomocí implementace těchto jazyků nad JVM (JRuby) lze tyto rámce používat i na platformě Java, ovšem za cenu naučení se nového programovacícho jazyka.

Rámce orientované na zpracování HTTP požadavku

  • Apache Struts - klasika mezi rámci, nejpoužívanější kolem roku 2000, dnes překonané
  • Spring MVC - knihovna z rodiny Spring
  • Stripes - asi nejjednodušší webový framework v Javě

V těchto rámcích je nějak mapován HTTP request na Java kód, který zpracuje request, připraví data a zavolá šablovací systém pro vykreslení stránky.

Mapování requestu na Java kód

Stripes

Ve Stripes je HTTP request mapován na public metody vracející Resolution ve třídách implementujících rozhraní ActionBean.

Mapování je nastaveno pomocí anotace @UrlBinding, která může obsahovat speciální značku {$event} pro jméno metody, a další značky {prom} pro proměnné, respektive jejich příslušné setProm() metody. Na volání set metod jsou konvertovány i normální URL parametry.

View pro zobrazení je určeno implementací rozhraní Resolution.

 
/* ukázka Stripes */
 
@UrlBinding("/seznam/{event}/{id}")
public class Seznam implements ActionBean {
 
    private ActionBeanContext ctx;
    public ActionBeanContext getContext() { return ctx; }
    public void setContext(ActionBeanContext ctx) { this.ctx = ctx; }
 
    @DefaultHandler 
    public Resolution zobrazVsechny() {
        this.seznam = ...;
        return new ForwardResolution("/seznam.jsp");
    }
 
    public Resolution smazat() {
        smazPolozku(id);
        return new RedirectResolution(this);
    }
 
 
    private List<Polozka> seznam;
 
    public List<Polozka> getSeznam() {
        return seznam;
    }
 
    private int id;
    public void setId(int id) {
        this.id = id;
    } 
}
Spring MVC

Ve Spring MVC je HTTP request mapován na public metody tříd označených anotací @Controller.

Mapování je nastaveno pomocí anotace @RequestMapping, která může obsahovat speciální značku {arg} pro jméno argumentu metody označeného anotací @PathVariable. Případně je možné použít argument s anotací @RequestParam pro normální URL parametry.

 
/* ukázka Spring MVC */
 
@Controller
@RequestMapping("/seznam")
public class Seznam {
 
    @RequestMapping("/zobrazVsechny")
    public String zobrazVsechny(Model model) {
        List<Polozka> seznam = ...;
        model.addAttribute("seznam", seznam);
        return "seznam";
    }
 
    @RequestMapping("/smazat/{id}")
    public String smazat(@PathVariable int id) {
        smazPolozku(id);
        return "redirect:/seznam";
    }
 
}
HTTP request a response

Stále jsou dostupné objekty HttpServletRequest a HttpServletResponse, ale kvůli unit testování se doporučuje je nepoužívat přímo. Pokud to však chceme udělat, ve Stripes je získáme z ActionBeanContextu a ve SpringMVC z argumentu metody:

 
 /* Stripes */
 
 public Resolution neco() {
     String a = getContext().getRequest().getParameter("a");
     getContext().getResponse().addHeader("X-my-header","1");
     //...
 }
 
 /* Spring MVC */
 @RequestMapping("/neco")
 public String neco(HttpServletRequest req,HttpServletResponse resp) {
     String a = req.getParameter("a");
     resp.addHeader("X-my-header","1");
     //...
 }

Spring MVC navíc nabízí možnost nechat si poslat jako argumenty metody i další údaje z requestu, argument Model představuje data pro šablonu, a UriComponentsBuilder umožňuje vytváření URL v rámci aplikace:

 
 @RequestMapping("/neco")
 public String neco(HttpServletRequest req,
                    HttpServletResponse resp,
                    HttpSession ses,
                    Locale locale,
                    HttpMethod httpMethod,
                    Principal user,
                    @RequestHeader("User-agent") String userAgent,
                    @CookieValue("JSESSIONID") String sesCookie,
                    Model model,
                    UriComponentsBuilder uriBuilder) {
      //....
 }

Dále SpringMVC nabízí možnost matchování částí URL na regex, v následující ukázce kódu by vstupní URL /machine/zegox15.cerit-sc.cz bylo rozparsováno na cluster=zegox, num=15, domain=cerit-sc.cz:

 
  @RequestMapping(value = "/machine/{cluster:[a-z]+}{num:\\d+}.{domain:.*}", method = RequestMethod.GET)
    public void machine(@PathVariable String cluster, @PathVariable int num, @PathVariable String domain) {
        log.debug("machine({},{},{})", cluster,num,domain);
    }

Výběr View

Zatímco ve Stripes je View (z tria MVC) určeno implementací Resolution, ve Spring MVC musí metoda vybrat logické jméno, které pak tzv. ViewResolver převede na vybrané View.

Stripes

V Stripes jsou předpřipraveny implementace Resolution:

 
public Resolution naJSP() {
    return new ForwardResolution("/nejaka.jsp");
}
 
public Resolution pryc() {
    return new RedirectResolution(JinyActionBean.class);
}
SpringMVC

View vybírá ViewResolver, ten je nutné vždy nastavit:

 
    @Bean
    public ViewResolver viewResolver() {
        InternalResourceViewResolver viewResolver = new InternalResourceViewResolver();
        viewResolver.setPrefix("/WEB-INF/views/");
        viewResolver.setSuffix(".jsp");
        return viewResolver;
    }

View pro zobrazení je pak určeno návratovou hodnotou. Ta může být

  • String, pak
    • pokud začíná na redirect:, způsobí redirect
    • jinak je přeložena na JSP stránku podle nastavení ViewResolver, např. book/detail bude přeloženo na WEB-INF/jsp/book/detail.jsp
  • void, pak je vyhledána JSP stránka odpovídající hodnotám @RequestMapping("/a) na třídě a metodě
  • jiné typy objektů (viz Supported method return types) jsou ošetřeny speciálně (viz Resolving views with the ViewResolver interface).

Podpora JSP

Oba rámce, Stripes i Spring MVC, poskytují vlastní knihovny JSP značek pro ulehčení práce.

 
<%@ taglib prefix="stripes" uri="http://stripes.sourceforge.net/stripes.tld" %>
 
<%@taglib uri="http://www.springframework.org/tags/form" prefix="form" %>
<%@taglib uri="http://www.springframework.org/tags" prefix="spring" %>

Podpora i18n

Ve Stripes je framework implementován pomocí Filteru, kdežto ve SpringMVC pomocí Servletu. Proto Stripes mají lépe vyřešen výběr jazyka, mohou totiž vyměnit implementaci HttpServletRequest za vlastní, která mění metodu getLocale(), a proto vybraný jazyk se projeví ve všech knihovnách, které tuto metodu používají.

Naproti tomu SpringMVC vyměnit implementaci getLocale() nemůže, proto pouze nastavuje atributy pro knihovnu JSTL.

Ve Stripes lze nastavit seznam jazyků a kódování podporovaných aplikací, a Stripes vyberou pro každá HTTP request právě jeden z nich:

 
<filter>
        <display-name>Stripes Filter</display-name>
        <filter-name>StripesFilter</filter-name>
        <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
        <init-param>
            <param-name>LocalePicker.Locales</param-name>
            <param-value>cs:utf-8,en:utf-8</param-value>
        </init-param>

Způsob výběru jazyka lze změnit vlastní implementací rozhraní LocalePicker.

Ve SpringMVC lze výběr jazyka ovlivnit tak, že ve třídě označené anotací @Configuration uvedeme kód

 
    @Bean
    public LocaleResolver localeResolver() {
        return new CookieLocaleResolver();
    }

a ve třídě implementující rozhraní WebMvcConfigurerAdapter kód:

 
@Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(new LocaleChangeInterceptor());
    }

Validace vstupních dat

Oba rámce, Stripes i Spring MVC, poskytují podporu pro typovou konverzi a validaci vstupních dat zadaných uživatelem. Tedy například kontrolu, zda požadovaný parametr je skutečně číslo nebo zda je to řetězec o určité maximální délce.

Stripes poskytují jednoduchou validaci na prezentační vrstvě pomocí anotací, např.

 
    @ValidateNestedProperties(value = {
            @Validate(on = {"save"}, field = "surName", mask = "\\p{javaUpperCase}.*", required = true),
            @Validate(on = {"save"}, field = "givenName", mask = "\\p{javaUpperCase}.*", required = true),
            @Validate(on = {"save"}, field = "mail", converter = EmailTypeConverter.class, required = true),
    })
    private User user;

Spring MVC používá systém validace na business vrstvě podle JSR-303 Java Bean validation,jehož referenční implementace je Hibernate Validator.

Lze tak anotacemi označit přímo ve třídě s daty, jaká omezení musí data splnit. Např.

 
import javax.validation.constraints.*;
 
public class User {
    @NotNull
    @Pattern(regexp = "\\p{javaUpperCase}.*")
    @Size(min = 1, max = 30)
    private String surName;
 

Standardní anotace jsou v balíku javax.validation.constraints. Další poskytuje Hibernate Validator v balíku org.hibernate.validator.constraints.

Lze definovat i vlastní anotace a k nim příslušné validátory. Lokalizovaná chybová hlášení jsou pak umístěna v souboru ValidationMessages.properties, který musí být do stupný na CLASSPATH.

Výhodou přístupu SpringMVC je, že data lze validovat bez ohledu na to, jakou cestou se do systému dostala, kdežto Stripes je kontroluje jen na presentační vrstvě při zpracování dat z webového formuláře.


Flash atributy

Stripes i SpringMVC poskytují podporu pro předávání atributů do následujícího requestu, tzv. flash atributy.

Stripes:

 
    public Resolution redir() {
        FlashScope.getCurrent(getContext().getRequest(), true).put("myflashattr","some value");
        return new RedirectResolution(NecoActionBean.class).addParameter("id", 123).addParameter("a", 5);
    }

SpringMVC:

 
   @RequestMapping("/redir")
   public String redir(RedirectAttributes redirectAttributes,UriComponentsBuilder uriBuilder) {
       redirectAttributes.addFlashAttribute("myflashattr","some value");
       String uri=  uriBuilder.path("/neco/{id}").queryParam("a", 5).buildAndExpand(123).encode().toUriString();
       return "redirect:"+uri;
   }

Zobrazování zpráv

Stripes

Stripes rozlišuje chybové zprávy a obecné zprávy. Chybové zprávy pocházejí ze tří zdrojů:

  • chyby automatické konverze typů (např. z řetězce na číslo)
  • chyby validace jednotlivých položek formuláře popsané pomocí anotací @ValidateNestedProperties a @Validate
  • chyby validace složitějších vztahů mezi položkami v metodě označené anotací @ValidationMethod
 
  //chyba jednotlivé položky formuláře
  @Validate(on = {"save"}, required = true, mask = "[a-z][a-z0-9]+")
  private String uid;
 
  //metoda kontrolujíc složitější vztahy
  @ValidationMethod(on = "save")
  public void myValidations(ValidationErrors errors) {
      if(book.isPaperback() && book.getPrice()>100) {
          errors.add("surname", new LocalizableError("expensive.paperback"),book.getPrice());
      }
  }
 
  public Resolution neco() {
      //...
 
      //obecné zprávy jsou automaticky ve flash scope
      getContext().getMessages().add(new SimpleMessage("Today is a holiday !"));
 
      //...
  }

a jejich výpis v JSP:

 
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %>
<%-- chybové zprávy ---@>
<s:errors/>
<%-- obecné zprávy ---@>
<s:messages />
SpringMVC

Chybové zprávy SpringMVC bere ze tří zdrojů:

  • chyby převodu typů (např. ze řetězce na číslo)
  • chyby validace pomocí anotací z JSR-303 Java Bean Validation a příslušné zprávy z ValidationMessages.properties
  • vlastní SpringMVC validátor
 
public class BookSpringValidator implements Validator {
 
    @Override
    public boolean supports(Class<?> clazz) {
        return Book.class.isAssignableFrom(clazz);
    }
 
    @Override
    public void validate(Object target, Errors errors) {
        Book book = (Book) target;
        if(book.isPaperback() && book.getPrice()>100) {
            errors.rejectValue("price","book.price.expensive.paperback");
        }
    }
}

a jejich zobrazení podporuje JSP tagem <form:errors>:

 
 <table>
  ...
  <td><form:input path="price" /></td>
  <td><form:errors path="price" cssClass="error" /></td>
  ...
 </table>

SpringMVC nemá explicitní podporu obecných zpráv, ale lze je předávat jako ostatní objekty přes flash atributy:

 
 String message = messageSource.getMessage("msg_with_params", new Object[]{"A", 5}, locale);
 redirectAttributes.addFlashAttribute("message",message);

a pak vypisovat v JSP

 
 
 <c:if test="${not empty message}">
    <div class="warning"><c:out value="${message}"/></div>
 </c:if>
 

Rámce orientované na vizuální komponenty

Apache Wicket

Apache Wicket je podobný Tapestry.

Tapestry

Populární rámec zaměřený na vizuální komponenty je Tapestry, a je mu věnováno samostatné heslo. Za zmínku stojí, že Tapestry získalo v roce 2006 cenu Duke's Choice award za inovaci.

JSF

Java Server Faces je technologie prosazovaná firmou SUN, a v poslední verzi je integrovaná přímo do JavaEE a do specifikací EL jazyka. Je jí věnováno heslo JSF.

Portlety

Jedná se o filozoficky jiný přístup k vytváření aplikací, kdy celý webový server je nazýván portál a je sestaven z nezávislých aplikací generujících části stránek. Je mu věnováno samostatné heslo Java Portlets.

Odkazy