0

Proposal to improve Executions.createComponents()

asked 2010-11-08 03:03:15 +0800

dis gravatar image dis flag of Switzerland
140 4

Hi

I often use Executions.createComponents to nest components. It works perfectly.

However, I think the Executions.createComponents has two design flaws:

1. The Executions.createComponents(String uri, Component parent, Map arg) gives us the possibility to pass
a map with arguments to the nested component. It is easy to read those arguments in EL (in zul page), but
it is cumbersome to access the arguments in the Composer class (class which extends the GenericForwardComposer).

2. The Executions.createComponents(..) returns the root Component of the nested zul page. In many cases, I dont
really need the root component, what I need is the Composer object (if available).


To avoid those those two limits. I wrote an abstract class which extends the GenericForwardComposer:
code:

public abstract class MyGenericForwardComposer extends GenericForwardComposer {
    public static final String SESSION_ARG_KEY = "MyGenericForwardComposer.arg_key";
    public static final String SESSION_RESULT_KEY = "MyGenericForwardComposer.result_key";

    protected MyGenericForwardComposer() {
    }

    protected MyGenericForwardComposer(char separator) {
        super(separator);
    }

    protected MyGenericForwardComposer(char separator, boolean ignoreZScript, boolean ignoreXel) {
        super(separator, ignoreZScript, ignoreXel);
    }

    @Override
    public ComponentInfo doBeforeCompose(Page page, Component parent, ComponentInfo compInfo) {
        // call init befor any initialisation
        init();
        return super.doBeforeCompose(page, parent, compInfo);
    }

    private void init(){
    		// read the arguments from the session (see below how arguments are passed)
        Object args = XExecutions.getAttribute(SESSION_ARG_KEY);
        if(args!=null && args instanceof Map){
            XExecutions.removeAttribute(SESSION_ARG_KEY);

            // call onCreate with arguments. onCreate must be implemented by the composer class for the zul page
            onCreate((Map)args);
        }

        // set this composer in session to make it accessible for the callet (see below)
        XExecutions.setAttribute(SESSION_RESULT_KEY, this);
    }

    // implement the onCreate method in your Composer class
    protected abstract void onCreate(Map args);
}


and a helper class with a method which must be called instead of Executions.createComponents(...):
class MyExecutions {
    public static GenericForwardComposer createComponents2(String uri, Component parent, Map arg){
        if(arg!=null){
            // set arg in session
            setAttribute(MyGenericForwardComposer.SESSION_ARG_KEY, arg);
        }
        Executions.createComponents(uri, parent, arg);
        GenericForwardComposer composer = (GenericForwardComposer) getAttribute(MyGenericForwardComposer.SESSION_RESULT_KEY);
        removeAttribute(MyGenericForwardComposer.SESSION_RESULT_KEY);
        return composer;
    }
}


Now, each composer must extend from MyGenericForwardComposer instead of GenericForwardComposer:
class MyXXXComposer extends MyGenericForwardComposer {
    // override onCreate method.
    protected abstract void onCreate(Map args){
        // read arguments, store in members to make it accessible by the other methods 
    }
    
    .....
}

To call this is easy with the new method createComponents2 (see above).
MyXXXComposer xxxComposer = (MyXXXComposer) MyExecutions.createComponents2("mypage1.zul", parent, <Hashmap with arguments>);


This solves the two issues above. Does anybody see any problems with this? I am very interested in the opinion of experienced ZK developers about this.

In my opinion it would make sense to integrate it somehow into the ZK product.

Thanks
Dieter

delete flag offensive retag edit

3 Replies

Sort by ยป oldest newest

answered 2010-11-14 04:45:02 +0800

gekkio gravatar image gekkio flag of Finland
899 1
http://gekkio.fi/blog

I agree with point 1. I usually pass arguments using Executions.getCurrent().setAttribute/getAttribute instead of the args Map. So it's a similar method as yours.

However, I disagree with point 2 because the root component might have multiple composers applied. This practically means that you can't choose just one composer, especially if this were integrated into ZK itself. In your application maybe you only use one composer per component but this probably isn't true for all ZK applications (I often split large composers into smaller parts). Having a separate method called createComponents2 is of course an ok solution because it won't break existing applications.

link publish delete flag offensive edit

answered 2010-11-15 02:20:41 +0800

xmedeko gravatar image xmedeko
1021 1 16
http://xmedeko.blogspot.c...

Hi,

it is easy to read arg from the composer, do it in the doBeforeComposeChildren:

	@Override
	public void doBeforeComposeChildren(Component comp) throws Exception {
		super.doBeforeComposeChildren(comp);

		this.arg = Executions.getCurrent().getArg();
                this.myValue = this.arg.get("myValue");
	}

you see, I preset this.arg before the autowiring, so the.arg is accessible in the composer methods, which are called by EL resolvers. Something like

public String getMyValue() {
   return this.arg.get("myValue");
}

link publish delete flag offensive edit

answered 2010-11-15 09:58:30 +0800

dis gravatar image dis flag of Switzerland
140 4

Thank you for your answers.

Executions.getCurrent().getArg();

is definitely better than session variables from my approach.

- Dieter

link publish delete flag offensive edit
Your reply
Please start posting your answer anonymously - your answer will be saved within the current session and published after you log in or create a new account. Please try to give a substantial answer, for discussions, please use comments and please do remember to vote (after you log in)!

[hide preview]

Question tools

Follow

RSS

Stats

Asked: 2010-11-08 03:03:15 +0800

Seen: 667 times

Last updated: Nov 15 '10

Support Options
  • Email Support
  • Training
  • Consulting
  • Outsourcing
Learn More