04 Tapestry5 In Action Pratica

download 04   Tapestry5 In Action   Pratica

If you can't read please download the document

Transcript of 04 Tapestry5 In Action Pratica

PraticaTapestry5 in action

Indice

Preparare l'ambiente

Creiamo la nostra prima page

Creiamo un componente per gestire il layout

Creiamo un componente per il login/logout

La pagina di iscrizione utente

L'upload di un file

Realizziamo il jukebox

Preparare l'ambiente

Tapestry5 in action

Preparare l'ambiente

Software utilizzato:

JDK 1.6 (mustang)

Servlet specification 2.4

Maven2

Eclipse 3.2

Maven2 plugin

Jetty launcher 1.4.1

Jetty 4.2.27

Mysql Server 5.0

Preparare l'ambiente

Prima di cominciare installiamo nel repository (locale) di maven tre jar previa scaricati:

jukemodel-1.0.0.jar (allegato alla presentazione)

jid3lib-0.5.4.jar, JLayer(mp3 util, reperibili qui e qui)

jta-1.0.1B.jar (java transaction api, reperibile qui)

mvn install:install-file -DgroupId=jukemodel -DartifactId=jukemodel -Dversion=1.0.0 -Dpackaging=jar -Dfile=/jarfile/path -DpomFile=/pomfile/path

mvn install:install-file -DgroupId=javax.transaction -DartifactId=jta -Dversion=1.0.1B -Dpackaging=jar -Dfile=/jarfile/path

mvn install:install-file -DgroupId=jid3lib -DartifactId=jid3lib -Dversion=0.5.4 -Dpackaging=jar -Dfile=/jarfile/path

mvn install:install-file -DgroupId=JLayer -DartifactId=JLayer -Dversion=1.0.0 -Dpackaging=jar -Dfile=/jarfile/path

Preparare l'ambiente

Ok, apriamo eclipse creiamo il nostro maven2 project jukeweb

File -> new -> project

Maven2 -> Maven2 project

Preparare l'ambiente

Create project:

Preparare l'ambiente

Configure project:

Preparare l'ambiente

Creato il progetto aggiungiamo le dipendenze:

jukemodel jukemodel 1.0.0 org.apache.tapestry tapestry-spring 5.0.6 org.springframework spring-web 2.0.2

Preparare l'ambiente

Ora dovremmo avere tutte le librerie necessarie.

Non ci resta che creare e configurare il web.xml

[...]

tapestry.app-packagejavaday.jukebox.web

jukeorg.apache.tapestry.TapestryFilter

