need clarification on JSF and managed beans - jsf

i have some behavior im unable to understand,
so i started to recently learn JSF, im using TOMCAT 6, now i created JSF file , and i created two Managed Beans under different packages, but each bean have the same name.
1. First bean is com.app.TestBean.
2. Second bean is jsftest.TestBean.
now when i call my JSF page, i get to invoke the first bean, if i restart the TOMCAT , i get the result of the second bean, can any body explain what im doing wrong here ?

Unless you specified their name explicitely, the beans have their name/id assigned based on they class name.
So TestBean would be: testBean
So if you have conflicting class names, you need to explicitely specify their (different) name.
For example if you are using the annotation (which i suspect is the case), you need to do
package com.app;
#ManagedBean("testBean1")
public class TestBean {
...
}
and the other bean
package jsftest;
#ManagedBean("testBean2")
public class TestBean {
...
}
And then use either #{testBean1} or #{testBean2}

Related

How to have one instance of Backing Bean per Browser tab?

My environment: Java 7/JSF 2.1/PrimeFaces 6.1.
My goal: to have a certain page of my application instantiated many times, one for each browser tab, each one with a different context.
My problem: everytime I open a second browser tab requesting from the same url, but with different object id, the previous one is destroyed, so only one backing bean instance is kept alive.
How do I know that: In my backing bean I have one method annotated with #PosConstruct and other with #PreDestroy, so I can track the life cicle of the instances.
My backing bean is annotated as follows:
#ViewController
public class MyBackingBeanMB extends AbstractBackingBeanMB {
private static final long serialVersionUID = 1L;
// many fields and methods
}
The #ViewController annotation is provided by the application framework I have to use. Such an annotation is declared as:
#Named
#Controller
#Stereotype
#ViewScoped // For me, this should do the trick, but...
#Target(value={TYPE})
#Retention(value=RUNTIME)
#Inherited
public #interface ViewController {
}
Update 1:
The #Controller annotation is also provided by the framework I use and is declared as:
#InterceptorBinding
#Inherited
#Target({ TYPE, METHOD })
#Retention(RUNTIME)
public #interface Controller {
}
Any ideas of what could be wrong?
TIA.
After some digging in the Internet I found Apache DeltaSpike, which provider a new kind of managed bean scope, WindowScoped.
Managed beans annotated with #WindowScoped` operate just like I wanted, providing me with the exact behaviour I needed and it is absolutely compatible with the framework I have to use.

CDI Bean Scoping during Injection is not working

