Cvičení Stripes

Z FI WIKI
Přejít na: navigace, hledání
Tato stránka obsahuje neaktuální informace a měla by být aktualizována. Berte ji proto prosím s rezervou!


Tato stránka byla nahrazena lepším cvičením Stripes a Spring ve webových aplikacích.







Příprava prostředí

Vytvořte si novou webovou aplikaci jménem WebCviceni5, zvolte server Apache TomCat 6.0.16 a verzi JavaEE 5.


Přidejte knihovny rámce Stripes. Klikněte pravým tlačítkem ve stromu projektu na Libraries - Add Jar/Folder. Zvolte všechny soubory v adresáři

/packages/run/idea-7.0/stripes-1.5/lib

tj.

commons-logging.jar
cos.jar
log4j-1.2.13.jar
stripes.jar

nebo si stáhněte instalaci Stripes z http://www.stripesframework.org/display/stripes/Download

Přidejte knihovny JSTL 1.1. Klikněte pravým tlačítkem na Libraries - Add Library, vyberte položku JSTL 1.1 a přidejte ji.

Zkuste aplikaci spustit, ať vidíte, že jede.

Zajistíme jednotný vzhled stránek

Teď zjistíme, jak se zajištuje jednotný vzhled stránek aplikace.

Vytvořte JSP stránku rozvrh.jsp (klikněte pravým tlačítkem na Web Pages, vyberte New - JSP, zadejte jméno rozvrh. Smažte její obsah a nahraďte ho tímto:

 
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
 
<s:layout-definition>
<html>
<head>
  <title><c:out value="${nadpis}" /></title>
  <style type="text/css">
      input.error { background-color: yellow; }
      body { font-family: Helvetica, sans-serif; background-color: azure;}
      h1 { text-align: center; text-decoration: underline; text-shadow: aquamarine; text-transform: capitalize; }
      /*  http://www.alistapart.com/articles/taminglists/ */
     #navigace { width: 120px; border-right: 1px solid #000; padding: 0 0 1em 0; margin-bottom: 1em;
               background-color: #90bade;  color: #333;  }
     #navigace ul { list-style: none;  margin: 0;  padding: 0;  border: none; }
     #navigace li { border-bottom: 1px solid #90bade;  margin: 0; }
     #navigace li a { display: block; padding: 5px 5px 5px 0.5em; border-left: 10px solid #1958b7;
         border-right: 10px solid #508fc4; background-color: #2175bc;  color: #fff; text-decoration: none; width: 100%; }
      html>body #navigace li a { width: auto; }
      #navigace li a:hover { border-left: 10px solid #1c64d1;  border-right: 10px solid #5ba3e0;
          background-color: #2586d7;  color: #fff; }
      /*  http://realworldstyle.com/2col.html */
      #navigace { width: 120px; float: left; margin-left: -1px; }
      #obsah { padding: 10px;  margin-left: 130px; }
  </style>
    <s:layout-component name="hlavicka"/>
</head>
<body>
   <h1><c:out value="${nadpis}" /></h1>
   <div id="navigace">
     <ul>
       <li><s:link href="/index.jsp">Domů</s:link></li>
       <li><s:link href="/praha.jsp">do Prahy</s:link></li>
       <li><s:link href="/podoli.jsp">do Podolí</s:link></li>
       <li><s:link href="/lekarna.jsp">do lékárny</s:link></li>  
     </ul>
   </div>
   <div id="obsah">
       
       <s:layout-component name="telo"/>
       
    </div>
</body>
</html>
 
</s:layout-definition>

Tím jsme vytvořili šablonu rozvržení všech stránek, s nadpisem, navigačním menu a místem pro doplnění obsahu jednotlivých stránek.

Nyní změňte obsah stránky index.jsp na následující:

 
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %>
 
<s:layout-render name="/rozvrh.jsp" nadpis="Hlavní stránka">
    <s:layout-component name="telo">
 
        Tady zatím nic není. Ale je to úvodní stránka aplikace.
 
    </s:layout-component>
</s:layout-render>

Je vidět, že stránka index.jsp se odkazuje na stránku rozvrh.jsp, a její oblast (tag s:layout-component) jménem telo nahrazuje vlastním obsahem. Zároveň definuje atribut nadpis, který je v rozvrh.jsp použit pro titul stránky a nadpis. Spusťte aplikaci.

samostatné cvičení

Vytvořte několik dalších JSP stránek využívajících stejný vzhled a přidejte je do navigačního menu.

Úloha pro pokročilé: změňte index.jsp tak, aby se přidal další obsah hlavičky stránky, ne do těla. Například další definici CSS nebo JavaScript.

Použití Stripes

Konfigurace

Nejdřív je nutné zkopírovat soubor s lokalizovanými chybovými hlášeními Stripes. Na příkazovém řádku se přepněte do adresáře s třídami a zkopírujte ho, tj.

cd ~/NetBeansProjects/WebCviceni5/src/java
cp /packages/run/idea-7.0/stripes-1.5/lib/StripesResources.properties .

V NetBeans se soubor objeví v Source packages - default package. Přidejte mu českou a anglickou variantu stejně jako v minulém cvičení (Add Locale - Language Code).


Otevřete soubor web.xml, a změňte ho na:

 
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
         version="2.5">
 
    <context-param>
        <description>JSTL tagy pouziji lokalizovane texty ze stejneho zdroje jako Stripes tagy</description>
        <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
        <param-value>StripesResources</param-value>
    </context-param>
 
    <filter>
        <description>hlavni misto konfigurace Stripes</description>
        <display-name>Stripes Filter</display-name>
        <filter-name>StripesFilter</filter-name>
        <filter-class>net.sourceforge.stripes.controller.StripesFilter</filter-class>
        <init-param>
            <description>kde Stripes hleda ActionBeans</description>
            <param-name>ActionResolver.Packages</param-name>
            <param-value>cz.muni.fi.pa165.cv5</param-value>
        </init-param>
        <init-param>
            <description>kde Stripes hleda ruzna rozsireni</description>
            <param-name>Extension.Packages</param-name>
            <param-value>cz.muni.fi.pa165.cv5</param-value>
        </init-param>
        <init-param>
            <description>jaka locale aplikace podporuje</description>
            <param-name>LocalePicker.Locales</param-name>
            <param-value>cs:utf-8,en:utf-8</param-value>
        </init-param>
    </filter>
 
    <filter-mapping>
        <filter-name>StripesFilter</filter-name>
        <url-pattern>*.jsp</url-pattern>
        <dispatcher>REQUEST</dispatcher>
    </filter-mapping>
    
    <filter>
        <description>dynamicky mapuje URL na ActionBeans</description>
        <display-name>Stripes Dynamic Mapping Filter</display-name>
        <filter-name>DynamicMappingFilter</filter-name>
        <filter-class>net.sourceforge.stripes.controller.DynamicMappingFilter</filter-class>
    </filter>
 
    <filter-mapping>
        <filter-name>DynamicMappingFilter</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>
    
</web-app>


Ještě je vhodné vytvořit soubor log4j.xml s konfigurací logování, abychom viděli, co se děje. Pravým tlačítkem myši na default package dejte New - XML - XML document

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j='http://jakarta.apache.org/log4j/'>
    <appender name="STDOUT" class="org.apache.log4j.ConsoleAppender">
        <layout class="org.apache.log4j.PatternLayout">
            <param name="ConversionPattern" value="%d [%t] %-5p %c - %m%n"/>
        </layout>
    </appender>
    <category name="org.apache.log4j.xml">
        <priority value="info"/>
    </category>
    <category name="net.sourceforge.stripes">
            <priority value="info"/>
    </category>
    <category name="cz.muni.fi.pa165.cv5">
            <priority value="debug"/>
    </category>
    <root>
        <priority value="info"/>
        <appender-ref ref="STDOUT"/>
    </root>
</log4j:configuration>

Práce s daty

V reálné aplikaci budte pracovat s databází, ale abychom tento příklad nekomplikovali, vystačíme si s daty v paměti.

Nejdříve vytvoříme nějakou třídu představující data, normální JavaBean. Nezapomeňte vytvořit balík cz.muni.fi.pa165.cv5, do kterého budeme třídy umísťovat. Abychom simulovali databázi, instance budou mít unikátní id.

 
package cz.muni.fi.pa165.cv5;
 
public class Zaznam {
    
    public enum Barva { ZELENA, MODRA, CERVENA }
 
    private static long counter;
 
    private long id = counter++;
    private String jmeno;
    private int pocet;
    private boolean vybran;
    private Barva barva;
 
    public long getId() { return id; }
    public void setId(long id) { this.id = id; }
    public String getJmeno() { return jmeno;  }
    public void setJmeno(String jmeno) { this.jmeno = jmeno; }
    public int getPocet() { return pocet; }
    public void setPocet(int pocet) { this.pocet = pocet; }
    public boolean isVybran() { return vybran; }
    public void setVybran(boolean vybran) { this.vybran = vybran; }
    public Barva getBarva() { return barva; }
    public void setBarva(Barva barva) { this.barva = barva;  }
    
}

Přístup k datům je vhodné oddělit do speciální třídy nazývané kontext. Pro jednoduchost bude používat List uložený v HTTP session. Třída dědí z třídy ActionBeanContext, Stripes si ji najdou samy při startu aplikace, pokud je v nějakém package nstaveném v parametru Extension.Packages ve web.xml:

 
package cz.muni.fi.pa165.cv5;
 
import net.sourceforge.stripes.action.ActionBeanContext;
import java.util.ArrayList;
import java.util.List;
 
public class MujActionBeanContext extends ActionBeanContext {
    @SuppressWarnings({"unchecked"})
    public List<Zaznam> getZaznamy() {
        List<Zaznam> zaz = (List<Zaznam>) getRequest().getSession().getAttribute("zaz");
        if (zaz == null) {
            getRequest().getSession().setAttribute("zaz", new ArrayList<Zaznam>());
        }
        return zaz;
    }
 
    public Zaznam getZaznamById(long id) {
        for (Zaznam z : getZaznamy()) {
            if (z.getId() == id)
                return z;
        }
        return null;
    }
 
    public void smazZaznam(long id) {
        ListIterator<Zaznam> listIterator = getZaznamy().listIterator();
        while (listIterator.hasNext()) {
            if (listIterator.next().getId() == id) {
                listIterator.remove();
                break;
            }
        }
    }
 
    public void ulozZaznam(Zaznam z) {
        //normalne by se tady ulozil zaznam do databaze, ale
        //protoze existuje pouze v pameti, neni to potreba
    }
}

Při přechodu k reálné databázi stačí měnit tuto třídu.

Přijímání a kontrola dat z formuláře

Vytvoříme třídu, která implementuje ActionBean, tedy ve Stripes může obsluhovat požadavky od prohlížeče:

 
package cz.muni.fi.pa165.cv5;
 
import net.sourceforge.stripes.action.*;
import net.sourceforge.stripes.controller.LifecycleStage;
import net.sourceforge.stripes.validation.Validate;
import net.sourceforge.stripes.validation.ValidateNestedProperties;
import org.apache.log4j.Logger;
 
import java.util.List;
import java.util.ListIterator;
 
@UrlBinding("/zaznam/{$event}/{zaznam.id}")
public class ZaznamActionBean implements ActionBean {
    static Logger log = Logger.getLogger(ZaznamActionBean.class);
 
    private MujActionBeanContext ctx;
    public void setContext(ActionBeanContext ctx) { this.ctx = (MujActionBeanContext) ctx; }
    public MujActionBeanContext getContext() { return ctx; }
 
    public List<Zaznam> getZaznamy() {
        return ctx.getZaznamy();
    }
 
    @ValidateNestedProperties(value = {
                @Validate(on = {"pridej", "uloz"}, field = "jmeno", required = true),
                @Validate(on = {"pridej", "uloz"}, field = "pocet", required = true, minvalue = 1)
            }
    )
    private Zaznam zaznam;
    public Zaznam getZaznam() { return zaznam;  }
    public void setZaznam(Zaznam zaznam) { this.zaznam = zaznam; }
 
    @DefaultHandler
    public Resolution zobraz() {
        return new ForwardResolution("/index.jsp");
    }
 
    public Resolution pridej() {
        log.debug("pridej()");
        getZaznamy().add(zaznam);
        return new RedirectResolution(this.getClass(), "zobraz");
    }
}

Tato třída je mapována na URL začínající /zaznam, při vyvolání události pridej zkontroluje, že data v instanci Zaznamu splňují podmínky, a bude vyvolána metoda odpovídající jménu události.

A změníme index.jsp tak, aby vypisovala seznam Zaznamů a obsahovala formulář pro zadání nového.

 
<%@ page pageEncoding="utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %>
 
<s:layout-render name="/rozvrh.jsp" nadpis="Hlavní stránka">
    <s:layout-component name="telo">
 
        <s:useActionBean var="ab" beanclass="cz.muni.fi.pa165.cv5.ZaznamActionBean"/>
 
        <table border="1">
        <c:forEach var="z" items="${ab.zaznamy}">
            <tr>
                <td><c:out value="${z.jmeno}" /></td>
                <td><c:out value="${z.pocet}" /></td>
                <td><c:out value="${z.vybran?'ano':'ne'}" /></td>
                <td><c:out value="${z.barva}" /></td>
            </tr>
            </c:forEach>
        </table>
 
        <s:form beanclass="cz.muni.fi.pa165.cv5.ZaznamActionBean">
            <fieldset><legend>Nový záznam</legend>
            <s:errors/>
            <table>
                <tr>
                    <td><label for="z1">jméno:</label></td>
                    <td><s:text id="z1" name="zaznam.jmeno" /></td>
                </tr>
                <tr>
                    <td><label for="z2">počet:</label></td>
                    <td><s:text id="z2" name="zaznam.pocet" /></td>
                </tr>
                <tr>
                    <td><label for="z3">vybrán:</label></td>
                    <td><s:checkbox id="z3" name="zaznam.vybran" /></td>
                </tr>
                <tr>
                    <td><label for="z4">barva:</label></td>
                    <td><s:select id="z4" name="zaznam.barva" >
                        <s:options-enumeration enum="cz.muni.fi.pa165.cv5.Zaznam.Barva"/>
                    </s:select></td>
                </tr>
            </table>
            <s:submit name="pridej">Přidej</s:submit>
            </fieldset>
       </s:form>
 
    </s:layout-component>
</s:layout-render>

Spusťte aplikaci a zkuste postupně odeslat formulář s hodnotami, bez hodnot, s textem místo čísla.

Lokalizace do češtiny

Je vidět, že máme tři problémy:

  • chybová hlášení nejsou lokalizovaná do češtiny
  • názvy polí neodpovídají popisům ve stránce
  • názvy barev jsou bez diakritiky, odpovídají identifikátorům enumu

Je proto nutné v souboru StripesResources_cs.properties

  • přeložit chybová hlášení, minimálně ta použitá v našem případě
  • lokalizovat názvy polí formuláře, ve kterých může dojít k chybě
  • definovat lokalizované názvy barev
 #chybova hlaseni
 stripes.errors.header=<div style="color:#b72222; font-weight: bold">Prosím opravte následující chyby:</div><ol>
 validation.required.valueNotPresent=pole {0} musí být vyplněno
 converter.number.invalidNumber=Hodnota "{1}" zadaná do pole {0} musí být číslo
 validation.minvalue.valueBelowMinimum=Minimální hodnota pro {0} musí být {2}

 #nazvy poli
 zaznam.jmeno=jméno
 zaznam.pocet=počet
 zaznam.vybran=vybrán
 zaznam.barva=barva

 #nazvy polozek enumu
 Barva.MODRA=modrá
 Barva.ZELENA=zelená
 Barva.CERVENA=červená
 

Zkuste si spustit aplikaci.

samostatné cvičení

Proveďte lokalizaci do angličtiny a důslednou internacionalizaci. Statické texty nahraďte JSP tagy

 
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
...
 <f:message key="klic.textu" />

Obsluha dalších událostí

Obsluhu dalších událostí můžeme do action beanu snadno dodat přidáním dalších metod, které mají následující tvar:

 
 
public Resolution nazevUdalosti() {
    //obsluha udalosti
    ...
    
        //vraceni ForwardResolution pro zobrazení JSPO stránky
        return new ForwardResolution("/stranka.jsp");
    } else {
        //vraceni RedirectResolution pro redirect prohlizece na prislusne URL
        return new RedirectResoution(NejakyActionBean.class,"nazevNejakeUdalosti");
    }
}

