# JSF 2.0 dataTables



## azenth (22. Jan 2013)

Hallo Java-Community,

ich habe ein Problem mit dataTables. Eventuell ist es auch für einen totalen Anfänger auch einfach noch zu kompleziert.

Mein Problem:

Ich bekomme von meinem Controller die Listen zurück, einmal eine UserListe und einmal eine HostListe.

Wenn ich das wie folgt mache, dann funktioniert das sehr gut.


```
<h1>Host Groups</h1>
<h:dataTable value="#{userControler.ugroups}" var="ugrp">
   <h:column>
      <h:outputText value="#{ugrp.name}"/>
   </h:column>
</h:dataTable>
<h1>Host Groups</h1>
<h:dataTable value="#{userControler.hgroups}" var="hgrp">
   <h:column>
      <h:outputText value="#{hgrp.name}"/>
   </h:column>
</h:dataTable>
```

Leider sieht das ganze nicht gut aus. Daher wollte ich das ganze tabellarisch aufbauen.

Das Problem nun ist, dass ich es einfach nicht hinbekomme. In diesem Beispiel kann ein User Mitglied mehrerer UserGroups (List) sein. Und eine UserGroup kann mehreren HostGroups (auch eine List) zu geordnet sein. Und eine HostGroup kann mehrere Hosts haben (auch eine List). 

Ich habe gedacht das es ungefähr so gehen müsste, aber irgendwie drehe ich mich im Kreis und nichts funktioniert.


```
<
h:dataTable value="#{userControler.ugroups}" var="ugrp" border="1"
	 		styleClass="order-tabel" 
	 		headerClass="order-table-header" 
	 		rowClasses="order-table-odd-row,order-table-even-row"
>
   <h:column>
      <f:facet name="header">User Groups</f:facet>
      <h:outputText value="#{ugrp.name}"/>
   </h:column>
   <h:column>
      <f:facet name="header">Host Groups</f:facet>
      <h:outputText value="#{hgrp.name}"/>					
   </h:column>
   <h:column>
      <f:facet name="header">Hosts</f:facet>
      <h:outputText value="#{host.name}"/>					
   </h:column>
</h:dataTable>
```

Hat jemand einen Tipp für mich, wie ich das Problem richtiger angehen kann? Ich finde grade von selbst keine Lösung.

Gruß


----------



## sence (22. Jan 2013)

Dein Problem ist recht einfach zu erklären 
Schau dir mal dein zuerst gepostetes Beispiel an, dann dein zweites.


Wenn du es jetzt noch nicht siehst, hier die Auflösung 
Beispiel eins:

```
<h:dataTable value="#{userControler.ugroups}" var="ugrp">
.......
.......

<h:dataTable value="#{userControler.hgroups}" var="hgrp">
.....
....
```
Das Funktioniert, da jedes Element in deiner Liste als Variablen Name ugrp bzw. hgrp  in der 2. Datatable referenziert wird.

Bei deinem 2. Beispiel, hast du nur folgendes stehen:

```
<h:dataTable value="#{userControler.ugroups}" var="ugrp"......
.....
```
hier, versucht du auch auf hgrp zuzugreifen, doch woher soll es herkommen? 

Die Lösung:
wenn du auf alle Elemente zugriff haben möchtest, muss die Liste mit dem höchsten "Parent" Objekt als Liste referenziert werden.
Die Unterelemente müssen dann in dem jeweiligen "Parent" Objekt erreichbar sein.

Beispiel:
Host
 ->HostGroup
     -> UserGroup

Wenn du jetzt die Liste mit List<Hosts> lst_host referenzierst kannst du wie folgt auf die Unterlemente zugreifen:


```
<h:dataTable value="#{userControler.hosts}" var="hosts" ....
<h:column>
      <f:facet name="header">User Groups</f:facet>
      <h:outputText value="#{hosts.hostgroup.ugrp.name}"/>
   </h:column>
   <h:column>
      <f:facet name="header">Host Groups</f:facet>
      <h:outputText value="#{hosts.hostgroup.name}"/>					
   </h:column>
   <h:column>
      <f:facet name="header">Hosts</f:facet>
      <h:outputText value="#{hosts.name}"/>					
   </h:column>
</h:dataTable>
```

