-
FEATURED COMPONENTS
First time here? Check out the FAQ!
Hi,
I am trying to build a tree from a click event on a button. That works fine in common cases but, after refreshing, an UiException are raised at the first click on the button then the second click works fine.
The whole stack of the exception is: org.zkoss.zk.ui.UiException: You cannot access components belong to other desktop at org.zkoss.zk.ui.AbstractComponent.checkDetach(AbstractComponent.java:409) at org.zkoss.zk.ui.AbstractComponent.checkParentChild(AbstractComponent.java:1073) at org.zkoss.zk.ui.AbstractComponent.setParent(AbstractComponent.java:966) at org.zkoss.zul.Treeitem.setParent(Treeitem.java:419) at org.zkoss.zk.ui.AbstractComponent.detach(AbstractComponent.java:1669)
The .zul :
<window apply="btrview.information.Information" width="100%" height="100%">
<div class="informationClass">
<div class="navigationClass">
<textbox id="selection" />
<button id="build" image="Images/Index/optimize_25.png" class="addViewButton" />
<textbox id="type" />
<button id="help" image="Images/Index/optimize_25.png" class="addViewButton" />
<tree id="navigation" rows="0" class="navigationTree" />
</div>
<div class="graphClass">
<label id="name" class="text" />
</div>
</div>
</window>
In the Information.java, I use the method onclick method to get the click event: public void onClick$build() { }
In this method, I build the tree.
Do you know why I get the UiException and how to fix it ? Thanks
You are binding your ZUL with Ids so when page rendered Dom already have that id now again when refreshing the page it is getting same id again that why it is throwing some id exception.
So I don't understand why other pages of the application have not the same behavior. My "Information" page is loaded from an include element as other pages with buttons too and these pages works fine after refreshing. Moreover, only the button (id=build) has this issue after refreshing the other ones work fine. So I suppose that the tree creation is badly done. The exception lets me think about the creation of a different desktop on refresh...
The method onClick$build() throws the following exception:
org.zkoss.zk.ui.UiException: You cannot access components belong to other desktop
at org.zkoss.zk.ui.AbstractComponent.checkDetach(AbstractComponent.java:409)
at org.zkoss.zk.ui.AbstractComponent.checkParentChild(AbstractComponent.java:1073)
at org.zkoss.zk.ui.AbstractComponent.setParent(AbstractComponent.java:966)
at org.zkoss.zul.Treeitem.setParent(Treeitem.java:419)
at org.zkoss.zk.ui.AbstractComponent.detach(AbstractComponent.java:1669)
at org.zkoss.zul.Tree.onTreeDataRemoved(Tree.java:1385)
at org.zkoss.zul.Tree.onTreeDataChange(Tree.java:1334)
at org.zkoss.zul.Tree.access$1000(Tree.java:156)
at org.zkoss.zul.Tree$2.onChange(Tree.java:1459)
at org.zkoss.zul.AbstractTreeModel.fireEvent(AbstractTreeModel.java:108)
at org.zkoss.zul.DefaultTreeNode$TreeNodeChildrenList.remove(DefaultTreeNode.java:278)
at org.zkoss.zul.DefaultTreeNode$TreeNodeChildrenList.remove(DefaultTreeNode.java:226)
at java.util.AbstractList$Itr.remove(AbstractList.java:374)
at java.util.AbstractList.removeRange(AbstractList.java:571)
at java.util.AbstractList.clear(AbstractList.java:234)
at btrview.information.Information.onClick$build(Information.java:111)
at btrview.information.Information.doAfterCompose(Information.java:87)
at org.zkoss.zk.ui.impl.UiEngineImpl.doAfterCompose(UiEngineImpl.java:530)
at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:825)
at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:771)
at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:680)
at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:644)
at org.zkoss.zk.ui.impl.UiEngineImpl.createComponents(UiEngineImpl.java:1025)
at org.zkoss.zk.ui.impl.AbstractExecution.createComponents0(AbstractExecution.java:246)
at org.zkoss.zk.ui.impl.AbstractExecution.createComponents(AbstractExecution.java:238)
at org.zkoss.zul.Include.afterCompose(Include.java:451)
at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild0(UiEngineImpl.java:823)
at org.zkoss.zk.ui.impl.UiEngineImpl.execCreateChild(UiEngineImpl.java:771)
at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate0(UiEngineImpl.java:680)
at org.zkoss.zk.ui.impl.UiEngineImpl.execCreate(UiEngineImpl.java:644)
In the following code, you can see my dirty hack to fix my issue. The uiException is catched and the method onClick$build() is executed again. By the way, this hack works fine but I would prefer to understand what I do wrong. Here the code of the Information class:
public class Information extends GenericForwardComposer<Component> {
private static final long serialVersionUID = 14L;
private final static Logger logger = LoggerFactory.getLogger(Information.class.getSimpleName());
private final SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
private final BtrScriptConnector connector = BtrScriptConnector.getInstance();
private final ElementFactory factory = ElementFactory.getInstance();
private Textbox selection, type;
private Tree navigation;
private Label name;
private Window popup;
private Div staticBar, dynamicBar, staticProps;
@Override
public void doAfterCompose(Component pComp) throws Exception {
super.doAfterCompose(pComp);
PageManager.getInstance().register(PageType.INFORMATION, this);
selection.setText("/datacenter");
type.setText("vm");
// Initialize bars and their buttons
BarButtonManager bbm = new BarButtonManager(staticBar);
for (Component c : staticBar.getChildren())
c.addEventListener(Events.ON_CLICK, bbm);
bbm = new BarButtonManager(dynamicBar);
for (Component c : dynamicBar.getChildren())
c.addEventListener(Events.ON_CLICK, bbm);
switch (InformationVariables.getStaticVar()) {
case RULES:
((Button) staticBar.getChildren().get(1)).setClass("pressedButton");
break;
case RECONFIGURATION:
((Button) staticBar.getChildren().get(2)).setClass("pressedButton");
break;
default:
((Button) staticBar.getChildren().get(0)).setClass("pressedButton");
break;
}
switch (InformationVariables.getDynamicVar()) {
case CPU:
((Button) dynamicBar.getChildren().get(1)).setClass("pressedButton");
break;
case POWER:
((Button) dynamicBar.getChildren().get(2)).setClass("pressedButton");
break;
case MEMORY:
((Button) dynamicBar.getChildren().get(3)).setClass("pressedButton");
break;
default:
((Button) dynamicBar.getChildren().get(0)).setClass("pressedButton");
break;
}
// Generate the navigation menu (tree)
if (!InformationVariables.getSelectionVar().isEmpty() && !InformationVariables.getTypeVar().isEmpty()) {
selection.setText(InformationVariables.getSelectionVar());
type.setText(InformationVariables.getTypeVar());
onClick$build();
}
// Generate element data
if (InformationVariables.getSelectedElement() == null)
name.setValue("Select an element in the navigation menu.");
else
generateInfo();
};
public void onClick$build() {
try {
if (selection.getText().isEmpty() || type.getText().isEmpty()) {
logger.warn("Missing navigation or type!");
Messagebox.show("Missing navigation or type!");
} else {
InformationVariables.setSelectionVar(selection.getText());
InformationVariables.setTypeVar(type.getText());
factory.setLeafType(type.getText());
List<String> uuids = connector.getElementUUIDs(selection.getText());
String mytype = connector.getProperty(uuids.get(0), BSProperty.type.toString());
List<String> path = connector.getTypes(mytype, type.getText());
navigation.setItemRenderer(new ElementRender(this, new PopupWindow(popup)));
InformationVariables.setRootElement(factory.newElement(Element.rootName));
ElementNode rootNode = InformationVariables.getRootElement().getNode();
rootNode.getChildren().clear();
navigation.setModel(new ElementModel(rootNode));
// Build the tree
logger.info("path: " + path);
Element el;
List<Element> elements = new ArrayList<Element>();
for (String uuid : uuids) {
logger.info("Add to root: " + uuid);
el = factory.newElement(uuid);
el.buildNode(false);
elements.add(el);
rootNode.add(el.getNode());
}
String type = null;
String sonType = null;
List<Element> sons = new ArrayList<Element>();
List<Element> temp = new ArrayList<Element>();
while (path.size() > 1) {
type = path.remove(0);
sonType = path.get(0);
logger.info("Type: " + type + ", sonType: " + sonType);
for (Element elem : elements) {
for (String son : connector.getElementsFromLink(elem.getUuid(), sonType)) {
if (!son.isEmpty()) {
logger.info("Add the son '" + son + "' to " + elem.getName());
Element sonEl = factory.newElement(son);
sonEl.buildNode(path.size() == 1);
sons.add(sonEl);
elem.getNode().add(sonEl.getNode());
}
}
temp.addAll(sons);
sons.clear();
}
elements.clear();
elements.addAll(temp);
temp.clear();
}
}
} catch (UiException e) {
logger.error("Can not build the tree: ", e);
onClick$build();
} catch (Throwable t) {
logger.error("Can not build the tree: ", t);
}
}
public void onClick$help() {
Messagebox.show("Help me plz!");
}
public void onClick$properties() {
InformationVariables.setStaticVar(GraphVar.PROPERTIES);
// Get properties of the selected element
staticProps.getChildren().clear();
Element selectedElement = InformationVariables.getSelectedElement();
for (String prop : selectedElement.refreshProperties()) {
StringBuilder buffer = new StringBuilder();
logger.info("property: " + prop);
try {
switch (BSProperty.valueOf(prop)) {
case cpu:
buffer.append(prop + ": " + selectedElement.getProperty(prop) + " / "
+ selectedElement.getPropertyAsInt(BSProperty.cpu_max));
break;
case cpu_need:
case cpu_cap:
buffer.append(prop + ": " + selectedElement.getProperty(prop) + " MHz");
break;
case iodisk:
buffer.append(prop + ": " + selectedElement.getProperty(prop) + " / "
+ selectedElement.getPropertyAsInt(BSProperty.iodisk_max) + " kb/s");
break;
case mem:
buffer.append(prop + ": " + selectedElement.getProperty(prop) + " / "
+ selectedElement.getPropertyAsInt(BSProperty.mem_max));
break;
case mem_cap:
buffer.append(prop + ": " + selectedElement.getProperty(prop) + " Mb");
break;
case net:
buffer.append(prop + ": " + selectedElement.getProperty(prop) + " / "
+ selectedElement.getPropertyAsInt(BSProperty.net_max) + " Mb/s");
break;
case power:
buffer.append(prop + ": " + selectedElement.getProperty(prop) + " / "
+ selectedElement.getPropertyAsInt(BSProperty.power_max));
break;
case power_min:
buffer.append(prop + ": " + selectedElement.getProperty(prop) + " W");
break;
case cpu_max:
case iodisk_max:
case mem_max:
case name:
case net_max:
case power_max:
case type:
case uuid:
break;
default:
buffer.append(prop + ": " + selectedElement.getProperty(prop));
break;
}
} catch (IllegalArgumentException e) {
buffer.append(prop + ": " + selectedElement.getProperty(prop));
}
if (buffer.length() > 0) {
Button propButton = new Button(buffer.toString());
propButton.setClass("staticItem");
staticProps.appendChild(propButton);
}
}
}
public void onClick$rules() {
InformationVariables.setStaticVar(GraphVar.RULES);
staticProps.getChildren().clear();
for (String rule : connector.getRules(InformationVariables.getSelectedElement().getUuid())) {
Button propButton = new Button(connector.getRuleExpression(rule) + " (" + connector.getRuleState(rule) + ")");
propButton.setClass("staticItem");
staticProps.appendChild(propButton);
}
}
public void onClick$reconfigurations() {
InformationVariables.setStaticVar(GraphVar.RECONFIGURATION);
staticProps.getChildren().clear();
Messagebox.show("Sorry, not implemented yet :P");
}
private void generateInfo() {
name.setValue("Overview of " + InformationVariables.getSelectedElement());
// Static Properties
switch (InformationVariables.getStaticVar()) {
case RULES:
onClick$rules();
break;
case RECONFIGURATION:
onClick$reconfigurations();
break;
default:
onClick$properties();
break;
}
// Dynamic properties
switch (InformationVariables.getDynamicVar()) {
case CPU:
onClick$cpu();
break;
case MEMORY:
onClick$memory();
break;
case POWER:
onClick$power();
break;
default:
onClick$radar();
break;
}
}
@Override
public void onEvent(Event pEvt) throws Exception {
try {
if (pEvt.getName().equals(Events.ON_CLICK)) {
InformationVariables.setSelectedElement(((ElementNode) ((Treeitem) ((Treerow) pEvt.getTarget()).getParent()).getValue())
.getData());
generateInfo();
} else if (pEvt.getName().equals("timerEvent") && InformationVariables.getSelectedElement() != null)
generateInfo();
else
super.onEvent(pEvt);
} catch (Throwable t) {
logger.error("onEvent: ", t);
}
}
private void displayChart(BSProperty pCons) {
GraphVar chart;
int max;
Element selectedElement = InformationVariables.getSelectedElement();
switch (pCons) {
case cpu:
chart = GraphVar.CPU;
max = selectedElement.getPropertyAsInt(BSProperty.cpu_max);
break;
case power:
chart = GraphVar.POWER;
max = selectedElement.getPropertyAsInt(BSProperty.power_max);
break;
case mem:
chart = GraphVar.MEMORY;
max = selectedElement.getPropertyAsInt(BSProperty.mem_max);
break;
default:
chart = GraphVar.CPU;
max = selectedElement.getPropertyAsInt(BSProperty.cpu_max);
logger.warn("Can not display chart for the property: " + pCons);
break;
}
StringBuilder datas = new StringBuilder();
datas.append("dynamic" + Language.FIELD_SEPARATOR);
InformationVariables.setDynamicVar(chart);
datas.append(String.valueOf(max) + Language.FIELD_SEPARATOR);
List<Integer> values = selectedElement.getHistory(pCons);
Calendar cal = selectedElement.getAcquisitionTime();
cal.add(Calendar.SECOND, -2 * values.size());
for (int i = 0; i < values.size(); i++) {
cal.add(Calendar.SECOND, 2);
datas.append(sdf.format(cal.getTime()) + String.valueOf(Language.DEVICE_SEPARATOR) + values.get(i)
+ Language.FIELD_SEPARATOR);
}
Clients.evalJavaScript("$(document).ready(function start_drawChart(){ if((typeof(Raphael) === 'function')"
+ "&& (typeof(drawChart) === 'function')) { drawChart('" + datas + "');} });");
}
public void onClick$radar() {
Element selectedElement = InformationVariables.getSelectedElement();
InformationVariables.setDynamicVar(GraphVar.RADAR);
// Power is expressed as a per thousand
int power =
selectedElement.getPropertyAsInt(BSProperty.power) * 1000 / selectedElement.getPropertyAsInt(BSProperty.power_max);
int cpu = selectedElement.getPropertyAsInt(BSProperty.cpu) * 1000 / selectedElement.getPropertyAsInt(BSProperty.cpu_max);
int mem = selectedElement.getPropertyAsInt(BSProperty.mem) * 1000 / selectedElement.getPropertyAsInt(BSProperty.mem_max);
Clients.evalJavaScript("$(document).ready(function start_radar(){if((typeof(Raphael) === 'function') "
+ "&& (typeof(radar) === 'function') ) {radar('" + cpu + Language.FIELD_SEPARATOR + mem + Language.FIELD_SEPARATOR
+ power + "');}});");
}
public void onClick$cpu() {
InformationVariables.setDynamicVar(GraphVar.CPU);
displayChart(BSProperty.cpu);
}
public void onClick$memory() {
InformationVariables.setDynamicVar(GraphVar.MEMORY);
displayChart(BSProperty.mem);
}
public void onClick$power() {
InformationVariables.setDynamicVar(GraphVar.POWER);
displayChart(BSProperty.power);
}
}
Thank you for your help