# JSF Bean-Property mit Parameter aufrufen



## Marsman (21. Sep 2007)

Hallo Ihr!

Wie kann ich eine Bean-Property mit Parameter aufrufen bzw. an die Bean einen Parameter übergeben und das Ergebnis anzeigen?

Es geht letztlich darum, dass ich in einer JSF den Inhalt eines bestimmten Datensatzes der Datenbank anzeigen möchte. Leider schaffe ich es aber nicht, die Id den Satzes an die Bean zu übergeben. Ich habe auf Basis von diesem 
Beispiel
folgendes programmiet. Vielleicht geht es auch einfacher. Wäre für jeden Tipp dankbar.


```
<h:outputText value="#{ingredientBean.ingredient.price}€">
	<f:param name="paramName" value="1"/>
</h:outputText>
```


```
<managed-bean>
    <description>Dao</description>
    <managed-bean-name>ingredientBean</managed-bean-name>
    <managed-bean-class>com.cbw.pizza.IngredientBean</managed-bean-class>
    <managed-bean-scope>request</managed-bean-scope>
    <managed-property>
    	<property-name>
    	id</property-name>
    	<property-class>
    	java.lang.String</property-class>
    	<value>
    	#{param.paramName}</value>
    </managed-property>
  </managed-bean>
```


```
public class IngredientBean {

	private Ingredient ingredient;
	
	private String id;

	public IngredientBean() {
		FacesContext fc = FacesContext.getCurrentInstance();
		Map requestParams = fc.getExternalContext().getRequestParameterMap();
		setId((String) requestParams.get("tid"));
	}

	private IngredientDaoInt getDao() {
		try {
			InitialContext ctx = new InitialContext();
			return (IngredientDaoInt) ctx.lookup("IngredientDao/local");
		} catch (Exception e) {
			e.printStackTrace();
			throw new RuntimeException("couldn't lookup Dao", e);
		}
	}

	public String persist() {
		getDao().persist(ingredient);
		return "persisted";
	}

	public DataModel getIngredients() {
		return (new ListDataModel(getDao().findIngredients()));
	}

	public Ingredient getIngredient(String id) {
		setId(id);
		return ingredient;
	}

	public Ingredient getIngredient() {
		return ingredient;
	}

	public void setIngredient(Ingredient ingredient) {
		this.ingredient = ingredient;
	}

	public String delete() {
		getDao().delete(ingredient);
		return "removed";
	}

	public String update() {
		getDao().update(ingredient);
		return "updated";
	}

	public String getId() {
		return id;
	}

	public void setId(String id) {
		System.out.println("setId:" + id);
		this.id = id;
		if (id != null) {
			ingredient = getDao().findIngredient(id);
		} else {
			ingredient = new Ingredient();
		}
	}

}
```

Der System.out gibt bei setId() übrigens null aus. Also kommt der Parameter irgendwie nicht in der Methode an.

Titus


----------



## maki (21. Sep 2007)

Deine Managed Bean sollte die id des Datensatzes, den sie (re)Präsentiert, doch kennen, oder etwa nicht?

Wenn du Listen darstellst, ist es natürlich anders 

<h:commandButton .....
						   					<faram value="#{listItem.object}"/>

</h:commandButton>

Das geht bei uns so, ohne das name attribut, wir benutzen aber auch keine managed properties.


----------



## SnooP (21. Sep 2007)

Also... was willst du denn wirklich genau machen?  ... das mit der Parameterübergabe find ich persönlich nicht so wirklich JSF-like - dort hat man ja aber auch noch ganz andere Möglichkeiten, wie etwa tabellen per binding an den controller binden oder tomahawk t:updateActionListener verwenden etc...

ich glaube auch nicht, dass den managed-propertys das irgendwie juckt, wenn du an einen outputText einen Parameter bindest... irgendwo muss ja per form was übertragen werden - aber parameter im output werden imho nirgends hin übertragen.

Meintest du evtl. nen outputLink?


----------



## Marsman (21. Sep 2007)

SnooP hat gesagt.:
			
		

> Also... was willst du denn wirklich genau machen?



Es geht darum, dass ich Werte, die in einer Datenbanktabelle gespeichert sind, auf meiner JSF anzeigen möchte. In unserem Projekt wollen wir einen kleinen Bestell-Service programmieren. Im oberen Bereich sollen die Zutaten mit den Preisen zu sehen sein. Dabei möchte ich derzeit noch kein datatable verwenden. Die möglichen Zutaten sind fest codiert. Wie man an meiner IngredientBean sehen kann, wird mit setId() auch der Datensatz gelesen und den Preis wollte ich dann mit getPrice auslesen. Wie ich das nun aber in JSF bewerkstellige, ist mir nicht klar. (Oder vielleicht doch lieber datatable? Aber wie kann ich die Zellen der datatable horizontal anordnen?)


Titus


----------



## SnooP (21. Sep 2007)

Mit der Anforderung verstehe ich noch viel weniger, was der Parameter in dem outputText soll - aber gut  ...

