Wire Variables"
Line 29: | Line 29: | ||
With this approach, since the composer will be instantiated by Spring, all the data member that Spring recognizes will be wired. Thus, you could access them directly. | With this approach, since the composer will be instantiated by Spring, all the data member that Spring recognizes will be wired. Thus, you could access them directly. | ||
− | <source lang="java" high="4"> | + | <source lang="java" high="4,6"> |
− | + | import org.springframework.stereotype.Component; | |
+ | import org.springframework.beans.factory.annotation.Autowired; | ||
− | public class PasswordSetter extends | + | @Component |
+ | public class PasswordSetter extends GenericForwardComposer { | ||
@Autowired | @Autowired | ||
private User user; //wired automatically by Spring | private User user; //wired automatically by Spring | ||
Line 43: | Line 45: | ||
</source> | </source> | ||
− | As shown, (non-UI) beans are wired by Spring, so you have to specify Spring's annotation accordingly. | + | As shown, (non-UI) beans are wired by Spring, so you have to specify Spring's annotation accordingly, such <code>@Component</code> to annotate the composer and <code>@Autowired</code> to the field. |
==Approach 2: have GenericForwardComposer to wire a Spring-managed bean== | ==Approach 2: have GenericForwardComposer to wire a Spring-managed bean== |
Revision as of 01:49, 8 December 2011
Wiring Sequence
GenericForwardComposer will wire members defined in the composer. Here is the sequence:
- It searches any setters if its name matches any of the following
- Any fellow with the same name (Component.getFellow(String))
- Any variable defined in Page.addVariableResolver(VariableResolver) with the same name
- Any variable defined in zscript with the same name
- Any implicit object with the same name
- Then, it searches any field to see if it matches any fellow, any variable,... the same as the above.
Wire Spring-managed Beans
Basically there are two approaches depending on whether you want to make the composer as a Spring-managed bean.
Approach 1: make the composer as a Spring-managed bean
If you prefer to manage composers with Spring, you could simply declare the Spring variable resolver called DelegatingVariableResolver in a ZUML document, and then use EL to retrieve the composer in the apply attribute. For example,
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<window apply="${passwordSetter}"> <!-- assume there is a Spring-managed bean called passwordSetter -->
...
As shown above, passwordSetter shall be a Spring-managed bean.
With this approach, since the composer will be instantiated by Spring, all the data member that Spring recognizes will be wired. Thus, you could access them directly.
import org.springframework.stereotype.Component;
import org.springframework.beans.factory.annotation.Autowired;
@Component
public class PasswordSetter extends GenericForwardComposer {
@Autowired
private User user; //wired automatically by Spring
private Textbox password; //wired automatically by ZK
public void onClick$submit() {
user.setPassword(password.getValue());
}
}
As shown, (non-UI) beans are wired by Spring, so you have to specify Spring's annotation accordingly, such @Component
to annotate the composer and @Autowired
to the field.
Approach 2: have GenericForwardComposer to wire a Spring-managed bean
If you prefer not to have Spring to manage composers (for better separation or other reasons), you could have GenericForwardComposer to wire it for you.
GenericForwardComposer not only wires UI components, but also wires beans that can be found by the registered variable resolvers. Thus, you could have ZK to wire the Spring-managed beans by registering the Spring variable resolver manually as shown in the following code snippet. Then, if a data member's name matches a Spring-managed bean, it will be wired automatically too. For example,
public class PasswordSetter extends GenericForwardComposer {
private User user; //wired automatically if user is a spring-managed bean
private Textbox password; //wired automatically if there is a textbox named password
public void doAfterComposer(Component comp) {
page.addVariableResolver(new org.zkoss.zkplus.spring.DelegatingVariableResolver());
//variable resolver must be added before calling super.doAfterCompose
//since the autowiring depends on it
super.doAfterCompose(comp);
}
public void onClick$submit() {
user.setPassword(password.getValue());
}
}
As shown, we could register the variable resolver in doAfterCompose
by use of
Page.addVariableResolver(VariableResolver).
Wire CDI-managed Beans
The approaches to work with CDI are similar to the approaches for Spring, except the variable resolver for CDI is DelegatingVariableResolver, and the Java class has to be annotated with CDI annotations.
zscript and Variable Resolver
By default, variables defined in both zscript and variable resolvers will be checked[1]. There might be some performance penalty if you have too much zscript code, or your variable resolver is too slow.
You could turn them off by passing false to the second and third argument of GenericForwardComposer.GenericForwardComposer(char, boolean, boolean):
public class MyComposer extends GenericForwardComposer {
public MyComposer() {
super('$', false, false);
}
}
Notice if you disable the wiring of EL variables (i.e., variables defined in a variable resolver), you can't wire the Spring-managed beans as described in the previous section.
- ↑ It will be default to false in ZK 6 for better performance.
ID Space
For components that are inside of another ID space, you could use id1$id2$id3
to access it. More precisely, it will cause GenericForwardComposer to look for id1
in the same ID space as the applied component, and then look for, if found and it is another ID space, id2
, and so on. For example, you could find the textbox by inner$input
.
<window apply="foo.MyComposer">
<window id="inner">
<textbox id="input"/>
...
Here is another example: suppose have two ZUL files:
Main file | Included file - includeme.zul |
---|---|
<window id="mywindow" apply="MyComposer">
<include id="i" src="includeme.zul" />
</window>
|
<textbox id="username" />
|
To access the textbox "username" from "MyComposer", you could specify:
public class MyComposer extends GenericAutowireComposer {
Textbox i$username;
...
}
Version History
Version | Date | Content |
---|---|---|