Globale Navigation mit Menus in TemplatePages

In meinem aktuellen Projekt trat das Problem auf, dass eine Navigation über eine Menustruktur ermöglicht werden soll, die in allen Seiten der Anwendung zugänglich sein soll. Leider ist die Anwendung so groß, dass die UseCases gruppiert wurden und in eigene TaskFlows ausgelagert werden müssen (das entspricht wohl auch der ‘Best Practice’).
Leider stellen wir fest, dass innerhalb eines Taskflow (bounded) kein Zugriff auf Regeln des aufrufenden Taskflow (i.a. adfc-config.xml) möglich sind, da der Taskflow in sich abgeschlossen ist. Alle Seiten werden von einer TemplatePage abgeleitet, die das Menu für die globale Navigation als Facette in jede Seite einbaut. Damit braucht die Navigation nur einmal in dem Menufragment verdrahtet zu werden.
Nach der Suche nach Lösungen gab es aus meiner Sicht nur zwei Möglichkeiten:

  1. Eine Seite in der adfc-config.xml die das Menu für die globale Navigation enthält, die einzelnen Taskflows, die die Usecases darstellen werden immer in dieser Seite als Region eingebunden
  2. Die Navigation über das Menu muss in allen Seiten zugänglich gemacht werden, auch wenn eine Seite in einem Taskflow (gegebenenfalls geschachtelt) eingebaut ist.

Lösung 1 habe ich nicht weiter untersucht, da mir die Erfahrung im Umgang mit Regions fehlt. Lösung 2 sollte eigentlich die einfachere sein. Wir sind doch wohl nicht die einzigen Anwender mit der Anforderung einer global zugreifbarer Navigation über eine Menuleiste, die in einem Fragment eingebaut ist.

Leider hat die Suche nach einer Lösung wie in 2. beschrieben kein Resultat hervorgebracht. Nach einigem Probieren bin ich auf die im Folgendem beschriebene Lösung gekommen:

Jeder Menueintrag wird an eine Bean im Session Scope gebunden. Die Bean merkt sich nur welcher Menueintrag gewählt wurde (über einen an die Bean gebundenen ActionLisener pro Menueintrag). Weiterhin enthält die Bean eine Methode, die die Kennung des Menueintrag der als letzter gewählt wurde zurückliefert. Die Kennung dient dann später als Sprungziel.

Jeder Taskflow enthält eine Wildcard-Regel, die immer einen festen Outcome (z.B. fertigMenuauswahl) liefert, der auch genau über diesen Namen angesprungen werden kann.

Wildcrd Regel zur Menunavigation

Wildcard Regel zur Menunavigation

Bei der Auswahl eines Menueintrag muss jetzt nur nuch als Action der oben definierte Outcome geliefert werden (hier fertigMenuauswahl). Als XML sieht dies dann so aus:

<control-flow-rule>
<from-activity-id>*</from-activity-id>
<control-flow-case>
<from-outcome>fertigMenuauswahl</from-outcome>
<to-activity-id>menuauswahl</to-activity-id>
</control-flow-case>
</control-flow-rule>

Ein Menueintrag stellt sich im Propertyinspector so dar:

Propertyinspector eines Meuneintrag

Propertyinspector eines Meuneintrag

oder im Code:

<af:menuBar>
<af:menu text=”Stammdaten”>
<af:commandMenuItem text=”Standardsätze” actionListener=”#{MenuBean.menuauswahlStandardsaetze}”
action=”fertigMenuauswahl”/>
<af:commandMenuItem text=”Quellen”
actionListener=”#{MenuBean.menuauswahlQuellen}”
action=”fertigMenuauswahl”/> …
Der Code in der Bean ist:

public class MenuBean
{
String mMenuauswahl = null;

public void menuauswahlStandardsaetze(ActionEvent actionEvent)
{
    mMenuauswahl = "menustandardsaetze";
}
public String handleMenuAuswahl()
{
    return mMenuauswahl;
}
}

Als letztes Glied in der Kette fehl nur noch die eigentliche Durchführung der Navigation im unbounded Taskflow (adfc-config.xml). Dies geschieht wieder durch eine Wildcard-Regel, die mit der ID, die der Menuauswahl geliefert wird (fertigMenuauswahl) eine Methode in der Bean anspringt, die als Ergebnis das zuletzt ausgewählte Menu zurückliefert.

Ausschnitt der adfc-config.xml

Ausschnitt der adfc-config.xml

Der Methodencall wird so verdrahtet:

Propertyinspector handleMenuauswahl

Propertyinspector handleMenuauswahl

Damit können globale Navigationen über das Menu in allen Seiten, auch solchen in Taskflows, die auch noch geschachtelt sein können, durchgeführt werden.

Es ist allerdings noch zu berücksichtigen, dass in der Bean gegebenenfalls noch ein Rollback durchzuführen ist, damit in einem Taskflow gemachte Änderungen zurückgenommen werden, falls sie nicht expliziert gespeichert wurden.