událost pak vyvoláme odkazem v JSP s případnými parametry. Odkaz lze specifikovat pomocí URL nebo pomocí třídy s ActionBeanem:

 
  <s:link href="/NazevActionBeanu.action" event="nazevUdalosti"> 
     <s:param name="p1" value="${p1}" /> 
     <s:param name="p2" value="${p2}" /> 
     text odkazu 
  </s:link>

případně submitem ve formuláři se stejným jménem:

 
  <s:submit name="nazevUdalosti"> text tlacitka </s:submit>

Parametry a obsah polí ve formuláři se Stripes pokusí nastavit do stejnojmených properties na action beanu, tj. parametr "p1" se pokusí nastavit např. do:

 
 int p1;
 public int getP1() { return p1; } 
 public void setP1(int i) { p1 = i; }

Mazání

Do index.jsp do tabulky se záznamy je třeba přidat odkaz, který specifikuje volanou metodu a parametr:

 
<s:link beanclass="cz.muni.fi.pa165.cv5.ZaznamActionBean" event="smaz"><s:param name="zaznam.id"value="${z.id}"/>smazat</s:link>

nebo

 
<s:link href="/zaznam" event="smaz"><s:param name="zaznam.id"value="${z.id}"/>smazat1</s:link>

první varianta se specifikací třídy má tu výhodu, že při úpravě anotace @UrlBinding se samy upraví všechny odkazy, druhá varianta je zase kratší.