juke/*

[...]

Creiamo la nostra prima page

Tapestry5 in action

Creiamo la nostra prima page

Start.java:

package javaday.jukebox.web.pages;

public class Start {

}

Creiamo la nostra prima page

Start.tml:

home page

Benvenuti nel mondo di Tapestry!
E' stata renderizzata la pagina ${class.simpleName}!

Creiamo la nostra prima page

Start.tml:

home page

Benvenuti nel mondo di Tapestry!
E' stata renderizzata la pagina ${class.simpleName}!

Creiamo la nostra prima page

La sintassi ${[prefix:]expression[.nestedExpr]} detta Expansions.

In un' expansions:

L'espressione passata viene interpretata secondo le regole di binding

La regola da usare viene selezionata con un prefisso

prop (default)

literal

message

Creiamo la nostra prima page

Bene, giunto il momento di lanciare per la prima volta l'applicazione:

Creiamo la nostra prima page

Configuriamo jetty:

Creiamo la nostra prima page

Configuriamo e lanciamo jetty:

Creiamo la nostra prima page

Infine digitiamo l'url sul browser:

http://localhost:8080/jukeweb/

Creiamo un componente per

gestire il layout

Tapestry5 in action

Creiamo un componente..

Prima di proseguire occorre includere nel progetto (in src/main/webapp/) alcune risorse disponibili come allegati alla presentazione:

Stylesheets

Immagini

Un flash mp3 player

E in src/main/resources/

Javascript files

Creiamo un componente..

Come gi detto le component classes e i component templates si devono trovare in qualunque sub-package di

tapestry.app-package/components

Creiamo quindi un componente che ci consenta di centralizzare la gestione del layout delle pagine

Creiamo un componente..

Border.java (versione 1)

package javaday.jukebox.web.components;

public class Border {

}

Creiamo un componente..

Border.tml (versione 1)

titolo finestra

...

Creiamo un componente..

Border.tml (versione 1)

...

titolo paginamenu Created by [email protected]

Creiamo un componente..

Border.tml (versione 1)

...

titolo paginamenu Created by [email protected]

Creiamo un componente..

Adeguiamo quindi il template Start.tml

Benvenuti nel mondo di Tapestry!
E' stata renderizzata la pagina ${class.simpleName}!

Creiamo un componente..

http://localhost:8080/jukeweb/

Creiamo un componente..

Ok, ora dovremmo avere acquisito un po' di confidenza col codice, ma il tutto ancora statico

Prima di tutto vediamo come fare a passare al Border i titoli per la finestra e per la pagina.

Creiamo un componente..

Un parametro di un componente altro non che un'attributo d'istanza opportunamente annotato (@Parameter) e corredato dei metodi accessor.

Creiamo un componente..

Border.java (versione 2)

package javaday.jukebox.web.components;

import org.apache.tapestry.annotations.Parameter;

public class Border {@Parameter(defaultPrefix="literal")private String windowTitle = "Untitled";

@Parameter(defaultPrefix="literal")private String pageTitle = "Untitled";

...

Creiamo un componente..

Border.java (versione 2)

package javaday.jukebox.web.components;

import org.apache.tapestry.annotations.Parameter;

public class Border {@Parameter(defaultPrefix="literal")private String windowTitle = "Untitled";

@Parameter(defaultPrefix="literal")private String pageTitle = "Untitled";

...Binding prefix:

prop

literal

asset

block

component

traslate

Message

validate

Creiamo un componente..

Border.java (versione 2)

...public String getPageTitle() {return pageTitle;}

public void setPageTitle(String pageTitle) {this.pageTitle = pageTitle;}

public String getWindowTitle() {return windowTitle;}

public void setWindowTitle(String windowTitle) {this.windowTitle = windowTitle;}

}

Creiamo un componente..

Adeguiamo quindi il template Start.tml

Benvenuti nel mondo di Tapestry!
E' stata renderizzata la pagina ${class.simpleName}!

Creiamo un componente..

http://localhost:8080/jukeweb/

Creiamo un componente..

Gli Assets

sono il meccanismo offerto da Tapestry per riferirsi a risorse statiche

Consentono di accedere a risorse presenti nel classpath (default) o nel context root della web application

Creiamo un componente..

Creiamo quindi ora in Border.java i riferimenti agli stylesheets, ai files javascript e al mp3 flash player

Per farlo dobbiamo

Dichiarare per ciascuna risorsa che vogliamo linkare una variabile d'istanza di tipo org.apache.tapestry.Asset e il corrispondente metodo getter (il setter non occorre in quanto la risorsa in sola lettura)

Creiamo un componente..

(continua)

Annotare ciascuna delle variabili con org.apache.tapestry.ioc.annotations.Inject

Annotare ciascuna delle variabili con org.apache.tapestry.annotations.Path (@Path(context|classpath:path/risorsa.ext))

Creiamo un componente..

Aggiungiamo a Border.java

...@Inject@Path("context:styles/layout.css")private Asset layout;@Inject@Path("context:styles/header.css")private Asset header;@Inject@Path("context:styles/menu.css")private Asset menu;@Inject@Path("context:styles/body.css")private Asset body;...

Creiamo un componente..

(...continua)

...@Inject@Path("classpath:js/script.js")private Asset script;@Inject@Path("classpath:js/audio-player.js")private Asset playerScript;

...

Creiamo un componente..

Aggiungiamo i metodi getter e modifichiamo il template

...

${windowTitle}

...

Creiamo un componente..

Dopo aver salvato ed eseguito diamo uno sguardo al codice risultante

......

Creiamo un componente..

Creiamo un componente per il men. Menu.java

package javaday.jukebox.web.components;

import org.apache.tapestry.annotations.OnEvent;

public class Menu {

@OnEvent(value="action")String openPage(String pageName){return pageName;}}

Creiamo un componente..

Creiamo un componente per il men. Menu.java

package javaday.jukebox.web.components;

import org.apache.tapestry.annotations.OnEvent;

public class Menu {

@OnEvent(value="action")String openPage(String pageName){return pageName;}}

Creiamo un componente..

E il template Menu.tml

Home

Creiamo un componente..

E il template Menu.tml

Home

Creiamo un componente per

il login/logout

Tapestry5 in action

Il componente login

Passiamo ora a creare un componente che gestisca le operazioni di login/logout

Al componente spettano la responsabilit di:

esporre le operazioni opportune

Conoscere e gestire il comportamento dell'applicazione al momento del login/logout

Il componente login

Login.java

package javaday.jukebox.web.components;...public class Login {

@Persist private String _userName;

private String _password;

@Component(id = "password") private PasswordField _passwordField;

@Component(id="loginForm") private Form _form;...

Il componente login

Login.java

package javaday.jukebox.web.components;...public class Login {

@Persist private String _userName;

private String _password;

@Component(id = "password") private PasswordField _passwordField;

@Component(id="loginForm") private Form _form;...

Il componente login

Login.java

package javaday.jukebox.web.components;...public class Login {

@Persist private String _userName;

private String _password;

@Component(id = "password") private PasswordField _passwordField;

@Component(id="loginForm") private Form _form;...

Il componente login

(... continua)

...@OnEvent(component="loginForm",value="success") void login() {boolean valid = false;if(!valid){ _form.recordError(_passwordField, "Invalid user name or password.");} }

@OnEvent(component="logout",value="action")void logout(){}...

Il componente login

(... continua)

...@OnEvent(component="loginForm",value="success") void login() {boolean valid = false;if(!valid){ _form.recordError(_passwordField, "Invalid user name or password.");} }

@OnEvent(component="logout",value="action")void logout(){}...

Il componente login

(... continua)

...@OnEvent(component="loginForm",value="success") void login() {boolean valid = false;if(!valid){ _form.recordError(_passwordField, "Invalid user name or password.");} }

@OnEvent(component="logout",value="action")void logout(){}...

Il componente login

(... continua)

...

public String getPassword() {return _password;}public void setPassword(String _password) {this._password = _password;}public String getUserName() {return _userName;}public void setUserName(String name) {_userName = name;}}

Il componente login

Login.tml

Loginuser...

Il componente login

Login.tml

Loginuser...

Il componente login

Login.tml

Loginuser...

Il componente login

Login.tml

Loginuser...

Il componente login

(..continua)

...passlogout

Il componente login

(..continua)

...passlogout

Il componente login

(..continua)

...passlogout

Il componente login

E' giunto il momento di integrare spring e il backend per comunicare con il database

Primo, modificare il filter nel web.xml

[...]

jukeorg.apache.tapestry.spring.TapestrySpringFilter

[...]

Il componente login

Secondo, aggiungere al web.xml:

Il listener di spring che si vuole usare

Il context-param che punta ai files di configurazione

[...]

contextConfigLocation/WEB-INF/config/bean.xml,/WEB-INF/config/hibernate-config.xml

org.springframework.web.context.ContextLoaderListener

[...]

Il componente login

Importiamo nel path opportuno i due files di configurazione di spring

Modifichiamo i dati per la connessione nel file hibernate-config.xml

[...][...]

Il componente login

Importiamo nel path opportuno i due files di configurazione di spring

Modifichiamo i dati per la connessione nel file hibernate-config.xml

[...][...]

Il componente login

Per conservare lo stato dell'utente creiamo una classe UserState nel package

tapestry.app-package/state

package javaday.jukebox.web.state;import javaday.jukebox.model.dto.User;public class UserState {private User user;public User getUser() {return user;}public void setUser(User user) {this.user = user;}public boolean isLoggedIn(){return user != null && user.getId() != null;}}

Il componente login

Aggiungiamo i riferimenti allo state object e allo userService, e il metodo getter per accedere allo state object in Login.java

...@ApplicationStateprivate UserState _userState;

@Injectprivate IUserService _userService;

public UserState getUserState() {return _userState;}

...

Il componente login

Aggiungiamo i riferimenti allo state object e allo userService, e il metodo getter per accedere allo state object in Login.java

...@ApplicationStateprivate UserState _userState;

@Injectprivate IUserService _userService;

public UserState getUserState() {return _userState;}

...

Il componente login

Aggiungiamo i riferimenti allo state object e allo userService, e il metodo getter per accedere allo state object in Login.java

...@ApplicationStateprivate UserState _userState;

@Injectprivate IUserService _userService;

public UserState getUserState() {return _userState;}

...

Il componente login

Aggiungiamo i riferimenti allo state object e allo userService, e il metodo getter per accedere allo state object in Login.java

...@ApplicationStateprivate UserState _userState;

@Injectprivate IUserService _userService;

public UserState getUserState() {return _userState;}

...Per specificare il nome del bean da usare occorre modificare il codice come segue:

@Inject@Service("userService")private IUserService _userService;

Il componente login

Modifichiamo i metodi login e logout in Login.java

...@OnEvent(component="loginForm",value="success")void login(){_userState.setUser(_userService.login(getUserName(), getPassword()));if(!_userState.isLoggedIn()){ _form.recordError(_passwordField, "Invalid user name or password.");}}@OnEvent(component="logout",value="action")void logout(){_userState.setUser(null);}...

Il componente login

Ora con il tapestry component If facciamo in modo che nel template Login.tml venga mostrato il form di login solo se non ci si loggati e l'inverso per il comando di logout.

L'If component ha la seguente forma:

renderizzato se test=true e negate=false, oppure test=false e negate=truealtrimenti renderizza questo

Il componente login

Il Login.tml diventa quindi:

[...]logout

Il componente login

Adesso, per verificare quanto realizzato inseriamo un utente di prova sul db

insert into user (user, pass, firstName, name, emailAddress, birthDate)values ('bobpuley', 'bobpuley', 'pugliese', 'marco', '[email protected]', '1973-02-24');

Il componente login

Login:

Il componente login

Login:

La pagina di iscrizione utente

Tapestry5 in action

La pagina d'iscrizione utente

Veniamo ora a esaminare un componente molto potente, il beanEditForm.

La pagina d'iscrizione utente

Il beanEditForm:

Accetta i seguenti parametri:

object: l'oggetto che si vuole editare

remove: una lista di nomi di attributi dell'oggetto da editare, di cui si vuol inibire il rendering

submitLabel: l'etichetta del submit button del form

model: un'istanza di org.apache.tapestry.beaneditor.BeanModel

reorder: una lista di nomi di attributi nell'ordine desiderato

clientValidation: true|false

La pagina d'iscrizione utente

Il beanEditForm:

mappa

Boolean con checkbox

java.util.Date con DateField

Enum con select

String e Number con textField

La pagina d'iscrizione utente

Il beanEditForm:

mappa

Boolean con checkbox

java.util.Date con DateField

Enum con select

Tipi primitivi, wrapper e String con textField

Pu essere ulteriormente configurato annotando opportunamente l'oggetto che gli si passa.

La pagina d'iscrizione utente

Aggiungiamo il package account all'interno della root delle page component classes e creaiamo la classe CreateAccount.java

package javaday.jukebox.web.pages.account;import javaday.jukebox.model.dto.User;import org.apache.tapestry.annotations.OnEvent;public class CreateAccount {

private User user = new User();

public User getUser() {return user;}public void setUser(User user) {this.user = user;}

@OnEvent(component="userForm", value="success")void menageAccount(){System.out.println(user);}}

La pagina d'iscrizione utente

Aggiungiamo il package account all'interno della root delle page component classes e creaiamo la classe CreateAccount.java

package javaday.jukebox.web.pages.account;import javaday.jukebox.model.dto.User;import org.apache.tapestry.annotations.OnEvent;public class CreateAccount {

private User user = new User();

public User getUser() {return user;}public void setUser(User user) {this.user = user;}

@OnEvent(component="userForm", value="success")void menageAccount(){System.out.println(user);}}

La pagina d'iscrizione utente

...e il template.

Pass

La pagina d'iscrizione utente

...e il template.

Pass

La pagina d'iscrizione utente

...e il template.

reorder="user,pass,firstName,name,birthDate,emailAddress">Pass

La pagina d'iscrizione utente

...e il template.

reorder="user,pass,firstName,name,birthDate,emailAddress">Pass

La pagina d'iscrizione utente

http://localhost:8080/jukeweb/account/create

La pagina d'iscrizione utente

Come forse avrete notato la url non come ci si aspetterebbe /account/createaccount, bens /account/create. In sostanza tapestry ignora la ripetizione di account, questo consente di avere url pi pulite.

Resta da realizzare un link per accedere alla pagina di iscrizione, e aggiungere un riferimento al servizio verso il db nella classe della pagina per salvare l'utente creato.

La pagina d'iscrizione utente

Login.tml

[...]

Loginuserpassor: Get an account

[...]

La pagina d'iscrizione utente

CreateAccount.java

package javaday.jukebox.web.pages.account;import javaday.jukebox.model.dto.User;import org.apache.tapestry.annotations.OnEvent;public class CreateAccount {

private User user = new User();@Injectprivate IUserService userService;

public User getUser() {return user;}public void setUser(User user) {this.user = user;}

@OnEvent(component="userForm", value="success")void menageAccount(){userService.create(user);}}

La pagina d'iscrizione utente

CreateAccount.java

package javaday.jukebox.web.pages.account;import javaday.jukebox.model.dto.User;import org.apache.tapestry.annotations.OnEvent;public class CreateAccount {

private User user = new User();@Injectprivate IUserService userService;

public User getUser() {return user;}public void setUser(User user) {this.user = user;}

@OnEvent(component="userForm", value="success")void menageAccount(){userService.create(user);}}

La pagina d'iscrizione utente

CreateAccount.java

package javaday.jukebox.web.pages.account;import javaday.jukebox.model.dto.User;import org.apache.tapestry.annotations.OnEvent;public class CreateAccount {

private User user = new User();@Injectprivate IUserService userService;

public User getUser() {return user;}public void setUser(User user) {this.user = user;}

@OnEvent(component="userForm", value="success")void menageAccount(){userService.create(user);}}

L'upload di un file

Tapestry5 in action

L'upload di un file

Tapestry incapsula il componente e i servizi, necessari per effettuare l'upload, in un modulo a parte tapestry-upload.jar

Quindi aggiungiamo la dipendenza corrispondente nel pom.xml

[...]

org.apache.tapestry tapestry-upload 5.0.6

[...]

L'upload di un file

Creiamo una class page track/CreateTrack.java

public class CreateTrack {

private UploadedFile uploadedFile;

@OnEvent(component = "uploadForm", value = "success")public void upload() {FileUtil fileUtil = new FileUtil(null);File file = fileUtil.getTmpFile(uploadedFile.getFileName());uploadedFile.write(file);}public UploadedFile getUploadedFile() {return uploadedFile;}

public void setUploadedFile(UploadedFile uploadedFile) {this.uploadedFile = uploadedFile;}}

L'upload di un file

Quindi il template track/CreateTrack.tml

Upload a Mp3Add track

L'upload di un file

Una volta caricato il file dobbiamo inserire i dati ad essa relativi

Modifichiamo il metodo upload come segue

@OnEvent(component = "uploadForm", value = "success")public void upload() {FileUtil fileUtil = new FileUtil(null);File file = fileUtil.getTmpFile(uploadedFile.getFileName());uploadedFile.write(file);try {setTrack(fileUtil.getMp3Infos(file));setStyle(StylesEnum.getFromValue(getTrack().getStyle()));} catch (Exception e) {setTrack(new Track());}}

L'upload di un file

Una volta caricato il file dobbiamo inserire i dati ad essa relativi

Modifichiamo il metodo upload come segue

@OnEvent(component = "uploadForm", value = "success")public void upload() {FileUtil fileUtil = new FileUtil(null);File file = fileUtil.getTmpFile(uploadedFile.getFileName());uploadedFile.write(file);try {setTrack(fileUtil.getMp3Infos(file));setStyle(StylesEnum.getFromValue(getTrack().getStyle()));} catch (Exception e) {setTrack(new Track());}}

L'upload di un file

Una volta caricato il file dobbiamo inserire i dati ad essa relativi

Modifichiamo il metodo upload come segue

@OnEvent(component = "uploadForm", value = "success")public void upload() {FileUtil fileUtil = new FileUtil(null);File file = fileUtil.getTmpFile(uploadedFile.getFileName());uploadedFile.write(file);try {setTrack(fileUtil.getMp3Infos(file));setStyle(StylesEnum.getFromValue(getTrack().getStyle()));} catch (Exception e) {setTrack(new Track());}}

L'upload di un file

Aggiungiamo un attributo Track con i relativi accessor, per editare le informazioni.

@Persistprivate Track track = null;public Track getTrack() {return track;}

public void setTrack(Track track) {this.track = track;}

L'upload di un file

Occorre anche definire un attributo StylesEnum

Essendo una enum, il beanEditForm la gestir con una select.

@Persistprivate StylesEnum style;public StylesEnum getStyle() {return style;}

public void setStyle(StylesEnum style) {this.style = style;}

L'upload di un file

Infine ci servono i riferimenti allo stateObject e al servizio per salvare la traccia creata

@Injectprivate ITrackService trackService;@ApplicationStateprivate UserState state;

@OnEvent(component = "trackForm", value = "success")public void saveTrack() {try {track.setUser(state.getUser());track.setStyle(getStyle().toString());trackService.create(getTrack());track.setFileName(new FileUtil(null).modifyTrack(track));trackService.modify(track);setTrack(null);setStyle(null);} catch (Exception e) {e.printStackTrace();}}

L'upload di un file

Infine ci servono i riferimenti allo stateObject e al servizio per salvare la traccia creata

@Injectprivate ITrackService trackService;@ApplicationStateprivate UserState state;

@OnEvent(component = "trackForm", value = "success")public void saveTrack() {try {track.setUser(state.getUser());track.setStyle(getStyle().toString());trackService.create(getTrack());track.setFileName(new FileUtil(null).modifyTrack(track));trackService.modify(track);setTrack(null);setStyle(null);} catch (Exception e) {e.printStackTrace();}}

L'upload di un file

Infine ci servono i riferimenti allo stateObject e al servizio per salvare la traccia creata

@Injectprivate ITrackService trackService;@ApplicationStateprivate UserState state;

@OnEvent(component = "trackForm", value = "success")public void saveTrack() {try {track.setUser(state.getUser());track.setStyle(getStyle().toString());trackService.create(getTrack());track.setFileName(new FileUtil(null).modifyTrack(track));trackService.modify(track);setTrack(null);setStyle(null);} catch (Exception e) {e.printStackTrace();}}

L'upload di un file

Infine ci servono i riferimenti allo stateObject e al servizio per salvare la traccia creata

@Injectprivate ITrackService trackService;@ApplicationStateprivate UserState state;

@OnEvent(component = "trackForm", value = "success")public void saveTrack() {try {track.setUser(state.getUser());track.setStyle(getStyle().toString());trackService.create(getTrack());track.setFileName(new FileUtil(null).modifyTrack(track));trackService.modify(track);setTrack(null);setStyle(null);} catch (Exception e) {e.printStackTrace();}}

L'upload di un file

Infine ci servono i riferimenti allo stateObject e al servizio per salvare la traccia creata

@Injectprivate ITrackService trackService;@ApplicationStateprivate UserState state;

@OnEvent(component = "trackForm", value = "success")public void saveTrack() {try {track.setUser(state.getUser());track.setStyle(getStyle().toString());trackService.create(getTrack());track.setFileName(new FileUtil(null).modifyTrack(track));trackService.modify(track);setTrack(null);setStyle(null);} catch (Exception e) {e.printStackTrace();}}

L'upload di un file

Infine dobbiiamo modificare il template, in modo da mostrare prima l'upload form, e poi il track form.

[...]form uploadEdit infoPass[...]

L'upload di un file

Infine dobbiiamo modificare il template, in modo da mostrare prima l'upload form, e poi il track form.

[...]form uploadEdit infoPass[...]

L'upload di un file

Infine dobbiiamo modificare il template, in modo da mostrare prima l'upload form, e poi il track form.

[...]form uploadEdit infoPass[...]

L'upload di un file

Infine dobbiiamo modificare il template, in modo da mostrare prima l'upload form, e poi il track form.

[...]form uploadEdit infoPass[...]

Realizziamo il jukebox

Tapestry5 in action

Realizziamo il jukebox

Bene, siamo giunti all'ultimo elemento dell'applicazione

Nel realizzarlo vedremo

come untilizzare il grid component

Realizziamo il jukebox

Bene, siamo giunti all'ultimo elemento dell'applicazione

Nel realizzarlo vedremo

come untilizzare il grid component

come realizzare un componente che scrive direttamente sull'output (privo di template)

Realizziamo il jukebox

Bene, siamo giunti all'ultimo elemento dell'applicazione

Nel realizzarlo vedremo

come untilizzare il grid component

come realizzare un componente che scrive direttamente sull'output (privo di template)

come ottenere uno stream verso una risorsa tramite Tapestry

Realizziamo il jukebox

Modifichiamo quindi la Start page, e aggiungiamole gli attributi

@Persistprivate List tracks = new ArrayList();

private Track itemTrack;

@Injectprivate ITrackService service;

public Track getItemTrack() {return itemTrack;}public void setItemTrack(Track itemTrack) {this.itemTrack = itemTrack;}

public List getTracks() {return tracks;}public void setTracks(List tracks) {this.tracks = tracks;}

Realizziamo il jukebox

Modifichiamo quindi la Start page, e aggiungiamole gli attributi

@Persistprivate List tracks = new ArrayList();

private Track itemTrack;

@Injectprivate ITrackService service;

public Track getItemTrack() {return itemTrack;}public void setItemTrack(Track itemTrack) {this.itemTrack = itemTrack;}

public List getTracks() {return tracks;}public void setTracks(List tracks) {this.tracks = tracks;}

Realizziamo il jukebox

Infine faccio in modo che quando la pagina viene inizializzata, carichi dal database le tracce.

@SetupRendervoid init(){setTracks(service.findAll());if(getTracks()==null || getTracks().isEmpty()){setTracks(new ArrayList());}}

Realizziamo il jukebox

Infine faccio in modo che quando la pagina viene inizializzata, carichi dal database le tracce.

@SetupRendervoid init(){setTracks(service.findAll());if(getTracks()==null || getTracks().isEmpty()){setTracks(new ArrayList());}}

Realizziamo il jukebox

Quindi inseriamo il component grid nel template

Benvenuti nel mondo di Tapestry!
E' stata renderizzata la pagina ${class.simpleName}!JukeBoxThe collection is empty.

Realizziamo il jukebox

Riordiniamo gli attributi

Benvenuti nel mondo di Tapestry!
E' stata renderizzata la pagina ${class.simpleName}!JukeBoxThe collection is empty.

Realizziamo il jukebox

Aggiungiamo la paginazione

Benvenuti nel mondo di Tapestry!
E' stata renderizzata la pagina ${class.simpleName}!JukeBoxThe collection is empty.

Realizziamo il jukebox

Gestiamo il rating con un componente specifico

Benvenuti nel mondo di Tapestry!
E' stata renderizzata la pagina ${class.simpleName}!JukeBoxThe collection is empty.

Realizziamo il jukebox

Il componente Rating.java

public class Rating {private static final String MAX_RATING = "*****";@Parameter(required=true)private Integer ratingValue;@BeginRendervoid render(MarkupWriter writer){int rating = calculateRating(ratingValue);writer.element("span","class","rating" + rating);writer.write(getRatingStars(rating));writer.end();}

...

Realizziamo il jukebox

Il componente Rating.java

public class Rating {private static final String MAX_RATING = "*****";@Parameter(required=true)private Integer ratingValue;@BeginRendervoid render(MarkupWriter writer){int rating = calculateRating(ratingValue);writer.element("span","class","rating" + rating);writer.write(getRatingStars(rating));writer.end();}

...

Realizziamo il jukebox

Il componente Rating.java

public class Rating {private static final String MAX_RATING = "*****";@Parameter(required=true)private Integer ratingValue;@BeginRendervoid render(MarkupWriter writer){int rating = calculateRating(ratingValue);writer.element("span","class","rating" + rating);writer.write(getRatingStars(rating));writer.end();}

...

Realizziamo il jukebox

Il componente Rating.java

public class Rating {private static final String MAX_RATING = "*****";@Parameter(required=true)private Integer ratingValue;@BeginRendervoid render(MarkupWriter writer){int rating = calculateRating(ratingValue);writer.element("span","class","rating" + rating);writer.write(getRatingStars(rating));writer.end();}

...

Realizziamo il jukebox

Il componente Rating.java

public class Rating {private static final String MAX_RATING = "*****";@Parameter(required=true)private Integer ratingValue;@BeginRendervoid render(MarkupWriter writer){int rating = calculateRating(ratingValue);writer.element("span","class","rating" + rating);writer.write(getRatingStars(rating));writer.end();}

...

Realizziamo il jukebox

Il componente Rating.java

public Integer getRatingValue() {return ratingValue;}

public void setRatingValue(Integer value) {this.ratingValue = value;}private String getRatingStars(int rating) {return MAX_RATING.substring(0, rating);}private int calculateRating(Integer value) {int rating = (int)(value/5) + 1;rating = rating