zur Vollständigkeit halber:
es geht natürlich auch andersherum, vom niedrigsten Objekt zum höchsten, also:
ugrp.hgrp.hosts
oder wie ich es geschrieben habe (vom höchsten nach unten)
hosts.hgrp.ugrp

Grüße


----------



## AndiE (22. Jan 2013)

Das habe ich nicht richtig verstanden

Ich habe in einem Bean


```
@ManagedBean(name="schulen")
...
Schule[] Schullist= new Schule[8];
...
```

und habe dann im Facelet

[XML]
...
<hataTable  value="#{schulen.Schullist}" var="s">
...

<h:column>
#{s.Name}
</h:column>
...
[/XML]

Wenn ich Schule-Klasse-Schueler habe, dann würde  ich ( nur skizzenhaft) das so anlegen:


```
class Schueler{
...
private String name;
...
}

class Klasse
{
   private Schueler[] s= new Schueler[20];
}
...

@managedBean(name="schule")
public class Schule{
private Klasse[] Klassenliste= new Klasse[20];

}
```

anlegen. 

Wie geht das jetzt mit der Referenzierung? Oder geht das nur bei Listen. wie würde es da aussehen?


----------



## sence (22. Jan 2013)

jetzt kannst du, (bei deinem Aufbau)

auf die einzelnen Element wie folgt zugreifen:


```
<h:column>
#{s.Name} #{s.Klassenliste[0].s[0].name}
</h:column
```

auf die Schule-> dann auf das erste Objekt der Klassenliste [0] -> dann auf den ersten schüler  [0] -> auf den Namen -> .name
zugreifen.

Mit Referenzieren wollte ich ausdrücken, das aus einem Objekt, die anderen Objekte erreichbar sein müssen.
bzw mit der Referenzierung bei value="" war gemeint, dass man nur eine Liste angeben kann, die iteriert werden soll.

Kleine Anmerkung, variablen klein schreiben, Klassen Namen groß.


----------



## azenth (23. Jan 2013)

Hallo sense,

danke dir erstmal für den Tipp. Aber ich habe iregndwie noch ein Problem. 

Ich habe nun die dataTable entsprechend umgebaut. 


```
<h:dataTable value="#{userControler.groups}" var="grps" border="1"
	 		styleClass="order-tabel" 
	 		headerClass="order-table-header" 
	 		rowClasses="order-table-odd-row,order-table-even-row"
>
<h:column>
   <f:facet name="header">User Groups</f:facet>
   <h:outputText value="#{grps.name}"/>
</h:column>
<h:column>
   <f:facet name="header">Host Groups</f:facet>
   <h:outputText value="#{grps.hostgroup.name}"/>		 			
</h:column>
<h:column>
   <f:facet name="header">Hosts</f:facet>
   <h:outputText value="#{grps.hostgroup.host.name}"/>					
</h:column>
</h:dataTable>
```

Jedoch erhalte ich in meiner xhtml-Datei folgende Fehlermeldung: name cannot be resolved as a member of hostgroup

Kann es sein das ich beim referenzieren etwas falsch gemacht habe???

Die entsprechenden Java-Klassen schauen wie folgt aus:

UserGroup-Klasse