Do ActionBeanu je třeba přidat metodu odpovídající názvem obsahu atributu event v odkazu:

 
    public Resolution smaz() {
        ctx.smazZaznam(zaznam.getId());
        return new RedirectResolution(this.getClass(), "zobraz");
    }

Kód využívá toho, že když Stripes obdrží od prohlížeče parametr s tečkami v názvu, pokusí se ho převést na volání metod. V tomto případě tedy parametr zaznam.id způsobí zavolání getZaznam(), které vrátí null (je to nový request od prohlížeče a tudíž nová instance ActionBeanu), takže Stripes vytvoří instanci třídy Zaznam, nastaví ji do proměnné zaznam a pak zavolá getZaznam().setId(id) kde id bude číslo vzniklé převodem hodnoty parametru.

Editování

Smazání je jednoduchá operace. pro editování je třeba data ve formuláři předvyplnit, a při uložení změny promítnout. Je třeba provést následující změny. V index.jsp přidat odkaz:

 
<s:link beanclass="cz.muni.fi.pa165.cv5.ZaznamActionBean" event="edit"><s:param name="zaznam.id" value="${z.id}"/> edit </s:link>

Vytvořit novou JSP stánku pro editaci edit.jsp:

 
<%@ page contentType="text/html; charset=utf-8" pageEncoding="utf-8" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="f" uri="http://java.sun.com/jsp/jstl/fmt" %>
<%@ taglib prefix="s" uri="http://stripes.sourceforge.net/stripes.tld" %>
 
