CDI"

From Documentation
m ((via JWB))
 
(3 intermediate revisions by the same user not shown)
Line 12: Line 12:
 
ZUL provides a feature called [[ZK Developer's Reference/UI Composing/ZUML/EL Expressions#Variable Resolver| variable resolver]] that allows users to access CDI bean using EL expression. To do this, simply put the below directive on top of a ZUML page:
 
ZUL provides a feature called [[ZK Developer's Reference/UI Composing/ZUML/EL Expressions#Variable Resolver| variable resolver]] that allows users to access CDI bean using EL expression. To do this, simply put the below directive on top of a ZUML page:
  
'''<tt>&lt;?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver" ?&gt;</tt> '''
+
'''<code>&lt;?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver" ?&gt;</code> '''
  
Then, in the rest of your page, you can access a CDI bean which has <tt>@Named</tt> directly using its '''bean EL name'''.  
+
Then, in the rest of your page, you can access a CDI bean which has <code>@Named</code> directly using its '''bean EL name'''.  
  
 
'''Session scoped bean'''
 
'''Session scoped bean'''
<source lang="java" high="1">
+
<source lang="java" highlight="1">
 
@SessionScoped @Named
 
@SessionScoped @Named
 
public class UserPreference implements Serializable{
 
public class UserPreference implements Serializable{
Line 27: Line 27:
  
 
'''Application scoped bean'''
 
'''Application scoped bean'''
<source lang="java" high="1">
+
<source lang="java" highlight="1">
 
@ApplicationScoped @Named
 
@ApplicationScoped @Named
 
public class SystemConfiguration implements Serializable{
 
public class SystemConfiguration implements Serializable{
Line 38: Line 38:
  
 
'''Access bean using EL in a ZUL'''
 
'''Access bean using EL in a ZUL'''
<source lang="xml" high="1,5, 9">
+
<source lang="xml" highlight="1,5, 9">
 
<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver"?>
 
<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver"?>
 
...
 
...
Line 55: Line 55:
 
==  Wire a CDI bean in a Composer ==
 
==  Wire a CDI bean in a Composer ==
  
It is likely that we need to use a CDI bean in a composer, for example calling a service layer object to perform business logic. If a composer is a CDI bean, we can simply use <tt>@Inject</tt> to inject all collaborators. However, we do not recommend this approach as explained in previously.  
+
It is likely that we need to use a CDI bean in a composer, for example calling a service layer object to perform business logic. If a composer is a CDI bean, we can simply use <code>@Inject</code> to inject all collaborators. However, we do not recommend this approach as explained in previously.  
  
ZK provides another approach to wire a CDI bean in a composer which is not a CDI bean. With help of <tt>org.zkoss.zkplus.spring.DelegatingVariableResolver</tt> and <tt>@WireVairable</tt>,  we can inject CDI beans into a composer. There are two ways to apply a variable resolver to a composer. We can  
+
ZK provides another approach to wire a CDI bean in a composer which is not a CDI bean. With help of <code>org.zkoss.zkplus.spring.DelegatingVariableResolver</code> and <code>@WireVairable</code>,  we can inject CDI beans into a composer. There are two ways to apply a variable resolver to a composer. We can  
  
 
<ol>
 
<ol>
 
<li>Put it in a zul with directive mentioned in the previous section or,</li>
 
<li>Put it in a zul with directive mentioned in the previous section or,</li>
<li>In a Java class with annotation, <tt>@VariableResolver</tt> then apply the annotation, <tt>@WireVariable</tt> on the variables which we want to inject CDI beans to.</li>
+
<li>In a Java class with annotation, <code>@VariableResolver</code> then apply the annotation, <code>@WireVariable</code> on the variables which we want to inject CDI beans to.</li>
 
</ol>
 
</ol>
  
Line 68: Line 68:
  
 
'''A composer injected with a CDI bean'''
 
'''A composer injected with a CDI bean'''
<source lang="java" high="3">
+
<source lang="java" highlight="3">
  
 
public class ResolverComposer extends SelectorComposer<Window> {
 
public class ResolverComposer extends SelectorComposer<Window> {
Line 89: Line 89:
  
 
'''A ZUL with CDI variable resolver'''
 
'''A ZUL with CDI variable resolver'''
<source lang="xml" high="1">
+
<source lang="xml" highlight="1">
  
 
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
 
<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
Line 100: Line 100:
 
== Wire a CDI bean in a ViewModel ==
 
== Wire a CDI bean in a ViewModel ==
  
Like wiring in a composer, we apply CDI variable resolver with directive and <tt>@WireVariable</tt> to inject CDI beans.
+
Like wiring in a composer, we apply CDI variable resolver with directive and <code>@WireVariable</code> to inject CDI beans.
  
<source lang="java" high="3,5">
+
<source lang="java" highlight="3,5">
  
 
public class MyViewModel{
 
public class MyViewModel{
Line 126: Line 126:
 
</source>
 
</source>
  
<source lang="xml" high="1,4">
+
<source lang="xml" highlight="1,4">
  
 
<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver"?>
 
<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver"?>
Line 141: Line 141:
 
Adding a variable resolver to a ZUL will make it available to all composers on the ZUL. If you only want to add a variable resolver to a specific composer (or ViewModel), you should apply the annotation  
 
Adding a variable resolver to a ZUL will make it available to all composers on the ZUL. If you only want to add a variable resolver to a specific composer (or ViewModel), you should apply the annotation  
  
'''<tt>@VariableResolver(org.zkoss.zkplus.cdi.DelegatingVariableResolver.class)</tt>'''
+
'''<code>@VariableResolver(org.zkoss.zkplus.cdi.DelegatingVariableResolver.class)</code>'''
  
on '''the class that inherits <tt>SelectorComposer</tt> or a ViewModel''', then, apply <tt>@WireVariable</tt> on variables like shown in the previous section.  
+
on '''the class that inherits <code>SelectorComposer</code> or a ViewModel''', then, apply <code>@WireVariable</code> on variables like shown in the previous section.  
  
 
Example code are as follows:
 
Example code are as follows:
  
<source lang="java" high="1,4">
+
<source lang="java" highlight="1,4">
 
@VariableResolver(org.zkoss.zkplus.cdi.DelegatingVariableResolver.class)
 
@VariableResolver(org.zkoss.zkplus.cdi.DelegatingVariableResolver.class)
 
public class MyComposer extends SelectorComposer<Window> {
 
public class MyComposer extends SelectorComposer<Window> {
Line 162: Line 162:
 
Developers might tend to make a composer (or a ViewModel) as a CDI bean, but we don't recommend this approach. Because none of CDI's copes matches correctly with the life cycle of the composers. The scope of a composer is "desktop" scope. It is shorter than "session" and longer than "prototype". Only ZK knows when to create composers (or ViewModel), so it's better to let composers be managed by ZK.
 
Developers might tend to make a composer (or a ViewModel) as a CDI bean, but we don't recommend this approach. Because none of CDI's copes matches correctly with the life cycle of the composers. The scope of a composer is "desktop" scope. It is shorter than "session" and longer than "prototype". Only ZK knows when to create composers (or ViewModel), so it's better to let composers be managed by ZK.
  
If you insist on making composers (or ViewModel) as CDI beans, <tt>@Dependent</tt> scope could be a feasible scope but you need to use with care; each time you try to resolve a composer bean, you will get a new instance of a composer. If the composer stores some states, it would cause inconsistency states among multiple composers.
+
If you insist on making composers (or ViewModel) as CDI beans, <code>@Dependent</code> scope could be a feasible scope but you need to use with care; each time you try to resolve a composer bean, you will get a new instance of a composer. If the composer stores some states, it would cause inconsistency states among multiple composers.
  
  
Line 170: Line 170:
  
 
=Version History=
 
=Version History=
{{LastUpdated}}
+
 
{| border='1px' | width="100%"
+
{| class='wikitable' | width="100%"
 
! Version !! Date !! Content
 
! Version !! Date !! Content
 
|-
 
|-

Latest revision as of 07:33, 8 July 2022


Overview

Contexts and Dependency Injection (CDI) is one of Java EE 6 features and is composed of a set of services designed for using with stateful objects. It also allows developers to integrate various kinds of objects in a loosely coupled and type safe way. We will talk about several ways of integration including injecting and accessing CDI beans under different conditions. We assume that readers have knowledge in basic CDI configuration and concept such as bean scope, we will therefore not cover those topics here. Please refer to Oracle's CDI tutorial.


Access a CDI Bean in a ZUL

ZUL provides a feature called variable resolver that allows users to access CDI bean using EL expression. To do this, simply put the below directive on top of a ZUML page:

<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver" ?>

Then, in the rest of your page, you can access a CDI bean which has @Named directly using its bean EL name.

Session scoped bean

@SessionScoped @Named
public class UserPreference implements Serializable{
...
}
  • User preference should be distinct for each user but shared among multiple requests. It is suitable to be a session scoped bean.


Application scoped bean

@ApplicationScoped @Named
public class SystemConfiguration implements Serializable{
...
}
  • As system configuration should be shared within the whole application, it should be an application scoped bean.


Access bean using EL in a ZUL

<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver"?>
...
			<hlayout>
				User Preference :
				<label id="sessionValue">${userPreference.value}</label>
			</hlayout>
			<hlayout>
				System Configuration :
				<label id="applicationValue">${systemConfiguration.value}</label>
			</hlayout>
...

Wire CDI beans

Wire a CDI bean in a Composer

It is likely that we need to use a CDI bean in a composer, for example calling a service layer object to perform business logic. If a composer is a CDI bean, we can simply use @Inject to inject all collaborators. However, we do not recommend this approach as explained in previously.

ZK provides another approach to wire a CDI bean in a composer which is not a CDI bean. With help of org.zkoss.zkplus.spring.DelegatingVariableResolver and @WireVairable, we can inject CDI beans into a composer. There are two ways to apply a variable resolver to a composer. We can

  1. Put it in a zul with directive mentioned in the previous section or,
  2. In a Java class with annotation, @VariableResolver then apply the annotation, @WireVariable on the variables which we want to inject CDI beans to.

Example code are as follow:


A composer injected with a CDI bean

public class ResolverComposer extends SelectorComposer<Window> {

	@WireVariable("normalOrderService")
	NormalOrderService orderService;
	
	@Wire("#number")
	private Label label;
	
	
	@Override
	public void doAfterCompose(Window comp) throws Exception {
		super.doAfterCompose(comp);
		label.setValue(Integer.toString(orderService.findAll().size()));
	}
	
}

A ZUL with CDI variable resolver

<?variable-resolver class="org.zkoss.zkplus.spring.DelegatingVariableResolver"?>
<window title="Access Bean with different scopes" border="normal" width="700px"
	apply="org.zkoss.reference.developer.spring.composer.ResolverComposer">
...
</window>

Wire a CDI bean in a ViewModel

Like wiring in a composer, we apply CDI variable resolver with directive and @WireVariable to inject CDI beans.

public class MyViewModel{

	@WireVariable
	private UserPreference userPreference;
	@WireVariable
	private ProductService productService;
	
	private List<String> productList;
	
	@Init
	public void doAfterCompose(Window comp) throws Exception {
		productList = productService.findAll();
	}

	public UserPreference getUserPreference() {
		return userPreference;
	}
	
}
<?variable-resolver class="org.zkoss.zkplus.cdi.DelegatingVariableResolver"?>
<window border="normal" width="500px"
	apply="org.zkoss.bind.BindComposer" 
	viewModel="@id('vm')@init('org.zkoss.reference.developer.composer.MyViewModel')">
...
</window>

Adding Variable Resolver to a Composer (or ViewModel)

Adding a variable resolver to a ZUL will make it available to all composers on the ZUL. If you only want to add a variable resolver to a specific composer (or ViewModel), you should apply the annotation

@VariableResolver(org.zkoss.zkplus.cdi.DelegatingVariableResolver.class)

on the class that inherits SelectorComposer or a ViewModel, then, apply @WireVariable on variables like shown in the previous section.

Example code are as follows:

@VariableResolver(org.zkoss.zkplus.cdi.DelegatingVariableResolver.class)
public class MyComposer extends SelectorComposer<Window> {

	@WireVariable
	private UserPreference userPreference;
...
}


Warning: Declare a Composer (or ViewModel) as a CDI bean

Developers might tend to make a composer (or a ViewModel) as a CDI bean, but we don't recommend this approach. Because none of CDI's copes matches correctly with the life cycle of the composers. The scope of a composer is "desktop" scope. It is shorter than "session" and longer than "prototype". Only ZK knows when to create composers (or ViewModel), so it's better to let composers be managed by ZK.

If you insist on making composers (or ViewModel) as CDI beans, @Dependent scope could be a feasible scope but you need to use with care; each time you try to resolve a composer bean, you will get a new instance of a composer. If the composer stores some states, it would cause inconsistency states among multiple composers.


Example Source Code

All source code of examples used in this chapter can be found here.

Version History

Version Date Content
6.5.0 November 2012 Rewrite for improvement.



Last Update : 2022/07/08

Copyright © Potix Corporation. This article is licensed under GNU Free Documentation License.