I want to give on-the-go scope to a pojo bean in CDI during injection.
I created a plain bean and injected the same as #javax.enterprise.context.ApplicationScoped in a #javax.faces.bean.ViewScoped Managed Bean like this:
#Inject
#ApplicationScoped
Pojo pojo;
// POJO Class
Class Pojo {
private String var;
public Pojo() {
}
public String getVar() {
return var;
}
public void setVar(String var) {
this.var = var;
}
}
The Pojo bean's populated values could not be restored in a new view bean when I inject using the same syntax.
But it works when I use #ApplicationScoped in the class declaration instead, followed by non-scoped injection, like this:
#ApplicationScoped
Class Pojo {
private String var;
Injection:
#Inject
Pojo pojo;
The former case gets resolved when I make a producer and qualifier but I feel this would be an overhead I should do without. Being new to CDI, I want to ask what I am really missing here.
Scope and Context management are a very powerful feature in CDI. It is also part of the business logic of the components (an #ApplicationScoped bean won't be developed the same way than a #RequestScoped), that's why the scope is link to bean definition.
An injection point is only a place where you consume a bean and not a place where you define it, so there is no way to define the scope of a bean at the injection point at spec level.
Now if you really want to use this feature you could develop a portable extension to add this possibility. But you'll probably have to work on a qualifier system as well since scope is not used in bean resolving process (i.e. 2 beans with the same type in different scope will be in conflict for a given injection point if they don't have specific qualifier).

Is there anything wrong with using a CDI ViewScoped bean for caching information used in multiple pages?

All of my pages are backed their own ViewScoped bean, but I'm finding that there are a lot of similar methods used on these pages. For example, a user may want to view dates in their preferred time zone so each time a page is loaded, the DB is queried for what their preferred time zone is.
So my initial thought was to create a ViewScoped bean to manage this. The timeZone value would be only be "good" for the lifetime of the page and they would be lazy-loaded to avoid unnecessary database hits:
#Named
#ViewScoped
public class Preference implements Serializable {
#Inject
private SessionManager sessionManager;
#EJB(name = "PreferencesReadFacade")
private PreferencesReadFacadeRemote prefReadFacade;
private HashMap<String, Object> cache = new HashMap<>();
/**
* #return the user's TimeZone preference
*/
public String getTimeZone() {
if(cache.get("TimeZone") == null) {
cache.put("TimeZone", prefReadFacade.getUserPreference(sessionManager.getUserId(), "TimeZone").toString());
}
return cache.get("TimeZone").toString();
}
}
Usage:
<h:outputText value="#{preference.timeZone}"/>
Is there anything wrong with this type of methodology? Is there a better way of doing something like this?
EDIT: Would like to add that I'm using ICEfaces and Omnifaces so if there are resources in these libraries at my disposal, I'm certainly open to using those.
Your approach is bsolutely correct - you may reuse the same bean in multiple pages regardless of its scope. If those pages are in the same scope, a bean would be reused, otherwise a new bean would be created with an empty cache. If the scope is ViewScoped, the bean would be recreated for every page, hence DB would be accessed first when the data is needed on after a page loads.
You may also make your common bean a base bean of other viewscoped beans, which are constructed for a particular page (they must remain viewscoped).
Or, you may inject your Preference bean into any other Named bean, which is used in your pages. In this way, you may inject it to a bean with any scope, but CDI will always give you the same bean for a view (within viewscope), but different when you redirect to a new page.
But your solution is equally correct, if not even better.
You can create one #SessionScoped bean and hold there user preferences like time zone. Then #Inject it to your #ViewScoped beans and get time zone from #SessionScoped. As long as http session lives, the DB query will be done only once in the user session if you do it in #PostConstruct and assign to variables.

Unexpected JPA SELECT statements logged when JSF page submitted [duplicate]

This question already has answers here:
Why JSF calls getters multiple times
(9 answers)
Closed 7 years ago.
I'm using Glassfish Server 4.1 with bundled JSF. I've enabled JPA FINE logging in "persistence.xml".
I have this Facelets page:
<p:dataTable var="customer" value="#{customerService.customers}">
</p:dataTable>
<h:form>
<h:commandButton value="Test"/>
</h:form>
(Note that that's really all there is: I haven't associated an action with the button, or added columns to the table, and if I do, the behaviour I'm about to describe doesn't change. Also recall that default render behaviour is #none.)
And this Stateless EJB (with #Named so that the page can refer to it directly):
#Stateless
#Named
public class CustomerService {
#PersistenceContext
private EntityManager em;
public List<Customer> getCustomers() {
return em.createNamedQuery("Customer.findAll", Customer.class).getResultList();
}
...
When I load the page, the following message appears in the log:
Fine: SELECT ID, CUSTOMERNAME, EMAIL, PAID, QUANTITY, TYPE FROM CUSTOMER
So far so good. When I click the button though, this appears in the logs:
Fine: SELECT ID, CUSTOMERNAME, EMAIL, PAID, QUANTITY, TYPE FROM CUSTOMER
Fine: SELECT ID, CUSTOMERNAME, EMAIL, PAID, QUANTITY, TYPE FROM CUSTOMER
... Same message appears five more times ...
The Customers table is empty.
Can anyone reproduce or explain this behaviour? One SELECT for page load makes sense, but seven SELECTS for form submit is confusing.
UPDATE
The behaviour is unchanged if I move the EJB into a ViewScoped JSF backing-bean and update the Facelets page to use it:
#ManagedBean // javax.faces.bean.
#ViewScoped
public class BackingBean {
#EJB
private CustomerService cs;
public List<Customer> getCustomers() {
return cs.getCustomers();
}
}
I think the problem is in the scope you are using in the bean, let me quote this from other question:
If it's CDI via #Named, then it defaults to #Dependent, as mentioned in Weld documentation:
Finally, CDI features the so-called dependent pseudo-scope. This is the default scope for a bean which does not explicitly declare a scope type.The effect is that the bean instance is newly created on every single EL expression. So, imagine a login form with two input fields referring a bean property and a command button referring a bean action, thus with in total three EL expressions, then effectively three instances will be created.
Now, how do we solve it? May be you should try another scope for your bean depending on your requirements, Check out this documentation about Scopes and context in JSF.
As Tiny explained in a comment on my question, the extra logging is occurring because I placed business logic inside the getter method used by the Facelets page. It is usually frowned upon to put business logic in the accessors (getter and setter) methods used by Facelets pages, as these methods are used by the JSF framework and you have little control over when and how often they are called.
In this case the issue can be "fixed" by initializing customers in the #PostConstruct method of a JSF view-scoped backing-bean:
#PostConstruct
public void init() {
customers = customerService.getCustomers();
}
public List<Customer> getCustomers() {
return customers;
}
This is a more conventional set-up, but I was trying to get by without a JSF backing-bean.
If someone can explain why the JSF framework is calling the method seven times, which seems arbitrary, I would definitely mark that answer correct, but in the meantime I am satisfied with this.
UPDATE
The explanation for the exact number of calls, seven, is probably similar to this answer, Why is the getter called so many times by the rendered attribute?:
The getter calls are all done by rendered="#{selector.profilePage ==
'some'}" during the render response phase. When it evaluates false
the first time, in UIComponent#encodeAll(), then no more calls
will be done. When it evaluates true, then it will be re-evaluated
six more times in the following sequence...

jsf multiple instances managed bean for multiple tabs

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?

Resources