<f:message key="edit.nadpis" var="nadpis" />
    <s:layout-render name="/rozvrh.jsp" nadpis="${nadpis}">
    <s:layout-component name="telo">
        <s:useActionBean var="ab" beanclass="cz.muni.fi.pa165.cv5.ZaznamActionBean"/>
 
        <s:form beanclass="cz.muni.fi.pa165.cv5.ZaznamActionBean">
            <s:hidden name="zaznam.id" />
            <fieldset><legend><f:message key="upravit.zaznam" /></legend>
            <s:errors />
            <table>
                <tr>
                    <td><label for="z1"><f:message key="zaznam.jmeno" />:</label></td>
                    <td><s:text id="z1" name="zaznam.jmeno" /></td>
                </tr>
                <tr>
                    <td><label for="z2"><f:message key="zaznam.pocet" />:</label></td>
                    <td><s:text id="z2" name="zaznam.pocet" /></td>
                </tr>
                <tr>
                    <td><label for="z3"><f:message key="zaznam.vybran" />:</label></td>
                    <td><s:checkbox id="z3" name="zaznam.vybran" /></td>
                </tr>
                <tr>
                    <td><label for="z4"><f:message key="zaznam.barva" />:</label></td>
                    <td><s:select id="z4" name="zaznam.barva" >
                        <s:options-enumeration enum="cz.muni.fi.pa165.cv5.Zaznam.Barva"/>
                    </s:select></td>
                </tr>
            </table>
            <s:submit name="uloz"><f:message key="uloz" /></s:submit>
            </fieldset>
       </s:form>
    </s:layout-component>
