# duplicated id's in the faces tree



## freez (1. Okt 2007)

Hallo

ich bekomme bei folgendem Code immer die Meldung "Client-id : deviceid is duplicated in the faces tree"


```
<h:form>
	<t:dataTable var="searchdevice" value="#{extendedSearchDevices.deviceList}"
		...
		>
		<t:column>
		...
		</t:column>
		
		<t:column>
			<h:outputLink value="#{searchdevice.webauthlink}" styleClass="datatable_col_link"  >
				<h:outputText value="WebAuthentication" styleClass="datatable_col_links_text" />
			</h:outputLink>
			<h:commandLink action="showDevice" styleClass="datatable_col_link" actionListener="#{DeviceDetail.selectDeviceID}">
				<h:outputText value="Details" styleClass="datatable_col_links_text" />
				<f:param id="deviceid" name="deviceid" value="#{searchdevice.deviceID}" />
			</h:commandLink>
			<h:commandLink action="to_confirmDeleting" actionListener="#{DeviceDetail.selectDeviceID}">
				<h:outputText value="Gerät löschen" styleClass="cellOptions" />
				<f:param name="deviceid" id="deviceid" value="#{searchdevice.deviceID}" />
			</h:commandLink>
		</t:column>
		
		<f:facet name="footer">
			<t:dataScroller id="scroll_2"
				...
			</t:dataScroller>
		
		</f:facet>
	</t:dataTable>
</h:form>
```

Ich habe schon versucht den Form Tag aussen weg zu nehmen und einzeln um jeden commandLink Tag zu setzen. Dann meckert Tomcat, das irgendwas vom dataScroller in einen form Tag muss. Und den Datascroller kann ich nicht in einen Form Tag stecken, weil er dann nicht auf die dataTable zugreifen kann.

Ich könnte natürlich verschiedene ID's beim faram verwenden. Aber dann müsste ich in dem ActionListener auf verschiedene ID's abfragen, was ich auch nicht möchte. Wie kann ich dieses Problem lösen?


----------



## freez (1. Okt 2007)

Und noch was. Wieso funktioniert denn dieser Code bezüglich der duplicated ID? In einem Form Tag sind da zwei gleiche id's in den farams:




```
<h:dataTable var="device" value="#{cell.deviceList}">
	<h:column>
		<h:panelGrid columns="1">
			<h:panelGroup>
				<h:form>
					<h:outputText value="Optionen: " styleClass="cellOptions" />
												
					<h:commandLink style="padding-right:10px;" action="to_confirmDeleting" actionListener="#{DeviceDetail.selectDeviceID}">
						<h:outputText value="löschen"  styleClass="cellOptions" />
						<f:param name="deviceid" id="deviceid" value="#{device.device1ID}" />
					</h:commandLink>
					<h:commandLink action="showDevice" styleClass="datatable_col_link" actionListener="#{DeviceDetail.selectDeviceID}">
						<h:outputText value="Details" styleClass="datatable_col_links_text" />
						<f:param id="deviceid" name="deviceid" value="#{device.device1ID}" />
					</h:commandLink>
				</h:form>
			</h:panelGroup>
		</h:panelGrid>
	</h:column>
	<h:column>
		<h:panelGrid columns="1">
			<h:panelGroup>
				<h:form>
					<h:outputText value="Optionen: " styleClass="cellOptions" />
												
					<h:commandLink style="padding-right:10px;" action="to_confirmDeleting" actionListener="#{DeviceDetail.selectDeviceID}">
						<h:outputText value="löschen"  styleClass="cellOptions" />
						<f:param name="deviceid" id="deviceid" value="#{device.device2ID}" />
					</h:commandLink>
					<h:commandLink action="showDevice" styleClass="datatable_col_link" actionListener="#{DeviceDetail.selectDeviceID}">
						<h:outputText value="Details" styleClass="datatable_col_links_text" />
						<f:param id="deviceid" name="deviceid" value="#{device.device2ID}" />
					</h:commandLink>
				</h:form>
			</h:panelGroup>
		</h:panelGrid>
	</h:column>		
</h:dataTable>
```


----------



## maki (1. Okt 2007)

> Und noch was. Wieso funktioniert denn dieser Code bezüglich der duplicated ID? In einem Form Tag sind da zwei gleiche id's in den farams:


Ich verstehe ehrlich gesagt nicht, warum 2 params überhaupt ids zuordnest, und dann noch diesselben...
aber dafür den deinen  Komponeneten gar keine zuordnest...

params brauchen keine ids, aber wenn du sauber arbeiten willst, braucht jede deiner Komponeneten eine id.


----------



