Die JSF Spring Integration enthält zusätzlichen Integration, um JSF Ext zusammen mit Spring verwenden zu können.
Custom Scope Injection#
Beim Laden von Scopes werden typischer Weise Parameter übergeben:<h:commandButton image="#{resource['images/bitcons:edit.gif']}" title="#{messages['edit']}"> <f:ajax/> <e:load scopeId=":user-input"> <f:param name="user" value="#{user}"/> </e:load> </h:commandButton>
Der Wert wird zunächst in den geladenen Scope geschrieben. Die Parameter können generell mit der Spring-Annotation @Value injiziert über eine EL-Expression injiziert werden:
Allerdings macht Spring Probleme, wenn die EL-Expression zu null evaluiert oder das Property nicht gefunden werden kann. Des Weiteren stört die unnötige EL-Expression, da der Wert bereits durch den Feld- bzw. Methodennamen klar ist, ähnlich bei @Autowired. Durch die Annotation @ScopeValue kann dies eleganter erreicht werden:
@Component @Scope(Scopes.CUSTOM_SCOPE) public class UserEdit { @ScopeValue private User user; public User getUser() { if (user == null) user = new User(); return user; } public void setUser(User user) { this.user = user; } }
Die Annotation @ScopeValue ist vergleichbar mit @Value("#{scope.user}"). Allerdings ist die Injection effizienter, da keine EL-Expression evaluiert wird und es kommt zu keinen Problemen, falls der Wert nicht vorhanden ist.
Request Parameter Injection#
Sicher gibt es auch andere Möglichkeiten Parameter aus dem HTTP Servlet-Request in eine Bean zu bekommen. Die direkteste Methode ist:FacesContext context = FacesContext.getCurrentInstance().getExternalContext(); String value = context.getRequestParameterMap().get(<name>);
Allerdings gibt es gute Gründe, die Injection der JSF Spring Integration zu verwenden:
- Auswertung erfolgt zum richtigen Zeitpunkt, während des Requests. Der Wert befindet sich im Property, wenn er benötigt wird. Es ist unter Umständen zu spät, den Parameter aus dem Request zu holen, wenn er benötigt wird, weil dann bereits ein weiterer Request ausgeführt wird.
- Die Null-Fälle werden abgehandelt, es kommt zu keinen Exceptions
- Es wird die Übliche Faces-Konvertierung in Enums, Zahlen etc. durchgeführt
- Der Code ist einfacher und verständlicher, weil er deklarativ ist und keine zusätzlichen Instruktionen enthält
Das Ganze sieht dann so aus:
@Component @Scope(WebApplicationContext.SCOPE_REQUEST) public class ParamController { @RequestParam private Long id; ... }
Flash Parameter Injection#
Eine großartige Neuerung von JSF 2 ist der sogenannte Flash. Es handelt sich um eine Cookie-basierte Map, die Redirects überlebt. Sie kann damit ein Bindeglied zwischen View-Scopes darstellen.Der Flash ermöglicht das gleichzeitige Verwenden von View-Scopes und die Übergabe von Parametern zwischen unterschiedlichen Views.
Hier ein Beispiel:
<h:commandButton action="/index.xhtml"> <e:set value="AVAILABLE" target="#{flash.mode}"/> </h:commandButton>
Und die zugehörige Bean:
@Component @Scope(Scopes.VIEW_SCOPE) public class Dashboard { @FlashParam private TransactionQueryMode mode = TransactionQueryMode.CHRONOLOGICAL; ... }
Erklärung: Die Annotation @FlashParam injiziert den Parameter "mode", der zuvor in den Flash geschrieben wurde.
Hinweis: Wie bei RequestParam oder ScopeValue werden auch hier Faces-Converter verwendet, um Datentypen zu konvertieren.