is it possible to change the default scope of CDI Beans (dependent scope) to something else (like ApplicationScope)?
Thanks
There is no simple API call or configuration property to do that, but you can always write a portable extension to add or replace scope annotations by observing the ProcessAnnotatedTypeevent.
Related
could some explain what a none scope is and purpose of it?
Suppose if i have a bean in
request scope as r1
session scope as s1
application scope a1
and say i inject none scope bean n1 in to each of above scopes then i find that n1 gets
instantiated for each parent bean when ever its parent bean[r1/s1/a1] is instantiated.
none scope bean in a1 is available throughout in a1 since a1 is appl scope.
none scope bean in s1 is available only until s1 is not destroyed and when s1 is created
again n1 is instanciated and made available to it.
Is it correct?
and what the purpose of using it? only to avoid creating such bean our self?
many thanks
A bean with a <managed-bean-scope> of none or a #NoneScoped annotation will be created on every single EL expression referencing the bean. It isn't been stored by JSF anywhere. The caller has got to store the evaluated reference itself, if necessary.
E.g. the following in the view
<p>#{noneScopedBean.someProperty}</p>
<p>#{noneScopedBean.someProperty}</p>
<p>#{noneScopedBean.someProperty}</p>
on a none-scoped bean will construct the bean 3 (three) times during a request. Every access to the bean gives a completely separate bean which is been garbaged immediately after the property access.
However, the following in for example a session scoped bean
#ManagedProperty("#{noneScopedBean}")
private NoneScopedBean noneScopedBean;
will make it to live as long as the session scoped bean instance. You should only make sure that you access it in the view by #{sessionScopedBean.noneScopedBean.someProperty} instead.
So it may be useful when you want scope-less data being available as a managed property in an arbitrary bean.
I'm using #nonescoped when my "view logic" dont need to be in any scope but be referenced by another ManagedBean.
I'm working with Liferay, as I want to make my architecture and design independent of liferay, I create my services interfaces and Dto, but when you need to persistence data, Liferay need that the companyId and companyGroupId be sended from the view layer (in this case JSF).
To maintain independence, I did a "Adapter pattern" creating a ServiceLayer ManagedBean with #noneScope with an interface independent from Liferay. This way I can get the companyId and the companyGroupId needed by the Liferay Apis.
The advantage of using #noneScope is that you can use it as a #ManagedProperty in any bean of any scope.
#NoneScoped would be beneficial in the following scenario.
Assume that we have to inject the same bean in two different scoped beans, we can mark that bean as #NoneScoped. Say a bean BeanOne with #NoneScoped can be easily injected in any bean with any scope like #Request or #Session.
Without using #NoneScoped for BeanOne, we may have to duplicate the bean with different scopes and inject them accordingly.
I am working on JSF2.2 at my work place. My faces-config.xml has the resource bundle tag which helps me to assign a variable to a property file and use the variable in a EL.
<resource-bundle>
<base-name>properties.common</base-name>
<var>prop</var>
</resource-bundle>
I also found another way of achieving this by using the f:loadBundle tag like this
<f:loadBundle basename="properties.common" var="prop"/>
But this is a localized solution, meaning I would have to write this in every page.
Would this work if i define this in a template ? If yes, how do i achieve it.
Is there any other way that i can declare the resource globally with a variable to be used in an EL(like in the case of faces-config.xml)
Would this work if i define this in a template ?
Yes.
If yes, how do i achieve it.
Just do exactly as you said. Define it in a template.
Is there any other way that i can declare the resource globally with a variable to be used in an EL(like in the case of faces-config.xml)
Put it in request map yourself in (post)constructor of a request scoped bean which is referenced in the view.
ResourceBundle bundle = ResourceBundle.getBundle("properties.common", facesContext.getViewRoot().getLocale());
externalContext.getRequestMap().put("prop", bundle);
It can even be referenced as a property of a request scoped bean and this guarantees construction of the bean even if it's not referenced elsewhere in the view.
This is exactly what Iam looking for, see my post https://stackoverflow.com/questions/24461307/jsf-2-external-resource-bundle
ResourceBundle bundle = ResourceBundle.getBundle("properties.common",facesContext.getViewRoot().getLocale());
externalContext.getRequestMap().put("prop", bundle);
thanks all...
There is a managed bean(DemoManagedBean.java) which holds some data on the (sample.xhtml)XHTML page.
There is a redirection link in the sample.xhtml which opens a new tab of the same page(sample.xhtml) but with different data loaded.
Issue - since there is only one instance of the DemoManagedBean.java, therefore not able to process anything further i.e; changes on one tab affect all the other tabs.
Is there a way so that I can have a multiple instances for every tab holding the data for the particular tabs?
Thanks,
Dinesh
You control that by setting the right bean scope. In your particular case, you need to put the bean in the request scope or in the view scope, depending on if you need a per-view based state or not.
Using the standard JSF bean management API, that would be just this (no XML needed!):
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
#ManagedBean
#RequestScoped
public class DemoManagedBean {
// ...
}
When the #XxxScoped scope annotation is not specified, it defaults to #NoneScope. Your description however matches the session or application scope. Perhaps you've explicitly set the #SessionScoped or #ApplicationScoped annotation while not really understanding what you were actually doing. Or perhaps you're for some reason using Spring to manage beans, a Spring #Controller without any explicit scope specified defaults to application scope.
See also:
How to choose the right bean scope?
I migrated from 1.2 to 2.0 and I moved my managed bean names and scopes from the faces-config.xml to the beans using annotations.
One bean(sessionscoped) has an instance variable which gets the current session as such:
private HttpSession httpsess = (HttpSession)FacesContext.getCurrentInstance().getExternalContext().getSession(false);
And then I call the httpsess variable in any instance method to add stuff to the session. But once I made the annotation changes. The httpsess variable returns null. When I create the variable as a local variable it works fine. Why would this happen?
In JSF 2.x, the creation of HttpSession is postponed as much as possible to avoid unnecessary session creation. It will only be created when it is really needed. It's apparently not been created yet at the point you're calling it. Passing false to getSession() means that the container shouldn't auto-create it if it doesn't exist. So if it doesn't exist yet, it will just return null.
You need to pass true to getSession() instead.
HttpSession httpsess = (HttpSession) FacesContext.getCurrentInstance().getExternalContext().getSession(true);
See also:
ExternalContext#getSession(boolean) javadoc
Unrelated to the concrete problem, this is a code smell. What exactly do you need the HttpSession for? To get/set some attributes? Why not just make it a property of the current session scoped managed bean? A JSF session scoped managed bean is by itself already stored as a session attribute anyway.
I can't find any guidance on this question. I am writing a composite component that needs its own backing bean because it interacts with a data base.
The new component also needs to be able to set a value in some other backing bean as the result of some user action.
To do this, the question is do I have to write a #FacesComponent java class or a regular #Model/#Named (I use CDI annotations) type of bean? If you can use either, what is the advantage of one or the other?
Secondary question: will I be able to use CDI #Inject into a #FacesComponent to get my DAOs and such?
Update: I discovered that I can access cc.attr objects with the following code in a regular backing bean:
FacesContext fc = FacesContext.getCurrentInstance();
Object obj = fc.getApplication().evaluateExpressionGet(fc,
"#{cc.attrs.model.location}", Location.class);
So this allows me to obtain attributes. I haven't found out how I can write them yet.
So it seems that the only real reason to do a #FacesComponent is if you want to write rendering code that will output something the normal Facelets tags won't render. Is this correct?
I think BalusC responded to this basic question in this thread.
The main advantage is the ability of a #FacesComponent to access attributes that a UIComponent normally has access to, rather than trying to tie in with EL expressions executed in the bean.