Tvorba aplikace v Tapestry

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

Vytvoření aplikace

Nejjednodušší to je asi přes Maven 2, nejdřív vytvořit aplikaci:

mvn archetype:create -DgroupId=cz.muni.fi.moje -DartifactId=tapestryapp -DarchetypeArtifactId=maven-archetype-webapp

a pak přidat do pom.xml:

 
    <dependency>
      <groupId>tapestry</groupId>
      <artifactId>tapestry</artifactId>
      <version>4.0.2</version>
      <scope>provide</scope>
    </dependency>
    <dependency>
      <groupId>tapestry</groupId>
      <artifactId>tapestry-annotations</artifactId>
      <version>4.0.2</version>
      <scope>provide</scope>
    </dependency>

Nastavení aplikace

Soubor WEB-INF/web.xml musí obsahovat mapování na servlet frameworku:

 
<?xml version="1.0" encoding="iso-8859-2"?>
<web-app xmlns="http://java.sun.com/xml/ns/j2ee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"
    version="2.4">     
    <display-name>Moje Tapestry Web Aplikace</display-name>
    <servlet>
        <servlet-name>app</servlet-name>
        <servlet-class>org.apache.tapestry.ApplicationServlet</servlet-class>
        <load-on-startup>1</load-on-startup>
    </servlet>
    <filter>
        <filter-name>redirect</filter-name>
        <filter-class>org.apache.tapestry.RedirectFilter</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>redirect</filter-name>
        <url-pattern>/</url-pattern>
    </filter-mapping>
    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>/app</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>*.html</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>*.direct</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>*.sdirect</url-pattern>
    </servlet-mapping>
    <servlet-mapping>
        <servlet-name>app</servlet-name>
        <url-pattern>*.svc</url-pattern>
    </servlet-mapping>
</web-app>

Je třeba vytvořit soubor WEB-INF/app.application s nastavením, v jakých packages se hledají třídy představující ovladače stránek a komponent.

 
<?xml version="1.0"?>
<!DOCTYPE application PUBLIC
        "-//Apache Software Foundation//Tapestry Specification 4.0//EN"
        "http://jakarta.apache.org/tapestry/dtd/Tapestry_4_0.dtd">
<application>
    <meta key="org.apache.tapestry.page-class-packages" value="cz.moje.app1.pages"/>
    <meta key="org.apache.tapestry.component-class-packages" value="cz.moje.app1.components"/>
    <meta key="org.apache.tapestry.template-encoding" value="iso-8859-2"/>
</application>

Pokud chceme pěkně vypadající URL, je třeba ješte soubor WEB-INF/hivemodule.xml:

 
<?xml version="1.0"?>
<module id="tapestryapp" version="1.0.0">
 
    <contribution configuration-id="tapestry.url.ServiceEncoders">
        <page-service-encoder id="page" extension="html" service="page"/>
    </contribution>
    <contribution configuration-id="tapestry.url.ServiceEncoders">
        <direct-service-encoder id="direct" stateless-extension="direct" stateful-extension="sdirect"/>
    </contribution>
    <contribution configuration-id="tapestry.url.ServiceEncoders">
        <extension-encoder id="extension" extension="svc" after="*"/>
    </contribution>
 
</module>

Lokalizované ResourceBundle texty mohou být buď ve speciálních souborech pro každou stránku a komponentu zvlášť, nebo v souborech pro celou aplikaci, které se jmenují WEB-INF/app_locale.properties

To je kompletní konfigurace. Šablony stránek se hledají v hlavním adresáři webaplikace, šablony komponent v adresáři WEB-INF.

Vytvoření komponenty

Nejlépe vytvořením třídy v package určeném pro ovladače komponent (viz konfigurace aplikace) s anotací @ComponentClass, tím odpadá vytvoření konfiguračního souboru. Veškerá konfigurace se dá dělat pomocí anotací.

Šablona pro komponentu se musí nacházet ve WEB-INF a musí se jmenovat stejně jako třída.

