SeamFramework.orgCommunity Documentation
Seam utilizza JBoss EL, il quale fornisce un'estensione allo standard Unified Expression Language (EL). JBoss EL apporta un numero di miglioramenti che incrementano l'espressività e la potenza delle espressioni EL.
Lo standard EL non consente di utilizzare un metodo con parametri definiti dall'utente — sicuramente metodi JSF listener (es. valueChangeListener
) prende i parametri forniti da JSF.
JBoss EL rimuove questa restrizione. Per esempio:
<h:commandButton action="#{hotelBooking.bookHotel(hotel)}" value="Book Hotel"/>
@Name("hotelBooking")
public class HotelBooking {
public String bookHotel(Hotel hotel) {
// Book the hotel
}
}
Come nelle chiamate ai metodi in Java, i parametri sono racchiusi tra parentesi e separati da virgole:
<h:commandButton action="#{hotelBooking.bookHotel(hotel, user)}" value="Book Hotel"/>
I parametri hotel
e user
verranno valutati come espressioni di valore e passati al metodo bookHotel()
del componente.
Qualsiasi valore d'espressione può essere usato come parametro:
<h:commandButton
action="#{hotelBooking.bookHotel(hotel.id, user.username)}"
value="Book Hotel"/>
E' importante capire bene come funziona quest'estensione a EL. Quando la pagine viene generata, i nomi dei parametri vengono memorizzati (per esempio hotel.id
e user.username
) e valutati (come espressioni di valore) quando la pagina viene inviata. Non si possono passare oggetti come parametri!
Devi assicurarti che i parametri siano disponibili non solo quando la pagina viene generata, ma anche quando ne viene fatto il submit. Se gli argomenti non possono essere risolti quando la pagina viene inviata, il metodo d'azione verrà chiamato con argomenti null
!
Si può passare stringe letterali usando virgolette singole:
<h:commandLink action="#{printer.println('Hello world!')}" value="Hello"/>
EL unificato supporta anche le espressioni di valore, usate per associare un campo ad un bean. Le espressioni di valore utilizzano le convenzioni dei nomi di JavaBean e richiedono get e set. Spesso JSP si attende un'espressione di valore dove solo un recupero (get) è richiesto (es. l'attributo rendered
). Molti oggetti, comunque, non hanno nominato in modo appropriato i metodi accessor alle proprietà o i parametri richiesti.
JBoss EL rimuove questa restrizione permettendo che i valori vengano recuperati usando la sintassi del metodo. Per esempio:
<h:outputText value="#{person.name}" rendered="#{person.name.length()
> 5}" />
Si può accedere alla dimensione di una collezione in maniera analoga:
<h:outputText value="#{person.name}" rendered="#{person.name.length() > 5}" />
In generale qualsiasi espressione nella forma #{obj.property} è identica all'espressione #{obj.getProperty()}.
Sono consentiti anche i parametri. Il seguente esempio chiama productsByColorMethod
con un argomento stringa letterale:
#{controller.productsByColor('blue')}
Nell'uso di JBoss EL dovresti tenere presente i seguenti punti:
Incompatibilità con JSP 2.1 — JBoss EL non può attualmente essere utilizzato con JSP 2.1 poiché il compilatore rifiuta espressioni con paramentri al suo interno. Quindi per usare quest'estensione con JSF 1.2, si dovranno utilizzare Facelets. Quest'estensione funziona correttamente con JSP 2.0.
Utilizzo all'interno di componenti iterativi — Componenti quali <c:forEach />
e <ui:repeat />
iterano su una lista o un array, esponendo ogni item della lista ai componenti innestati. Questo funziona bene selezionando una riga con <h:commandButton />
o <h:commandLink />
:
@Factory("items")
public List<Item
> getItems() {
return entityManager.createQuery("select ...").getResultList();
}
<h:dataTable value="#{items}" var="item">
<h:column>
<h:commandLink value="Select #{item.name}" action="#{itemSelector.select(item})" />
</h:column>
</h:dataTable
>
Comunque si voglia usare <s:link/>
o <s:button/>
si deve esporre gli item come DataModel
e usare <dataTable />
(o equivalente da componente impostato come <rich:dataTable />
). Né <s:link />
né <s:button />
eseguono il submit della form (e quindi producono un bookmarkable link) quindi serve un parametro "magico" per ricreare l'item quando viene chiamato l'action method. Questo parametro magico può essere aggiunto soltanto quando viene usata una data table con dietro un DataModel
.
Chiamata di un MethodExpression
da codice Java — normalmente quando una MethodExpression
viene creata, i tipi di parametro sono passati tramite JSF. Nel caso di un binding di metodo, JSF presume che non ci siano parametri da passare. Con quest'estensione non è possibile sapere il tipo di parametro prima che l'espressione venga valutata. Ciò ha due conseguenze:
Quando viene invocato un MethodExpression
nel codice Java, i parametri passati potrebbero essere ignorati. I parametri definiti nell'espressione avranno la precedenza.
Solitamente è sicuro chiamare in ogni momento methodExpression.getMethodInfo().getParamTypes()
. Per un'espressione con parametri occorre invocare il MethodExpression
prima di chiamare getParamTypes()
.
Entrambi questi casi sono estremamente rari e si applicano solo quando si vuole invocare manualmente MethodExpression
nel codice Java.
JBoss EL supporta una limitata sintassi di proiezione. Un'espressione di proiezione mappa una sotto-espressione attraverso un'espressione a valori multipli (lista, set, ecc...). Per esempio, l'espressione:
#{company.departments}
potrebbe restituire una lista di dipartimenti. Se occorresse una lista di nomi di dipartimento, l'unica opzione è quella di iterare sulla lista per recuperare i valori. JBoss EL permette questo con l'espressione di proiezione:
#{company.departments.{d|d.name}}
La sotto-espressione è racchiusa da parentesi. In quest'esempio l'espressione d.name
viene valutata per ogni dipartimento, usando d
come alias per l'oggetto dipartimento. Il risultato di quest'espressione sarà una lista di valori Stringa.
Qualsiasi espressione valida può essere usata in un'espressione, e quindi sarebbe perfettamente valido scrivere la seguente, assumendo che venga usata per le lunghezze di tutti i nomi di dipartimento in un'azienda:
#{company.departments.{d|d.size()}}
Le proiezioni possono essere annidate. La seguente espressione ritorna gli ultimi nomi di ciascun impiegato in ogni dipartimento:
#{company.departments.{d|d.employees.{emp|emp.lastName}}}
Le proiezioni annidate possono comunque rivelarsi un pò difficoltose. La seguente espressione sembra ritornare una lista di tutti gli impiegati in tutti i dipartimenti:
#{company.departments.{d|d.employees}}
Comunque, restituisce una lista contenente una lista di impiegati per ogni singolo dipartimento. Per combinare questi valori è necessario usare un'espressione leggermente più lunga:
#{company.departments.{d|d.employees.{e|e}}}
E' importante notare che questa sintassi non può essere analizzata da Facelets o JSP e quindi non può essere usata in file xhtml o jsp. Anticipiamo che la sintassi di proiezione cambierà nelle future versioni di JBoss EL.