Hi Ulrich,

I create and compone a lot of components programmatically. I've written library that creates JSF-based editors base on the XML Schema of the document.

Editors are composed from a large number of JSF components (inputs, command links and buttons) and so on.

I use a lot of dynamic value and method bindings to allow user input change the underlying document. You'll see a typical example of what I'm doing in the end of the mail.

As for me, correct state management with JSF was SO compilcated that I've desided to drop it for now and implement dirty and easy solution.

In JSF, you save structure and state of components separately. State is what you components put into these arrays. Structure is saved as tree of component classes.

When you restore the state you first re-create a tree of components (i.e. instantiate classes) and the provide them with the state.

This is very very very inconvenient for my case.

1. I have a lot of dynamic bindings via anonymous classes. They simply aren't serializable! And even if I invent a way to make them serializable, this would take SO much time to restore all these dynamic bindings.

2. Simply restoring component tree from component classes tree is a huge overhead. I may have hundreds of components on a single page, and I don't want them to be serialized/deserialized on each request. This is too slow.

So I have finally decided to do a dirty hack. I simply save one UIViewRoot per view ID in the session. Basta. No serialization/deserialization, simply get attribute from session.

Yes it is a dirty hack. If you access the same page concurrently, you will have problems. But I don't see another solution right now. I'm simply limiting users to have one browser window per application, that's it.

Bye.
/lexi

ps. Code example. This creates a label for the complex component, with text, pop-up context menu (copy and paste) add and remove buttons.


help = HelpUtils.createHelpLink("sd.structure." + getHelpTopicId(),
                getHelpSubTopicId());
label = TemplatedPanelUtils.createTemplatedPanel(getTemplateName(),
                getFragmentId());

text = FacesUtils.createOutputText(getEditor().getMessageId());
text.setValueBinding("styleClass", new LabelStyleClassValueBinding(
                                getEditor()));

final UIComponent copy = CommandUtils.createLink("copy",
                new ClipboardMethodBinding() {
                        protected Object invokeInternal(Clipboard clipboard) {
                                clipboard.copy(getModel());
                                return "Success.";
                        }
                });

final UIComponent paste = CommandUtils.createLink("paste",
                new ClipboardMethodBinding() {
                        protected Object invokeInternal(Clipboard clipboard) {
                                clipboard.paste(getModel());
                                return "Success.";
                        }
                });

paste.setValueBinding("rendered", new ClipboardValueBinding() {
        protected Object getInternal(Clipboard clipboard) {
                return Boolean.valueOf(clipboard.isPastePossible(getModel()));
        }
});

final HtmlCommandLink refresh = CommandUtils.createLink(
                Messages.REFRESH, null);

contextMenu = FacesUtils.createPopupBox(FacesUtils
                .createContextMenuGraphicImage(), new UIComponent[] { copy,
                paste, refresh });
contextMenu.setStyleClass("hijack-contextMenu");
contextMenu.setStyleClassBox("hijack-contextMenu-box");

label.getFacets().put("contextMenu", contextMenu);

final VoidMethodBinding addAction = new VoidMethodBinding() {
        protected void execute() {
                getModel().addValue();
        }
};

addButton = AjaxCommandUtils.createAddImageLink(addAction);

final VoidMethodBinding removeAction = new VoidMethodBinding() {
protected void execute() {
                getModel().removeValue();
        }
};

removeButton = AjaxCommandUtils.createRemoveImageLink(removeAction);
label.getFacets().put("text", text);
label.getFacets().put("help", help);
label.getFacets().put("contextMenu", contextMenu);
label.getFacets().put("add", addButton);
label.getFacets().put("remove", removeButton);
label.getFacets().put("validity", getEditor().getValidity());
update();
return label;


Reply via email to