Komponenta pro jednotný vzhled stránek

Vytvořím komponentu @Okraje, kterou všechny stránky použijí jako hlavní komponentu, a v její šabloně specifikuji společný vzhled.

Vytvořím ovladač, který bere atribut klic-titulku s obsahem klíč pro lokalizovaný nadpis, a odkaz na CSS stylesheet /styl.css

 
package cz.moje.app1.components;
 
import org.apache.tapestry.BaseComponent;
import org.apache.tapestry.IAsset;
import org.apache.tapestry.annotations.ComponentClass;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.annotations.Asset;
 
@ComponentClass
public abstract class Okraje extends BaseComponent {
 
    @Parameter(name = "klic-titulku")
    public abstract String getKlicTitulku();
 
    @Asset("/styl.css")
    public abstract IAsset getStylesheet();
 
    public String getTitulek() {
        if (isParameterBound("klic-titulku")) {
            String klicTitulku = getKlicTitulku();
            String msg = getMessages().getMessage(klicTitulku);
            return msg;
        } else {
            return "--no title--";
        }
    }
}

K tomu vytvořím šablonu v souboru WEB-INF/Okraje.html, do ní zadám společný vzhled. V místě komponenty @RenderBody se vloží tělo (obsah) značky volající komponentu @Okraje.

 
<html jwcid="@Shell" title="ognl:titulek" stylesheet="asset:stylesheet">
 <body>
  <h1><span jwcid="@Insert" value="ognl:titulek">Nadpis</span></h1>
  
  ... navigace, logo atd. ...
 
  <span jwcid="@RenderBody">Page content goes here.</span>
 </body>
</html>

Ve stránkách pak použiju @Okraje jako hlavní komponentu:

 
<body jwcid="@Okraje" klic-titulku="titulek_tehle_stranky">
 ...
</body>


Spolupráce s JSP

Lze vytvořit komponentu, která vykresluje JSP stránky, takto:

 
package cz.moje.app1.components;
 
import org.apache.log4j.Logger;
import org.apache.tapestry.AbstractComponent;
import org.apache.tapestry.IMarkupWriter;
import org.apache.tapestry.IRequestCycle;
import org.apache.tapestry.annotations.ComponentClass;
import org.apache.tapestry.annotations.InjectObject;
import org.apache.tapestry.annotations.Parameter;
import org.apache.tapestry.services.RequestGlobals;
 
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
 
/**
 * Komponenta pro vykresleni JSP stranky. Most mezi Tapestry a JSP.
 *
 * @author Martin Kuba makub@ics.muni.cz
 * @version $Id:$
 */
@ComponentClass(allowBody = false, allowInformalParameters = false, reservedParameters = "include")
public abstract class JspKousek extends AbstractComponent {
    static Logger log = Logger.getLogger(JspKousek.class);
 
    /**
     * Atribut "include" pri volani komponenty. Injektovan ramcem.
     *
     * @return obsah atributu
     */
    @Parameter(name = "include", required = true)
    public abstract String getInclude();
 
    /**
     * HiveMind objekt drzici request a response. Injektovan ramcem.
     *
     * @return globals
     */
    @InjectObject(value = "service:tapestry.globals.RequestGlobals")
    public abstract RequestGlobals getRequestGlobals();
 
    protected void renderComponent(IMarkupWriter writer, IRequestCycle cycle) {
        log.debug("renderComponent()");
        RequestGlobals globals = getRequestGlobals();
        HttpServletRequest request = globals.getRequest();
        HttpServletResponse response = globals.getResponse();
        try {
            request.getRequestDispatcher(getInclude()).include(request, response);
        } catch (ServletException e) {
            log.error(e.getMessage(), e);
        } catch (IOException e) {
            log.error(e.getMessage(), e);
        }
    }
}

Ve stránkách pak lze tuto komponentu volat pomocí:

 
 <span jwcid="@JspKousek" include="/snoop.jsp" />