Newsgroup: it.comp.java
Titolo: Passaggio dati da client a server con jsf

Salve a tutti.
Caso classico: ho una lista di dati cliccando su uno dei quali voglio
aprire la pagina con i dati (di quel record) da modificare.
Per fare ciò, mi basta ripassare al metodo lato server un'unica
informazione che chiameremo id.
Uso le facelets. La pagina che presenta la lista è questa:
<f:view>
<h:form>
	<table width="98%" border="1">
		<ui:repeat value="${tipologicaStandardForm.elencoRecord}"
var="tipologicaStandard">
			<tr>
				<td>
					<h:commandLink action="$
{tipologicaStandardForm.paginaDiModifica}" value="$
{tipologicaStandard.codice}">
						<f:param name="id" value="${tipologicaStandard.id}"/>
					</h:commandLink>
				</td>
				<td>
					<h:commandLink
action="#{tipologicaStandardForm.paginaDiModifica}"
value="#{tipologicaStandard.descrizione}">
						<h:inputHidden value="#{tipologicaStandard.id}"
binding="#{tipologicaStandardForm.id}"/>
					</h:commandLink>
				</td>
			</tr>
		</ui:repeat>
	</table>
</h:form>
</f:view>
Come vedete, sulle due colonne, corrispondenti a codice e descrizione,
ci sono due commandLink con la stessa action. Se clicco sul codice,
però, passo un <f:param> che poi recupero nel metodo paginaDiModifica
in qyesto modo:
		FacesContext facesContext = FacesContext.getCurrentInstance();
		String idTest =
facesContext.getExternalContext().getRequestParameterMap().get("id");
Nell'altro caso, invece, cioè cliccando sulla descrizione, lancio il
binding con un campo HtmlInputHidden.
Questa econda soluzione, a me piace di più perchè cos' non ho bisogno
di scrivere la stringa col nome del campo nel metodo ("id" per
capirci) ma, non riesco a capire come recuperare il valore del campo
hidden.
Infatti, nel mio setId
	public void setId(HtmlInputHidden id) {
 
this.id
 = id;
		if (
this.id
 != null){
			ValueExpression valueExpression =
this.id.getValueExpression("value");
			Object value = this.id.getValue();
			Object localValue = this.id.getLocalValue();
			Object submittedValue = this.id.getSubmittedValue();
		}
	}
tutti e tre gli Object sono null. Qual è la procedura per recuperare
questo valore?
Grazie
P.S.: se invece di <ui:repeat> uso <c:forEach>, l'AS mi va in
OutOfMemoryError... Avete idea del perchè?

informazione che chiameremo id.
Il primo metodo secondo me e' quasi corretto, il secondo totalmente 
sbagliato (come leggibilita' del codice) e non lo considero neppure.
Ci sono altri 2 metodi comunemente utilizzati per cio' che vuoi ottenere:
1) utilizzare un componente UIData (ui:repeat  non estende UIData) come 
h:dataTable e mettere un binding su dataTable.
Dentro la action ottieni l'oggetto nel seguente modo:
Utente utente = (Utente)table.getRowData()
Unica controindicazione e' che il binding *non* dovrebbe mai referenziare un 
bean di scope session.
2) utilizzare f:setPropertyActionListener
<ui:repat value="#{list}" var="utente">
<h:commandLink action="...">
  <f:setPropertyActionListener target="#{bean.utente}" value="#{utente}"/>
</h:commandLink>
</ui:repeat>
dove utente e' una property di bean.
JSF prima di invocare la action esegue l'actionListener 
(f:setPropertyActionListener) che imposta la proprieta'. 


In effetti non lo voglio affatto. Lo "scotto" però che devo pagare è
che il metodo richiamato dall'attributo "value" del DataTable deve
effettuare "lui" l'accesso al DB per la generazione della collection
da iterare; se invece - come piacerebbe a me - io invoco un metodo del
backing bean che si occupa di tutto ciò che concerne l'accesso al
model tra cui anche popolare la suddetta Collection e poi forwarda la
pagina in cui ho il datatable, l'elenco mi viene renderizzato ma il
puntamento allo specifico oggetto è perso, ossia, quando clicco sul
commandLink il metodo definito nell'attributo action non viene
invocato così come non ho modo di recuperare il rowData puntato.
Quindi, il problema è che, fino a quando io ho nella pagina un unico
elenco tutto ok ma, se io ho nella pagina più dati provenienti da
accessi diversi e che normalmente gestirei in un'unica transazione
PRIMA del forward - anche per evitare chiamate EJB multiple - o invece
accetto l'idea che ogni getter faccia la sua chiamata o faccio come
vorrei impostando però il managed bean con scope session.
Tutti ciò, resta valido anche se usassi <f:param> o
<f:setPropertyActionListener>
Sul OutOfMemory hai qualche idea? Perchè volevo appunto provare a
vedere cosa accadrebbe se usassi il forEach (e quindi non avrei più
una relazione tra commandLink e oggetto)
Per inciso, ho postato la stessa domanda anche sul forum della Sun e
mi hanno consigliato quest'ottimo articolo:
http://balusc.blogspot.com/2006/06/using-datatables.html

