CommandLink --- ActionMethode wird nicht aufgerufen

Hi!

Mich quält etwas. :slight_smile: Hier erstmal der Rahmen: Tomcat 8.0.41, JSF2.2, Java1.8.

Was mache ich:
Ich breche Daten in Details auf. So lasse ich mir in einer bundeslaender.xhtml eine DataTable mit Bundesländern anzeigen. Jede Zeile enthält einen CommandLink, welcher eine Methode in einer ManagedBean aufruft. Diese Methode beschafft die Städte des aktuellen Bundeslandes und geht per NavigationRule zur staedte.xhtml, in der eine DataTable mit den Städten angezeigt wird. Jede dieser Zeilen hat wieder einen ActionLink … … strassen.xhtml …

Es gibt nur eine ManagedBean. Diese ist im RequestScope.

Das Problem:
Der ActionLink in der staedte.xhtml funktioniert nicht. Die ActionMethode hinter dem ActionLink wird einfach nicht aufgerufen. Die staedte.xhtml wird, nach einem Click auf den ActionLink, einfach ohne Daten wieder angezeigt. Keine Exception oder sonstige Message, nicht im Log und nicht im StdOut. Wenn ich in NetBeans in der staedte.xhtml ein „Navigate to declaration“ mache, dann springt er mir in die Methode. So 100%ig falsch sein kann das nicht oder gibt es hier einen JsfBug?

Hätte bitte jemand von euch den einen oder anderen Tip für mich, wie ich das Problem umzingeln und lösen könnte?

Danke!

Daniel

Hi Daniel,

hast du Code für uns? (Aus der XHTML und der entsprechenden Bean)?

Das würde es einfacher machen.

Gruß
Tim

Der Code ist eigentlich ganz langweilig. Die Methode zuDenStrassen(Stadt stadt) wird leider nicht aufgerufen.

staedte.xhtml

[code]…
<h:form>
<h:dataTable value="#{adressenBean.staedteList}" var=“item”>
<h:column>
<f:facet name=“header”>Stadt</f:facet>


<h:outputText value="#{item.stadt}"></h:outputText>

</h:column>
	<h:column>
		<h:commandLink action="#{adressenBean.zuDenStrassen(item)}">Strassen</h:commandLink>
	</h:column>
</h:dataTable>

</h:form>
…[/code]

AdressBean.java

[code]…
public String zuDenStaedten(Bundesland bundesland) throws Exception{
AdressenDAO dao = new AdressenDAO();
staedteList = dao.getStaedte4Bundesland(bundesland);

return "staedte";

}

public String zuDenStrassen(Stadt stadt) throws Exception{
AdressenDAO dao = new AdressenDAO();
strassenList = dao.getStrassen4Stadt(stadt);

return "strassen";

}
…[/code]

Der Ärger scheint wohl darin zu liegen, dass der CommandLink bei der staedte.xhtml in der DataTable liegt. Alles genauso, wie in der bundeslaender.xhtml, aber in der staedte.xhtml funktioniert es einfach nicht.

Auch eine einfache TestAction ohne Parameter wird aus der DataTable nicht aufgerufen

... <h:column> <h:commandLink action="#{adressenBean.testAction()}">Strassen</h:commandLink> </h:column> ...

Wenn der CommandLink unter der Tabelle steht, dann passt es und ein Click ruft die ActionMethod auf, aber das ist ja nicht Zweck der Sache.

... </h:dataTable> <h:commandLink action="#{adressenBean.testAction()}">Strassen</h:commandLink> </h:form> ...

Also hast du den Fall mit Städten der funktioniert, und 1:1 den selben Code der mit Strassen nicht funktioniert? Und du bist sicher, dass es da keinen Unterschied gibt?

“Wird nicht aufgerufen” bedeutet auch, dass du mit einem Debugger siehst, dass die Methode nicht aufgerufen wird? Nicht, dass irgendetwas einen Fehler in deinem DAO produziert, der ungünstig verschluckt wird

Es ist wirklich 1:1 gleich. Die ActionMethoden sind genau diese einfachen 3zeiler. Ich habe die Views so zusammengeschnitten, dass nur noch die CommandLinks der DataTable angezeigt werden und alles andere umherum habe ich entfernt.

Ich habe das ganze in einer Miniaturversion nachprogrammiert. Da läuft es.

Experimentell habe ich den Scope der ManagedBean geändert und es kommt etwas sehr merkwürdiges raus:
RequestScoped:
Da was ich oben geschrieben habe
ViewScoped:
Schon die Methode zuDenStaedten() wird nicht aufgerufen. Ohne eine Meldung oder sonst einen Pieps. Es wird einfach nicht gemacht.
SessionScoped
Die Methoden lauffen und machen Ihren Job, aber die Properties sollen nicht in der Session gehalten werden.

Auf der Grundlage mit dem SessionScope kann ich schon etwas funktionierendes zusammenbasteln, aber vertrauenserweckend ist das ganze nicht. Bei JSF2.2 ist das jetzt schon der 3te Fall bei dem aus irgendwelchen Gründen der LiveCycle komplett versagt oder die Methoden in der falschen Reihenfolge aufgerufen werden.

Ich werde da einfach nicht schlau draus.

Das wird schon einen Grund haben. Ich war bisher auch schon öfters der Überzeugung, dass sich JSF falsch verhält - im Endeffekt lag es dann doch immer an mir.