</s:layout-render>

s patřičnými texty v StripesResources_cs.properties

edit.nadpis=Změna záznamu
upravit.zaznam=Změnit záznam
uloz=Ulož


a v actionbeanu je třeba přidat metodu s anotací @Before, která přednastaví záznam podle specifikovaného id do proměnné tak, aby getZaznam() vracelo vybraný záznam. Při odeslání formuláře se změněnými hodnotami se tedy nejdříve natáhne správný záznam do proměnné zaznam, a pak Stripes mapováním obsahu formuláře do něj nastaví nové hodnoty. V metodě uloz() se pak změněné hodnoty musí uložit do databáze.

Všimněte si, že po volání uloz() se provede redirect, protože šlo o odeslání obsahu formuláře a tato akce se nesmí provést podruhé, když uživatel klikne na reload.

 
    @Before(stages = LifecycleStage.BindingAndValidation,on={"edit", "uloz"})
    public void natazeni() {
        String ids = ctx.getRequest().getParameter("zaznam.id");
        if (ids == null) return;
        if(log.isDebugEnabled()) log.debug("natahuji zaznam "+ids);
        setZaznam(ctx.getZaznamById(Integer.parseInt(ids)));
    }
 
    public Resolution edit() {
        return new ForwardResolution("/edit.jsp");
    }
 
    public Resolution uloz() {
        if(log.isDebugEnabled()) log.debug("ukladam zmeny v zaznamu "+zaznam.getId());
        ctx.ulozZaznam(zaznam);
        return new RedirectResolution(this.getClass(),"zobraz");
    }