```
public class UserGroup implements Serializable {

	private static final long serialVersionUID = 1L;
	private transient Logger logger = Logger.getLogger(this.getClass().getName());

	private String name;
	private int db_id;
	
	List<HostGroup> groups = new ArrayList<HostGroup>();

	private DataSource datasource;

	public UserGroup() {
		super();
	}
	
	public UserGroup(int id, String name) {
		super();
		initHostGroups(this.name);
		this.name = name;
		this.db_id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getId() {
		return db_id;
	}

	public void setId(int id) {
		this.db_id = id;
	}
	
	public List<HostGroup> getHostgroup() {
		return groups;
	}

	public void setHostgroup(int id) {
		this.groups = groups;
	}
	
	public void initHostGroups(String ug) {
		
		Connection conn = null;
		Statement stmt = null;
		
		List<HostGroup> hostgroups = null;
		
		try {
			conn = datasource.getConnection();
			stmt = conn.createStatement();
		
		String groupsql = 	"SELECT H.hostgroup_name, H.hostgroup_id " +
   							"FROM vw_hostgroup H, vw_usergroup U, hostgroup_usergroup HG " +
							"WHERE U.usergroup_name = '" + ug + "' " +
							"AND U.usergroup_id = HG.usergroup_id " +
							"AND HG.hostgroup_id = H.hostgroup_id";
   				   			
		ResultSet rs_group = stmt.executeQuery(groupsql);
		while (rs_group.next()) {
			String name = rs_group.getString("hostgroup_name");
			int id = rs_group.getInt("hostgroup_id");
			HostGroup g = new HostGroup(id, name);

			logger.fine("Add group(s) to usergroup " + g);
			
			groups.add(g);
  		}
		} catch (SQLException e) {
			logger.log(Level.SEVERE, "SQL problem while getting data", e);
		} finally {
			try {
				stmt.close();
				conn.close();
			} catch (Exception e) {
				/* ignore */
			}
		}
	}
```

und


```
public class HostGroup implements Serializable{
	
	private static final long serialVersionUID = 1L;
	private transient Logger logger = Logger.getLogger(this.getClass().getName());

	private String name;
	private int db_id;

	private DataSource datasource;

	public HostGroup() {
		super();
	}

	public HostGroup(int id, String name) {
		super();
		this.name = name;
		this.db_id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getId() {
		return db_id;
	}

	public void setId(int id) {
		this.db_id = id;
	}
```

Ich hätte jetzt eigentlich erwartet, dass die getter und setter - - Methoden der Klasse Hostgroup nun verfügbar sind innerhalb der UserGroup und somit auch die Fehlermeldung nicht mehr erscheinen dürfte?

Habe ich etwas übersehen? Wie gesagt, dies ist eventuell ein schwerer Einstieg für einen Anfänger aber mit ein bisschen Hilfe beiße ich mich da durch.

Gruß


----------



## sence (23. Jan 2013)

du hast in UserGroup die Liste:

```
List<HostGroup> groups = new ArrayList<HostGroup>();
```

aber der Getter heißt:

```
public List<HostGroup> getHostgroup() {
		return groups;
	}
```

und dein Setter ist falsch:


```
public void setHostgroup(int id) { // Wieso ein int, als Setter für eine Liste, es müsste eine Liste sein, die der Setter übergeben bekommt
		this.groups = groups;
	}
```

du müsstest dann diekt den Getter #{grps.getHostgroup()}  verwenden.
nenne die Getter entsprechend der Variablen:
variable: groups
getter: getGroups() { ... };
setter: setGroups(...) { ...};

jetzt kannst du ganz normal wie folgt darauf zugreifen: #{grps.groups.weiteresObjekt.name}

Aber beachte: bei der Implementierung, greifst du nur auf die Liste zu, aber nicht auf einen der Listeneinträge.
das würde dann so aussehen: #{grps.groups[0].name}


----------



## JanHH (23. Jan 2013)

Irgendwie scheint mir das Problem eher grundsätzlich.. es liegt ein Datenmodell vor, welches aus mehreren geschachtelten Listen besteht (wobei ich es nicht ganz verstehe, aber egal). Die Frage ist ganz allgemein, wie ist das Modell aufgebaut, in welchen Beziehungen zueinander stehen die Daten, und wie kann man das vernünftig visualisieren. Ich bezweifle stark, sich das überhaupt vernünftig in einer einzigen dataTable darstellen lässt. Eher mit mehreren geschachtelten, oder einem Tree, oder einer Kombinattion aus Tree und Tabelle.. Überleg Dir doch erstmal was Du überhaupt genau willst bzw. was dein Datenmodell da für Notwendigkeiten mitbringt.


----------



## sence (23. Jan 2013)

Er will auf mehrere Objekte innerhalb der Objekte welche in der Liste sind zugreifen.
Soweit ist es okay, die Ausgabe der Unterlisten innerhalb einer Datatable ist nur mit weiteren Iterationen, wie z.B.

ui:repeat
möglich.