ich kann ja mal beschreiben, wie man das machen sollte...
1. dataTable nehmen - warum sollte man das nicht?
2. In der dataTable auf der JSP definierst du immer eine darzustellende Zeile, der value zeigt auf eine Liste mit den darzustellenden Objekten, die man sich über ein entsprechendes DAO holt.
3. In dem dataTable-Tag stellst du dann über <h:column> Tags die einzelnen Spalten da - de Facto also die Exemplare der Zellen einer aktuellen Zeile (die horizontale Anordnung wenn du so willst).
4. Auf die values der akt. Zeile greifst du mit dem unter var="row" zu...

kleines Beispiel?:


```
<h:dataTable id="data" style="width: 100%;" var="person" value="#{controller.personen}">
							<h:column>
								<f:facet name="header">
									<h:outputText value="Userid" />
								</f:facet>
								<h:outputText value="#{person.userid}">

								</h:outputText>
							</h:column>
							<h:column>
								<f:facet name="header">
									<h:outputText value="Vorname" />
								</f:facet>
								<h:outputText value="#{person.vorname}" />
							</h:column>
							<h:column>
								<f:facet name="header">
									<h:outputText value="Nachname" />
								</f:facet>
								<h:outputText value="#{person.nachname}" />
							</h:column>
							
</h:dataTable>
```


----------



## Marsman (21. Sep 2007)

SnooP hat gesagt.:
			
		

> Mit der Anforderung verstehe ich noch viel weniger, was der Parameter in dem outputText soll - aber gut  ... ich kann ja mal beschreiben, wie man das machen sollte...



Das mit der datatable ist mir soweit klar. Trotzdem muss es doch aber irgendwie gehen, aus der JSF eine Bean-Methode (Property) aufzurufen und ihre dabei Parameter zu übergeben? Oder geht das wirklich immer nur in diesem Request/Response-Spiel und nur mit der Bean, die der JSF zugeordnet ist?

PS: Ich würde JSF auch lieber von Grund auf lernen. Leider habe ich weder ein Buch zur Hand, noch hat unser Dozent davon die geringste Peilung. Darüber hinaus haben wir nur noch zwei Tage Zeit. Deswegen wollte ich das so einfach wie möglich machen.


Titus


----------



## maki (21. Sep 2007)

Marsman,

vielleciht hilt dir das ein wenig:

actionListener werden aufgerufen, bevor die action aufgerufen wird.

d.h., über den actionListener den wert setzen und auswerten, in über action dann die nächste seite aufrufen.
Die Action steht in der navig( zB "persisted" ), der actionlistener ist eine methode in deiner managedbean.

jsp:
<h:commandButton id="display"
	value="drück mich" 
	action="display"
	actionListener="#{ManagedBean.actionlistenerName}" 
	<faram value="wert"/>
</h:commandButton>

wobei "display" in  deiner navig steht(nächste seite), "ManagedBean" der name deiner Bean ist und  "actionlistenerName" der name der Methode in der Bean, die aufgerufen werden soll.


managed bean:

```
public void actionlistenerName(ActionEvent event) {

		List children = event.getComponent().getChildren();

		Object value = ((UIParameter) children.get(0)).getValue();

                // ersetze ValueTypemit dem typen des parameters, zB. String, etc. pp.
                ValueType vt= (ValueType) value;

                // und nun mach was damit.. zB. den Datensatz in die ManagedBean laden
                ...
	}
```

Wie gesagt, die managed property in derwürde ich weglassen (?).

Facestrace kann ich nur empfehlen: http://facestrace.sourceforge.net/

Im footer die taglib einbinden: 

```
<%@ taglib uri="http://sourceforge.net/projects/facestrace" prefix="ft"%>
```

und das tag setzen:

```
<ft:trace />
```

Ohne facestrace dauert die fehlersuche bedeutend länger und ist sehr schnell + einfach einzusetzen.

es würde sich wirklich lohnen, allen komponeneten ids zuzuweisen.


----------



## Marsman (21. Sep 2007)

hmm, ich fürchte, wir reden irgendwie an einander vorbei. Vielleicht habe ich noch nicht genau genug beschrieben, was mein Problem ist. Es ist nicht so, dass ich die Daten der zu Grund liegenden ManagedBean bzw. dessen Dao nicht angezeigt bekommen. Vielmehr möchte ich auf der SELBEN Seite Daten ANDERER Beans bzw. Datenbanktabellen anzeigen.  Und zwar bestimmte Datensätze, deren Primärschlüssel in der Seite festlegt ist. :? 

Ich habe schon der Verdacht, dass mein Weg dem Prinzip von JSF widerspricht. Kann es sein, dass man je JSF-Seite immer nur eine einzige Mananged-Bean hat?? Und diese für die Beschaffung ALLER auf der Seite angezeigten Daten zuständig ist. Und zwar auch dann, wenn diese aus mehreren Datenbanktabellen kommen? ???:L 

Titus


----------



## maki (21. Sep 2007)