Es ist wahrscheinlich nicht möglich, mehr Code oder das Projekt zu sharen, oder?

Mehr Code kann ich leider nicht herzeigen. Sonst gibt es eine auf den Deckel wenns rauskommt.

Das hier beschäftigt mich immer noch: Facelets --- LifecycleRätsel . Ich nenne es Komplettversagen des LiveCycles. Den vollständigen Quellcode habe ich vorhin nochmal hochgeladen, da er bei der Forenmodernisierung scheinbar abhandengekommen ist. Wenn Du Geduld und Zeit hast, dann spiel die Szene mal durch. Ich werde da nicht schlau draus und eigentlich darf sowas nicht passieren.

Der 3te Fall sieht so aus: Ein paar Properties der CustomerInfo werden per h:outputText angezeigt. In der View gibt es ein paar commandButtons. Sobald die Deklaration der customerInfo in der Klasse steht, dann zerhaut es den Lifecycle so, dass die View erst gerendert wird und erst danach die ActionMethods aufgerufen werden. Die CustomerInfo könnte ich einmalig im PostConstruct holen und müßte nicht im Getter xmal die DB heizen, aber leider klappt es nicht und ich werde auch nicht schlau draus. In einem Miniprojekt ist das Problem leider auch nicht nachvollziehbar.

[code]…
private Customer customerInfo;

public CustomerInfo getCustomerInfo() {
CustomerDAO dao = new CustomerDAO();
Lieferant cI = dao.findCustomerInfo(sessionManagedBean.getCustomerNo());

return cI;

}
[/code]

Hast Du es mal mit einem Ajax-Event ausprobiert? Was sagt der Browser? Wird überhaupt ein Event ausgelöst?

Ich habe mich gerade versucht schlau zu machen, aber bin nicht draufgekommen, wie mir ein Ajax-Event hier anwenden könnte. Hättest Du bitte einen Tip oder ein Codestückchen für mich?

http://www.jsftoolbox.com/documentation/help/12-TagReference/core/f_ajax.html
Hier wird f:ajax in einem CommandButton genutzt, sollte ähnlich auch mit CommandLink klappen.

Zu dem Problem kann ich konkret nichts sagen:

Das ist mir gerade aufgefallen: Du hältst State in einer Request Scoped Bean? Das macht ziemlich sicher Probleme, da diese nur exakt für einen HTTP Request lebt. Was tust du mit dieser Liste?

Diese Liste soll nur ein einziges mal ausgegeben werden. Aber da hast Du mich auf eine Idee gebracht und jetzt weiß ich woran es liegt. Ich poste später den Code dazu.

Danke. :slight_smile: Das ist ein interessantes Thema, aber hierbei hätte es mit leider nicht geholfen.

Hier der Code: MasterDetail.zip (2,8 MB)

Wenigstens ist der Übeltäter erkannt. :slight_smile: M.E. nicht ganz so offensichtlich, denn eigentlich hätte man erwarten können, das sowas funktioniert. Daß keine Fehlermeldung kommt und JSF nur mit Arbeitsverweigerung reagiert macht das ganze zusätzlich noch spannender.

Weil es kaum anders geht, muß man teilweise grössere Datenmengen in der Session halten. Es werden wohl so bis 5000 Objekte mit bis zu 15 Properties und durchschnittlich 50 Sessions sein. Kein Problem bei den heutigen Rechnern oder hat jemand von euch Bedenken?

Kannst du noch kurz erörtern, was du geändert hast? Die Request Scoped Bean gegen eine ViewScoped getauscht? Wieso hättest du erwartet, dass es mit Request Scope funktioniert? Jede API Dokumentation und jede Beschreibung des Lifecycles wird da sehr deutlich.

Ich habe alle 3 Scopes auf die Bean angewendet und mich jedes mal darüber gewundert, was da passiert.

So deutlich sind die Dokus, da auch nicht, denn nach denen dürfte der CommandLink in der bundeslaender.xthml, im RequestScope, auch nicht funktionieren. Response ist angekommen und Request abgehandelt.

Ich verstehe deine Verwirrung schon, ich war am Anfang auch an der Stelle. JSF verspricht eine Einfachheit, die es natürlich nicht halten kann. Man muss sich bei der Arbeit damit immer bewusst sein, was unter der Haube passiert, ähnlich wie bei JPA. Ansonsten kommt man mit dem Lifecycle, Bean Scopes, JSF vs. CDI Annotations usw. schnell durcheinander und ist frustriert, dass es sich nicht so verhält wie man angenommen hat.

JSF ist nicht “out of the box” benutzbar, und “Learning By Doing” funktioniert nur begrenzt

Ich empfehle dir auf jeden Fall mal diesen Artikel in Ruhe querzulesen, BalusC ist eine Instanz auf dem Gebiet und schafft es immer die Sachverhalte simpel herunterzubrechen:

Mein Beispielprogramm zeigt im RequestScope, dass das nicht stimmt, denn entweder

  • darf die Bean von der bundeslaenderList nichts mehr wissen, während der CommandLink „zuDenStädten“ geklickt wird
    oder auf der anderen Seite
  • hat die Bean von der die staedteList noch zu kennen, während der CommandLink „zuDenStrassen“ geklickt wird

Irgendetwas passt da nicht. Aus Benutzersicht verweitert genau hier JSF die Arbeit. Es passiert einfach mal nichts.