## freez (2. Okt 2007)

Das dachte ich bis jetzt auch. Aber vielleicht habe ich auch ein anderes Problem. Ich habe die id deswegen mit angegeben, weil ich sonst bei

```
UIParameter component = (UIParameter) event.getComponent().findComponent("deviceid");
```

im ActionListener immer null für "component" zurück bekomme. Vielleicht ist ja auch da etwas verkehrt. Füge ich die id hinzu, funktioniert es. Aber komischerweise mit dem text, welcher unter "id" angegeben ist und nicht mit dem unter "name".

Also wenn ich 
	
	
	
	





```
<f:param name="deviceid" id="deviceid2" value="#{searchdevice.deviceID}" />
```
 habe kann ich den Parameter mit 
	
	
	
	





```
UIParameter component = (UIParameter) event.getComponent().findComponent("deviceid2");
```
 abfragen, aber 
	
	
	
	





```
UIParameter component = (UIParameter) event.getComponent().findComponent("deviceid");
```
 geht nicht.

Ich kann mich erinnern, dass ich nur name und value benötigt habe. Wieso geht das aber da nicht?


----------



## maki (2. Okt 2007)

Probier doch mal:


```
List children = event.getComponent().getChildren();
		Object value = ((UIParameter) children.get(0)).getValue();
```
Was passiert?

Wird value etwas zugewiesen?


----------



## y0dA (2. Okt 2007)

**


----------



## freez (8. Okt 2007)

Also, ich habe mal faram nur mit name und value bestückt (ohne id) und mal den code ausprobiert:


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

Dort flog folgende Exception: 
	
	
	
	





```
Caused by: java.lang.ClassCastException: javax.faces.component.html.HtmlOutputText
	at DeviceDetail.selectDeviceID(DeviceDetail.java:188)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:585)
	at org.apache.myfaces.el.MethodBindingImpl.invoke(MethodBindingImpl.java:132)
	... 26 more
```

Dann habe ich einfach mal 
	
	
	
	





```
children.get(0)
```
 per out.println() ausgegeben, mit folgendem Ergebniss: javax.faces.component.html.HtmlOutputText@15d59c3

@maki: Was sagt dir das Ergebnis?


----------



## maki (8. Okt 2007)

> @maki: Was sagt dir das Ergebnis?


Ich wundere mich gerade, warum du ein outputText element unter deinen commandLink setzt (und warum mir das nicht gleich aufgefallen ist), denn dessen Wert bekommst du zurück.. nimm doch mal das value attribut des commandLink tag und entferne den outputText.


----------



## freez (8. Okt 2007)

ok, habe ich umgesetzt:

trotzdem bekomme ich bei 
	
	
	
	





```
UIParameter component = (UIParameter) event.getComponent().findComponent("deviceid");
```
 kein Objekt zurück.


```
List children = event.getComponent().getChildren(); 
			Object value = ((UIParameter) children.get(0)).getValue(); 
			System.out.println("Listenlänge: " + children.size() + " -- " + value);
```

gibt "Listenlänge: 1 -- 17" aus.

Was nu?


----------



## maki (8. Okt 2007)

was ist value?


----------



## freez (8. Okt 2007)

Also, nächster Test hat folgendes ergeben:

component: null
Listenlänge: 1 -- Name:Value = deviceid:17
children.get(0): javax.faces.component.UIParameter@1470c35

der code dazu: 
	
	
	
	





```
UIParameter component = (UIParameter) event.getComponent().findComponent("deviceid");
		if(component != null)
			deviceID = component.getValue().toString();
		else{
			deviceID = "";
			System.out.println("component: " + component);
//			TODO DEBUG CODE
			List children = event.getComponent().getChildren(); 
			Object value = ((UIParameter) children.get(0)).getValue();
			Object name = ((UIParameter) children.get(0)).getName();
			System.out.println("Listenlänge: " + children.size() + " -- Name:Value = " + name + ":" + value);
			System.out.println("children.get(0): " + children.get(0));
		}
```

Also die testausgaben sehen ja gut aus. Aber warum ist component immer noch null?


----------



## freez (8. Okt 2007)

So, nun ist Mittagspause  Guten Appetit


----------



## maki (8. Okt 2007)

Du sollst auch nicht nach Komponenten per id suchen; der vaule, in deinem falle 17, sollte doch reichen.

Parameter brauche keine ids und müssen auch nicht als Komponenten angesprochen werden.

Mahlzeit 
http://youtube.com/watch?v=2PAaqr9ZoZw


----------



## freez (8. Okt 2007)

So, geschmeckt hats 