JSF ist anfangs sehr komplex, es reicht leider nicht nur einen krzen Überblick darüber zu haben, musste ich leider auch schon feststellen.

Du kannst natürlich beliebig viele Managedbeans pro seite verwenden, kein Problem.. oder aber, deine Managedbean kümmert sich auch um die Daten aus den anderen Tabellen... oder, du hast mehrere Managedbeans (aber nur eine pro seite) und eine Managedbean hat als Eigenschaft weitere Managedbeans (komposition, mach ich gerade in meinem Projekt)

Mal was anderes: Deine Managedbean hat ein DAO??? Dachte, du würdest EJBs einsetzen?


----------



## Marsman (21. Sep 2007)

maki hat gesagt.:
			
		

> Mal was anderes: Deine Managedbean hat ein DAO??? Dachte, du würdest EJBs einsetzen?




Unser Projekt basiert auf diesem Tutorial. Die verwenden dabei 3 Klassen und 1 Interface. Sie haben dort zwischen ManagedBean und Entity-Bean eine DAO-Bean geschaltet. Ob das nun EJB ist oder nicht, war mir eigentlich egal. Ich fand die Aufteilung recht schlüssig. Wenn die ManagedBean der Controller ist, gehört die DAO-Bean wohl zur Persistenz-Schicht.


Titus


----------



## maki (21. Sep 2007)

> Sie haben dort zwischen ManagedBean und Entity-Bean eine DAO-Bean geschaltet.



Sieh es mal so, um beim Tutorial zu bleiben:

Die ManagedBean(TodoBean), welche eine Entity Bean referenziert, sitzt im Serlvet Container(Tomcat) , 
und benutzt das Interface(TodoDaoInt), welches dann auf die EJB zugreift, die im EJB Container (JBoss) sitzt. 

Dabei wandert die Entity Bean vom EJB Container zum Serlvet Container,
 beim speichern in die andere Richtung.
Die EJB kümmert sich um die Persistenz, d.h. die Persistenz findet ausschlieslich im EJB Container statt.
Durch die Ordnerstruktur wird die Trennung deutlich: http://www.redhat.com/docs/manuals/jboss/jboss-eap-4.2/doc/Getting_Started/Configuration_Files.html

Ich finde die Namensgebung in der Webschicht etwas missglückt (getDao(), etc.).
Das hindert den Code zwar nicht am laufen, kann aber verwirren.

Jedenfalls, deine ManagedBean hat eine Referenz auf ein Entity Objekt, die id und stellt Methoden dazu bereit.
Du könntest ja in IngredientsBean eine andere ManagedBean in referenzieren und so deren funktionen nutzen.


----------



## Marsman (22. Sep 2007)

maki hat gesagt.:
			
		

> Die ManagedBean(TodoBean), welche eine Entity Bean referenziert, sitzt im Serlvet Container(Tomcat) ,
> und benutzt das Interface(TodoDaoInt), welches dann auf die EJB zugreift, die im EJB Container (JBoss) sitzt.



Ja, das war mir aber auch schon klar. Die Trennung zwischen den beiden Containern haben wir hier lange durchgekaut.




> Ich finde die Namensgebung in der Webschicht etwas missglückt (getDao(), etc.).
> Das hindert den Code zwar nicht am laufen, kann aber verwirren.



Wie würdest Du es denn nennen?



> Du könntest ja in IngredientsBean eine andere ManagedBean in referenzieren und so deren funktionen nutzen.



So werde ich es wohl auch machen. Bzw. umgekehrt: Meine OrderBean könnte auf die IngredientBean zugreifen und sich darüber die Preise der Zutaten holen.  :idea: 

Titus


----------



## maki (22. Sep 2007)

> Ja, das war mir aber auch schon klar. Die Trennung zwischen den beiden Containern haben wir hier lange durchgekaut.


Dann dürfte dir ja klar sein, das die Aussage 


> Sie haben dort zwischen ManagedBean und Entity-Bean eine DAO-Bean geschaltet.


so keinen Sinn ergibt 



> Wie würdest Du es denn nennen?


Alles ausser DAO *g*

Du benutzt ja kein DAO, sondern eine EJB.

Die eigentlichen DAOs gibt es mit dem Persitenzmanager sowieso nur im "Hintergrund", und DAOs haben in der Presentationsschicht nichts verloren 

Siehe dazu das DAO Muster.

Wie gesagt, schade das man etwas so bekanntes (DAO) als Begriff benutzt, wenn in Wirklichkeit etwas ganz anderes gemeint ist (EJB Remote Interface).
Schon das die EJB das DAO im Namen hat ist imho daneben.
Dadurch kommt es zu unötigen Miss(t)verständnissen, denn wenn du DAO sagst, meinst du eigentlich EJB 




> So werde ich es wohl auch machen. Bzw. umgekehrt: Meine OrderBean könnte auf die IngredientBean zugreifen und sich darüber die Preise der Zutaten holen.


Na also 


Gruß,

maki


----------

