JSF Dependency-Injection funktioniert offenbar nicht - warum?

Txxxxs

Mitglied
Hallo,

ich habe zwei ManagedBeans und möchte eine Variable, die in der ersten ManagedBean erstellt/belegt wurde, in der zweiten nutzen - im Folgenden die hoffentlich entscheidenden Quelltextausschnitte:
Java:
@ManagedBean
@SessionScoped
public class Index {
	private PersistenceFacade facade = null;

	public Index() {
		if (facade == null) {
			facade = PersistenceFacadeFactory.getFactory().createFacade();
		}
	}
...
}
Java:
@ManagedBean
@ViewScoped
public class ArtikelAnlegen {
/*	@ManagedProperty(value = "#{index.facade}")
	private PersistenceFacade facade;*/
	@ManagedProperty(value = "#{index}")
	private Index index;
	private Artikel artikel;

	public ArtikelAnlegen() {
		/*artikel = facade.createArtikel();*/
		artikel = index.getFacade().createArtikel();
	}

/*	public void setFacade(PersistenceFacade facade) {
		this.facade = facade;
	}*/
	public void setIndex(Index index) {
		this.index = index;
	}
...
}

Ich habe mir viele Tutorials dazu durchgelesen, auch in die Reference Documentation geschaut - meines Erachtens dürfte der Quelltext korrekt sein. Rufe ich die entsprechende XHTML-Seite auf, meldet Apache Tomcat eine Exception:
javax.servlet.ServletException: Klasse verkaufssystem.ps.ArtikelAnlegen kann nicht instanziiert werden.
Gemäß meinen unzähligen Debug-Versuchen liegt das wohl daran, dass facade bzw. index auf null steht, obwohl das Attribut in Klasse Index beim Aufruf der Seite korrekt initialisiert wird.

Kann mir jemand erklären, warum dieses Dependency-Injection nicht funktioniert?


Darüber hinaus würde es mich interessieren, ob man - siehe auskommentierte Quelltextteile oben - statt einer ganzen ManagedBean auch nur ein Attribut injizieren kann. Im obigen Fall bräuchte ich nur die facade, um Methoden aus der Serviceschicht aufrufen zu können. In sämtlichen Tutorials, die ich fand, geht es beim Thema Initialisieren über ManagedProperty stets nur um fixe Werte oder ganze ManagedBeans, nicht aber um einzelne Eigenschaften anderer Beans.
 
Ich habe den Quelltext soeben abgeändert und die Zuweisung im Konstruktor auskommentiert/geändert:
Java:
	public ArtikelAnlegen() {
		artikel = new Artikel();
		//artikel = index.getFacade().createArtikel();
	}
Damit läuft die Seite fehlerfrei und ich konnte weiter als zuvor debuggen - dabei fand ich heraus, dass die Dependency-Injection offenbar doch funktioniert, der Wert über die ManagedProperty gesetzt wird, aber erst nach dem Konstruktor!
Warum geschieht sowas nicht zu Beginn des Konstruktoraufrufs?

Ich beschäftige mich erst seit ein paar Tagen intensiv mit JSF (2.0) und bin momentan etwas ratlos - ich habe eine Schnittstelle/Fassade zur Datenbankzugriffsschicht und in dieser einige Methoden definiert, ich benötige also die Fassade aus der Session/ManagedBean, die diese holt, um darüber die Methoden aufzurufen. Angenommen, ich möchte einen Artikel bearbeiten, dann würde ich über die entsprechende Methode ein Objekt vom Typ Artikel bekommen, aber damit das in JSF rechtzeitig (d.h. bei Aufruf der artikelBearbeiten.xhtml) genutzt wird, müsste es ja im Konstruktor geholt werden, oder? Was aber mache ich, wenn mir zu dem Zeitpunkt die Fassade noch nicht zur Verfügung steht? 🙁
 
Es gibt folgende Annotation

Java:
@PostConstruct
public void postCreateArticle() {
artikel = index.getFacade().createArtikel();
}

damit kannst du ggf. Werte erstellen, die vor dem Konstruktor bereit stehen sollen.

Gruß
 
Zuletzt bearbeitet:
Hi,

oh, da kann ich vieleicht aushelfen:

Die Dependency Injection findet erst statt, nachdem die Objekte erzeugt wurden, also nach dem Konstruktoraufruf.
Da Managed Beans usw POJOs sind, wäre das ja auch gar nicht anders möglich, denn es gibt ja keinen Parentalkonstruktor, in dem sowas passieren könnte.

bei EJBs z.B. kann man statt dessen eine Methode mit @javax.ejb.init annotieren, und diese dann wie einen Konstuktor verwenden. Ich vermute mal, das läuft bei ManagedBeans ähnlich, google mal nach "bean instantiation annotations" oder so, würd mich auch interessieren

Gruß Andreas
 
Danke für eure Antworten!

Ich habe es mit @PostConstruct getestet und es scheint zu funktionieren. 🙂
Die einzige Unsicherheit, die ich noch habe, ist, nicht ganz zu verstehen, wie man mit Exceptions aus darunterliegenden Schichten hinsichtlich der Oberfläche umgeht - wenn es dort zu Fehlern kommt, sollte der Benutzer des Systems ja eine Information darüber bekommen. Aber mal sehen, das werde ich schon noch in Erfahrung bringen, gehört ja auch nicht zum Thema hier.
 

Zurück
Oben