una relazione tra commandLink e oggetto)
Molto probabilmente non hai nessuna necessita' di utilizzare forEach, 
lascialo stare, dimentica tutto cio' che concerne JSTL.
Utilizzare forEach significa avere problemi di performance: ad ogni 
iterazione reinstanzia i componenti. Un comportamento ben differente e molto 
piu' performante si ha con ui:repeat o i componenti UIData. 


Ripeto: non voglio mettere il bean in sessione (non ha senso in questo
contesto).
Il problema non è il binding perchè come passare i dati (lo so,
oggetto del thread) si è capito.
Il problema concettuale mio è che ogni componente debba attivare con
il suo getter l'accesso ai dati (quindi N componenti N transazioni)
qualora sul loro output io voglia inserire un commandLink (o un
commandButton). E questo perchè, anche se io riesco a passare lo
stesso i dati alla pagina, quello che viene specificato nell'attributo
action non ha luogo qualora, invece, io precaricassi tutto (quindi con
un unico accesso al model) prima di entrare nella pagina.
Esempio: Ho due liste sugli item di ognuna delle quali voglio mettere
un comandLink? I loro due getter devono occuparsi dell'accesso ai
dati.
Se il metodo del backing bean che invoca la pagina con le due liste,
valorizza previamente lui le due Collection lato server prima di fare
il forward, i due getter funzionano lo stesso ma l'oggetto "da
cliccare" finito il rendering non esiste più e quindi il click non
produce nulla.
Sul forum della Sun mi parlano di "lazy loading". Secondo te cosa
intendono?

 commandButton).
Mi chiedo anche,
ma come fa il getter a sapere come è arrivato l'attributo?
Ossia, come fa la pagina a distinguere tra un
Collection getElenco(){
return elenco; //attributo valorizzato dal backing bean prima del
forward della pagina che utilizzerà questo metodo
}
e un
Collection getElenco(){
elenco = dao.execute()
return elenco;
}

intendono?
Si rifericonosco a Hibernate, ma non centra molto lascia stare. 


Ma io non voglio nemmeno che mi durino. Lo vuole jsf per permettermi
di lanciare l'action sul commandLink del dato i-esimo e che io ho
posizionato all'interno delle righe solo per poter passare
(con<f:param> o <f:setPropertyActionListener> un dato alla mia
action). In pratica, quando io clicco sul commandLink jsf richiama
un'altra volta il getter della Collection anche se a me non serve più
(il dato da passare ce l'ho già in canna) e siccome era requestScope
il getter gli restituisce null e l'action che con quella collection
non ci farebbe nulla non parte.
In pratica, quello che io non capisco è questo.
1) Determino una lista per ottenere alcuni oggetti.
2) Voglio usare un attributo di uno di essi per una nuova chiamata
(nella fattispecie per recuperare il dettaglio complessivo dal db)
3) Per fare la nuova chiamata usando l'attributo i-esimo (che ho
salvato già in un mio tag!) devo comunque rigenerare una collection
che a me non serve più
4) Se la collection non si rigenera il dato passa ma il metodo di
action non parte.
Come vedi, questa procedura, molto classica, non prevede l'uso della
request e siccome è una procedura molto standard se io dovessi
risolvere il tutto con la sessione alla fine avrei quasi tutti i miei
managed bean in sessione.
Con struts questa cosa si faceva facendo un semplice href al .do
mettendo il parametro in query string. Possibile che non si riesca ad
ottenere lo stesso con jsf al prezzo di nulla?

 ha scritto nel messaggio 
news:1193385388.2...@k79g2000hse.googlegroups.com...


JSF cerca di darti la possibilita' di ottenere la riga cliccata 
autoamticamente, qualora il bean non sia in request.
Se vuoi procedere con il metodo classico passando l'id dell'oggetto non vedo 
il problema.
Hai gia' mostrato tu un esempio con il commandLink e f:param name="id".
Per caso stai usando tomahawk oppure ajax4jsf? Offrono una possibilita' in 
piu' riguardo a questo problema.

 piu' riguardo a questo problema.
No, le richfaces di Jboss

 collection.
Giusto, scusa.
Visto che stai uando richfaces (che contiene a4j), guarda il componente 
a4j:keepAlive.
finche' il componente e' nella pagina il bean di request rimane vivo.
Ma con l'id come si dovrebbe fare?
JSF a riguardo offre i phase-listener.
Potresti usare un outputLink per generare la url con l'id, e dentro il phase 
listenere leggi l'id, e invochi il metodo opportuno (tramite EL magari).
Ci sono alcune librerie che rendono semplicissimo questo approccio stile 
action (tipico di action framework come Struts e Spring MVC).
Mi vengono in mente a riguardo Seam, Shale, Gravel, RestFaces....se ti 
interessa cerca (Seam forse e' troppo avanti per iniziare secondo me). 

 ha scritto nel messaggionews:1193391987.9...@v3g2000hsg.googlegroups.com...

Ti ringrazio, ora mi guardo un po' tutto.
Ma a me premerebbe di più lavorare alla jsf. Se mi dici che
l'approccio è alla Struts vuol dire che c'è qualcosa che ancora non ho
capito.
In soldoni, qual è l'approccio corretto con JSF per creare un elenco
di oggetti e poi cliccando su uno di essi aprirlo in dettaglio su
un'altra pagina?