Wie die Tabelle schlussendlich aussehen soll, dass sollte man schon wissen, da gebe ich dir recht jan 
Wollte ihm aber erstmal zeigen, wie er von was auf was kommt, damit er dann selbst sich in zukunft andere Gestricke bauen kann ,)

greetz, so kunden meeting bye bye
JSFAtWork, JSF 2.0 und Apache MyFaces


----------



## JanHH (23. Jan 2013)

*kopfschüttel


```
<h:dataTable value="#{liste1}" var="v1">
   <h:column>
      <h:dataTable value="#{v1.liste2}" var="v2">
         <h:column>
            ...
         </h:column>
      </h:dataTable>
   </h:column>
</h:dataTable>
```


----------



## Nogothrim (23. Jan 2013)

für geschachtelte Tabellen würde sich auch die Primefaces Datatable mit RowExpansion sehr gut eignen:

PrimeFaces - ShowCase

In der RowExpansion kann man dann mit beliebigen weiteren Iterationskomponenten arbeiten.


----------



## sence (23. Jan 2013)

wieso schüttelst du mit dem kopf ?

ui:repeat ist eine Möglichkeit, verschachtelte Datatable's sind ebenfalls eine.
Bei Verwendung von ui:repeat, wird weniger HTML Quellcode generiert, da keine zusätzliche Table erstellt wird.


----------



## JanHH (23. Jan 2013)

Hm dann hab ich Dich vielleicht falsch verstanden. Nämlich so, das keine geschachtelten dataTables gehen sondern NUR ui:repeat. Dann nich schüttel sondern nick.


----------



## sence (23. Jan 2013)

opcorn:


----------



## azenth (24. Jan 2013)

Hallo nochmal,

also ich habe es geschafft, dass die Spalten gefüllt werden. Zwar stehen, da momentan noch falsche Werte drin, aber das liegt nun mehr an meinen Java-Klassen, die ich überarbeiten muss. 

Wie gesagt, da ich mich erst seit einer Woche mit JSF 2.0 versuche, fällt es mir noch echt schwer die Trennung zwischen Frontend, Controllern und Backend zu machen. Ich hoffe, dass gibt sich mit der Zeit. 

Gruß


----------



## sence (24. Jan 2013)

Dafür ist das Forum da, viel Erfolg beim lernen


----------



## azenth (28. Jan 2013)

Hallo,

ich habe leider noch eine Frage an euch. Nachdem ich meine Java-Klassen mit Kommentaren versehen habe und für die dataTable ein CSS-File erstellt habe, fügte ich noch die Host-Klasse hinzu und stellte überrascht fest, dass mir keine Hosts angezeigt wurden. 

Daraufhin habe ich das Logging hochgedreht und mir ich bin mir sicher, dass der Fehler bei der dritten dataTable sein muss. Weil die Java-Klassen alle die richtigen Werte in den Listen zurückliefern. Eigentlich habe ich alles gemacht wie sence es beschrieben hat, aber eventuell ist da doch noch irgendwo ein Fehler.


```
<h:dataTable value="#{userControler.usergroups}" var="groups"
	 		styleClass="order-table" headerClass="order-table-header" rowClasses="order-table-odd-row, order-table-even-row"
	 		columnClasses="order-table-cell-left, order-table-cell-mid, order-table-cell-right"
	 	>
	 		<h:column>
	 			<f:facet name="header" class="header">User Groups</f:facet>
	 			<h:outputText value="#{groups.name}"/>
	 		</h:column>
	 		<h:column>
	 			<f:facet name="header">Host Groups</f:facet>
				<h:dataTable value="#{groups.hostgroups}" var="hgroups" styleClass="order-table2" rowClasses="order-table2-odd-row, order-table2-even-row">
					<h:column>
						<h:outputText value="#{hgroups.name}"/>	
					</h:column>
				</h:dataTable>
			</h:column>
			<h:column>
	 			<f:facet name="header">Hosts</f:facet>
				<h:dataTable value="#{hgroups.host}" var="host" styleClass="order-table2" rowClasses="order-table2-odd-row, order-table2-even-row">
					<h:column>
						<h:outputText value="#{host.name}"/>	
					</h:column>
				</h:dataTable>
			</h:column>
		 </h:dataTable>
```

