duplicated id's in the faces tree

Status
Nicht offen für weitere Antworten.

freez

Top Contributor
Hallo

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

Code:
<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 f:param 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

Top Contributor
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 f:params:



Code:
<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>
 
M

maki

Gast
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 f:params:
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

Top Contributor
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
Code:
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
Code:
<f:param name="deviceid" id="deviceid2" value="#{searchdevice.deviceID}" />
habe kann ich den Parameter mit
Code:
UIParameter component = (UIParameter) event.getComponent().findComponent("deviceid2");
abfragen, aber
Code:
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?
 
M

maki

Gast
Probier doch mal:

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

Wird value etwas zugewiesen?
 

freez

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

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

Dort flog folgende Exception:
Code:
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
Code:
children.get(0)
per out.println() ausgegeben, mit folgendem Ergebniss: javax.faces.component.html.HtmlOutputText@15d59c3

@maki: Was sagt dir das Ergebnis?
 
M

maki

Gast
@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

Top Contributor
ok, habe ich umgesetzt:

trotzdem bekomme ich bei
Code:
UIParameter component = (UIParameter) event.getComponent().findComponent("deviceid");
kein Objekt zurück.

Code:
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?
 

freez

Top Contributor
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:
Code:
		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

Top Contributor
So, geschmeckt hats :)

Hm, das habe ich nun net gerafft. Ich dachte
Code:
event.getComponent().findComponent("deviceid");
sucht mir den Parameter
Code:
<f:param name="deviceid" value="#{searchdevice.deviceID}" />
raus. Oder was mache ich verkehrt?
 
M

maki

Gast
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

Top Contributor
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

Code:
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?
 
M

maki

Gast
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:
Code:
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

Top Contributor
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
Code:
DAO.getParam(event, "deviceid");
auf, und habe sofort was ich will :)
 
M

maki

Gast
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

Top Contributor
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??
 
M

maki

Gast
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

Mitglied
Ich hab bisher immer so mit Parametern gearbeitet:

Code:
<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>

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

gruß
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben