The
none scoped beans lives to serve other beans
The
none scoped beans lives to serve other beans. The none scope seems to be the "black
sheep" of JSF scopes. Even its name doesn't inspire something useful.
Practically, a managed bean in this scope lives as long as a single EL
expression evaluation and is not visible in any JSF page - JSF will not store
it, which means that the caller can use it only if it stores the evaluated
reference itself. If the application scope lives the longest, this scope lives
the shortest. But, if you inject the none scoped managed beans in other managed
beans, then they will live as long as their hosts. The none scoped objects used in the
configuration file indicate managed beans that are used by other managed beans
in the application. So, whenever you need a humble managed bean that is ready
to be a part of a cool scope, such as a request or a session, you can annotate
it with @NoneScoped, available
in the
javax.faces.bean package. Moreover, objects with the none scope can use other
objects with the none scope.
Let's
see a simple example:
@ManagedBean
@NoneScoped
public class
InitBean implements Serializable {
private static final Logger LOG =
Logger.getLogger(InitBean.class.getName());
private int init;
public InitBean() {
LOG.info("InitBean#Constructor invoked
...");
init = 5;
}
public int getInit() {
return init;
}
public void setInit(int init) {
this.init = init;
}
}
<h:body>
Current init value: #{initBean.init}
Current init value: #{initBean.init}
Current init value: #{initBean.init}
</h:body>
Since
we are using the init property in
three ELs, the none scoped bean will be constructed three times (three different
instances). But, this is happening in a
single request! So, for each EL that uses a property from a none scoped bean,
JSF will create a separate instance of that bean!
But, as we said above, the none scoped beans lives to serve other beans. Per example, let's inject the InitBean into a session bean, CountBean, as below:
@ManagedBean
@SessionScoped
public class
CountBean implements Serializable {
@ManagedProperty(value =
"#{initBean}")
private InitBean initBean;
private static final Logger LOG = Logger.getLogger(CountBean.class.getName());
private int count;
public CountBean() {
LOG.info("CountBean#Initializing counter
...");
count = 0; // will be override in the init()
method
}
@PostConstruct
public void init() {
LOG.info("CountBean#Initializing counter
with @PostConstruct ...");
count = initBean.getInit();
}
public void increaseCount() {
count++;
initBean.setInit(count);
LOG.log(Level.INFO, "Current value:
{0}", count);
}
public InitBean getInitBean() {
return initBean;
}
public void setInitBean(InitBean initBean) {
this.initBean = initBean;
}
public int getCount() {
return count;
}
public void setCount(int count) {
this.count = count;
}
}
And,
we adjust the JSF page as below:
<h:body>
Current init value: #{initBean.init}
Current init value: #{initBean.init}
Current init value: #{initBean.init}
<hr/>
Current init value (via session bean): #{countBean.initBean.init}
Current count value (via session bean):
#{countBean.count}
<h:form>
<h:commandButton value="Count"
action="#{countBean.increaseCount()}"/>
</h:form>
</h:body>
Now,
notice that the injected instance lives as long as its "host" lives -
the session scoped bean, CountBean. You can
notice this from the below two screenshots:
Below
you can see the diagrams for injecting JSF none scoped beans exemplified on a
session scoped bean:
So, once you understand the none scope, it starts to look pretty useful. Compared to the rest of scopes this one is quite flexible. It allows us to "attach" a scope to scope-less data via injection. Practically, we can use @ManagedProperty in any bean of any scope for injecting scope-less data and expose them further as bean properties. Per example, in the same time, we can inject the a none scoped bean in a request, a session and an application scoped bean without the need to duplicate the bean and annotate them with acceptable scopes to be eligible for injection (remember that JSF doesn't allow us to use objects that have shorter lifespan than the objects you are calling it from).
See
you in the next post about the CDI singleton pseudo-scope.
Niciun comentariu :
Trimiteți un comentariu