Hm, das habe ich nun net gerafft. Ich dachte 
	
	
	
	





```
event.getComponent().findComponent("deviceid");
```
 sucht mir den Parameter 
	
	
	
	





```
<f:param name="deviceid" value="#{searchdevice.deviceID}" />
```
 raus. Oder was mache ich verkehrt?


----------



## maki (8. Okt 2007)

> Oder was mache ich verkehrt?


Ganz einfach: parameter sollten keine ids haben und nicht als Komponeneten angesprochen werden.

Löse dich von deiner Vorstellung, dann fällt es dir einfacher..


----------



## freez (8. Okt 2007)

Ok, habe mich davon gelöst  Ich habe es noch nicht einmal bewusst so gemacht. Diese Art die Parameter auszulesen habe ich mir von mehreren Seiten aus dem Internet abgeschaut.

Damit andere nicht dumm sterben: Ich habe es nun so gelöst


```
List children = event.getComponent().getChildren();
		Iterator it = children.iterator();
		while(it.hasNext()){
			UIParameter uip = (UIParameter) it.next();
			if(uip.getName().equals("deviceid")){
				deviceID = uip.getValue().toString();
			}
		}
```

Und was soll ich sagen ... es geht  Vielen Dank an maki.

Gibt es eigentlich auch eine kürzere Variante?


----------



## maki (8. Okt 2007)

> Gibt es eigentlich auch eine kürzere Variante?


Irgendwie hab ich fast das Gefühl, dass du mich auf den Arm enhmen möchtest.. oder etwas auf dem Schlauch stehst 

hier nochmals die Art und Weise wie wir das hier in meiner Firma machen:

```
public void myActionListener(ActionEvent event) {

      List children = event.getComponent().getChildren();
      Object value = ((UIParameter) children.get(0)).getValue(); 
  
      ....
```
Und schon hast du den Wert oder gleich ein Objekt, denn du könntest ja auch echte Domainobjekte als Paramerter benutzen, müssen ja keine Strings sein..

Ob es bessere Möglichkeiten gibt ist mir im Moment egal, denn das funktioniert.
Meine mich errinnern zu können, das bei Komponeneten auch getNewValue() funzt, aber parameter lesen wir immer so aus.


----------



## freez (8. Okt 2007)

Nein, ich denke wir haben uns schon verstanden. Du hast recht. Dein Code ist kürzer und funktioniert.

Ich habe meinen deswegen so "umständlich" geschrieben, weil ich den Parameter anhand des Namens holen möchte. Komme ich nämlich morgen auf die Idee noch 2 weitere Parameter an den commandLink zu hängen, muss ich nicht überlegen in welcher Reihenfolge die stehen. Ich rufe nur noch meine neue Methode 
	
	
	
	





```
DAO.getParam(event, "deviceid");
```
 auf, und habe sofort was ich will


----------



## maki (8. Okt 2007)

Vergiss die ids, ernsthaft, dass ist der falsche Weg.

Falls es dir nicht reicht, die parameter per index anzusprechen, könntest du den Namen rausfinden:
UIParameter.getName()

im Moment nehme ich nur den Wert mit
UIParameter.getValue()

Könntest ja durch die children iterieren bis eines den Namen hat, den du suchst.


----------



## freez (8. Okt 2007)

Ich habe das Gefühl, du störst dich an dem Wort "deviceid". Das ist fei nicht die id des parameters. Das ist die ID aus meiner Datenbank. Wenn du dir mal meinen Code genauer anschaust, wirst du sehen, das ich genau das gemacht habe, was du mir gerade vorgeschlagen hast. Ich iteriere über die childrens und vergleiche auf den Namen und beim match hole ich mir die Value (Welche eine ID aus meiner Datenbank ist )

Oder brauchst du noch mehr code von mir zum Verständniss??


----------



## maki (8. Okt 2007)

Hast recht, hab mich an der deviceId gestört und dir dann dann vorgeschlagen es so zu machen wie du es bereits getan hast... lol

Zeit für ne Pause


----------



## zordan (8. Okt 2007)

Ich hab bisher immer so mit Parametern gearbeitet:


```
<t:commandLink action="#{bean.navigateToItemAction}">
							<t:graphicImage value="/images/edit_icon.gif" border="0"
								alt="Gegenstand bearbeiten" />
							<f:param value="#{bean.number}"
								name="param_number" />
							<f:param value="#{Item.posnumber}"
								name="param_posnumber" />
						</t:commandLink>
```


```
fc = FacesContext.getCurrentInstance();
            number = (String)fc.getExternalContext().getRequestParameterMap().get("param_invnumber");
```

gruß


----------