Wenn ich statt value="#{host.name}" value="#{userControler.usergroups.hostgroups.host.name}" schreibe, dann bekomme ich folgenden Fehler zurück: hostgroup cannot resolved as a member of usergroup.

Ich stehe grade echt vor einem Rätsel.


----------



## azenth (29. Jan 2013)

Hallo, 

ich bin es nochmal. Ich kenne nun den Grund warum ich in der Spalte Hosts keine Daten bekomme.


```
<h:dataTable value="#{userControler.usergroups}" var="usergroups"
	 		styleClass="order-table" headerClass="order-table-header" rowClasses="order-table-odd-row, order-table-even-row"
	 		columnClasses="order-table-cell-left, order-table-cell-mid, order-table-cell-right"
	 	>
	 		<h:column>
	 			<f:facet name="header" class="header">User Groups</f:facet>
	 			<h:outputText value="#{usergroups.name}"/>
	 		</h:column>
	 		<h:column>
	 			<f:facet name="header">Host Groups</f:facet>
				[COLOR="DarkRed"]<h:dataTable value="#{usergroups.hostgroups}" var="hostgroups"[/COLOR] styleClass="order-table2" rowClasses="order-table2-odd-row, order-table2-even-row">
					<h:column>
						<h:outputText value="#{hostgroups.name}"/>	
					</h:column>
				[COLOR="DarkRed"]</h:dataTable>[/COLOR]
			</h:column>
			<h:column>
	 			<f:facet name="header">Hosts</f:facet>
				<h:dataTable value="#{hostgroups.hosts}" var="host" styleClass="order-table2" rowClasses="order-table2-odd-row, order-table2-even-row">
					<h:column>
						<h:outputText value="#{host.name}"/>	
					</h:column>
				</h:dataTable>
			</h:column>
		 </h:dataTable>
```

Es liegt daran, dass ich bei die 2te dataTable schließe (in rot markiert) bevor ich die 3te öffne und dadurch die Variable hostgroups nicht mehr bekannt ist. Jetzt habe ich versucht das irgendwie ineinander zu verschachteln aber jedesmal geht dadurch meine Tabellenstruktur kaputt. Kennt da jemand eine gängige Lösung für mehrfachverschachtelte dataTables oder kann man die Variable irgendwie global machen?

Gruß


----------



## sence (2. Feb 2013)

Bin mir gerade nicht sicher, aber so in der Art könnte es funktionieren.

Hinweis:
Es ist freihändig geschrieben, keine garantie dass alle Tags richtig geschrieben sind.
Relevant ist die 3. Datatable


```
<h:dataTable value="#{userControler.usergroups}" var="usergroups"
	 		styleClass="order-table" headerClass="order-table-header" rowClasses="order-table-odd-row, order-table-even-row"
	 		columnClasses="order-table-cell-left, order-table-cell-mid, order-table-cell-right"
	 	>
	 		<h:column>
	 			<f:facet name="header" class="header">User Groups</f:facet>
	 			<h:outputText value="#{usergroups.name}"/>
	 		</h:column>
	 		<h:column>
	 			<f:facet name="header">Host Groups</f:facet>
				[COLOR="DarkRed"]<h:dataTable value="#{usergroups.hostgroups}" var="hostgroups"[/COLOR] styleClass="order-table2" rowClasses="order-table2-odd-row, order-table2-even-row">
					<h:column>
						<h:outputText value="#{hostgroups.name}"/>	
					</h:column>
				[COLOR="DarkRed"]</h:dataTable>[/COLOR]
			</h:column>
			<h:column>
	 			<f:facet name="header">Hosts</f:facet>
				<h:dataTable value="#{usergroups.hostgroups}" var="hostgroups" styleClass="order-table2" rowClasses="order-table2-odd-row, order-table2-even-row">
					<h:column>
						<ui:repeat value="#{usergroups.hostgroups.hosts}"  var="host">
                                                  <h:outputText value="#{host.name"} />
                                                </ui:repeat>
					</h:column>
				</h:dataTable>
			</h:column>
		 </h:dataTable>
```


----------