Práce s databází

V reálné aplikaci je třeba nějak přistupovat k databázi. ActionBeans jsou objekty existující jen krátce, proto je vhodný postup ten, že si vytvoříte servlet, kterému nastavíte ve web.xml parametr load-on-startup, a do jeho metody init() umístíte vytvoření nějaké třídy pro práci s databází, a tu vložíte do kontextu aplikace. U TomCatu 6.0 můžete využít toho, že odpovídá specifikaci JavaEE5 a proto umí injektovat do servletů zdroje, konkrétně pool databázových spojení, viz Konfigurace webové aplikace.

 
import javax.sql.DataSource;
import javax.annotation.Resource;
 
public class Starter extends HttpServlet {
 
    @Resource(name = "jdbc/mojedatabaze")
    private DataSource pool;
 
    @Override
    public void init() throws ServletException {
        getServletContext().setAttribute("model", new MujModel(pool));
    }
  
}

a web.xml:

 
 <servlet>
   <servlet-name>Starter</servlet-name>
   <servlet-class>cz.muni.fi.pa165.cv5.Starter</servlet-class>
   <load-on-startup>1</load-on-startup>
 </servlet>
 <!-- spojeni na databazi -->
 <resource-ref>
     <res-ref-name>jdbc/mojedatabaze</res-ref-name>
     <res-type>javax.sql.DataSource</res-type>
     <res-auth>Container</res-auth>
 </resource-ref>

Je výhodné si v ActionBeanContextu udělat speciální metodu pro získání modelu, tj.

 
public class MujActionBeanContext extends ActionBeanContext {
   public MujModel getModel() {
        return (MujModel) getServletContext().getAttribute("model");
   }
}

V action beanech se pak k němu dostanete jednoduše přes kontext aplikace:

 
    public Resolution uloz() {
        ctx.getModel().uloz(getZaznam());
        return new RedirectResolution("/index.jsp");
    }

Při tomto přístupu je snadné i unit testování aplikace, protože stačí vytvořit jinou implementaci MujActionBeanContext.