using #Model `javax.enterprise.inject.Model` for JSF backing bean? [duplicate] - cdi

This question already has answers here:
How to choose the right bean scope?
(2 answers)
Closed 2 years ago.
I'm trying to implement JSF backing beans using CDI beans as suggested by the depreciation of #ManagedBean and it's scope annotations, but I'm struggling with the right use examples, I'm trying to implement view backing bean with #Model (javax.enterprise.inject.Model) which is #Named #RequestScoped.
I found this question but it's using a ViewScope bean, how would I implement the same functionality with RequestScoped (Preferably #Model), What is best practice use of #Model in general?
Edit 1:
I tried creating a new Product in the EditProduct PostConstruct:
#Model
public class EditProduct {
private Product product; // +getter +setter
#Inject
private ProductService productService;
#PostConstruct
public void init(){
product = new Product();
}
public String save() {
productService.save(product);
return "/products?faces-redirect=true";
}
// ...
}
and then setting the product via
<f:viewParameter name="product-id" target="#{editProduct.product}"
converter="#{productConverter}" />
it's working but I'm looking for a best practice.

A request scoped backing bean is meant to keep the application memory footprint as low as possible hence using them for supporting views with #Model annotation makes a lot of sense, the draw back is having to reach for the persistence data storage on every request that deals with data so a best use case for #Model bean is:
Basically every thing.
things like:
Events handling for JSF pages
Lazy loading of data
Validation and converting and other code execution
ETC.... yes every thing else
Those things are easily done best in request scoped beans, but then what are the roles of other beans?
In simplistic terms we can assume:
#ViewScoped to support data heavy pages where user edits data with many interactions and each interaction is a request but hitting the database for each one will be costly.
#SessionScoped for session data, authentication, credentials and configuration for the user.
#ApplicationScoped the state-full singleton of CDI.
.... each other scope has it's uses, but for a good web application #Model should be the default and the others has specific uses cases.

You should be able to also add the #Named annotation and it will be exposed as editProduct.
https://memorynotfound.com/cdi-managed-bean-example-with-named/
EDIT: See comment

Related

Primefaces: <p:dataTable>'s data source change or concurrency operation will cause the inconsistent parameter passing from jsf-el to backing bean [duplicate]

I've a data table as below:
<h:dataTable value="#{bean.items}" var="item">
I'd like to populate it with a collection from the database obtained from a service method so that it is immediately presented when the page is opened during an initial (GET) request. When should I call the service method? And why?
Call it before page is loaded. But how?
Call it during page load. How?
Call it in the getter method. But it is called multiple times.
Something else?
Do it in bean's #PostConstruct method.
#ManagedBean
#RequestScoped
public class Bean {
private List<Item> items;
#EJB
private ItemService itemService;
#PostConstruct
public void init() {
items = itemService.list();
}
public List<Item> getItems() {
return items;
}
}
And let the value reference the property (not method!).
<h:dataTable value="#{bean.items}" var="item">
In the #PostConstruct you have the advantage that it's executed after construction and dependency injection. So in case that you're using an EJB to do the DB interaction task, a #PostConstruct would definitely be the right place as injected dependencies would not be available inside a normal constructor yet. Moreover, when using a bean management framework which uses proxies, such as CDI #Named, the constructor may or may not be called the way you expect. It may be called multiple times during inspecting the class, generating the proxy, and/or creating the proxy.
At least do not perform the DB interaction job in the getter, unless it's lazy loading and you really can't do anything else. Namely, it would be invoked during every iteration round. Calling the service method during every iteration round is plain inefficient and may end up in "weird" side effects during presentation and postbacks, such as old values from DB seemingly still sticking around in the model instead of new submitted values.
If you rely on GET request parameters, then use <f:viewParam> and <f:viewAction> instead. See also Creating master-detail pages for entities, how to link them and which bean scope to choose.
If you want to preserve the model (the items property) across postbacks on the same view (e.g. CRUD table/dialog), then make the bean #ViewScoped, else the model won't be in sync with the view when the same model is concurrently edited elsewhere. See also Creating master-detail table and dialog, how to reuse same dialog for create and edit.
If you utilize JPA's #Version feature on the model, then you can catch OptimisticLockException to deal with it and show a message like "The data has been edited by someone else, please refresh/review if the desired changes are as intended". See also Letting the presentation layer (JSF) handle business exceptions from service layer (EJB).
See also:
Why JSF calls getters multiple times
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to choose the right bean scope?
JSF Controller, Service and DAO

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.

preRenderView not working during a method call [duplicate]

I've a data table as below:
<h:dataTable value="#{bean.items}" var="item">
I'd like to populate it with a collection from the database obtained from a service method so that it is immediately presented when the page is opened during an initial (GET) request. When should I call the service method? And why?
Call it before page is loaded. But how?
Call it during page load. How?
Call it in the getter method. But it is called multiple times.
Something else?
Do it in bean's #PostConstruct method.
#ManagedBean
#RequestScoped
public class Bean {
private List<Item> items;
#EJB
private ItemService itemService;
#PostConstruct
public void init() {
items = itemService.list();
}
public List<Item> getItems() {
return items;
}
}
And let the value reference the property (not method!).
<h:dataTable value="#{bean.items}" var="item">
In the #PostConstruct you have the advantage that it's executed after construction and dependency injection. So in case that you're using an EJB to do the DB interaction task, a #PostConstruct would definitely be the right place as injected dependencies would not be available inside a normal constructor yet. Moreover, when using a bean management framework which uses proxies, such as CDI #Named, the constructor may or may not be called the way you expect. It may be called multiple times during inspecting the class, generating the proxy, and/or creating the proxy.
At least do not perform the DB interaction job in the getter, unless it's lazy loading and you really can't do anything else. Namely, it would be invoked during every iteration round. Calling the service method during every iteration round is plain inefficient and may end up in "weird" side effects during presentation and postbacks, such as old values from DB seemingly still sticking around in the model instead of new submitted values.
If you rely on GET request parameters, then use <f:viewParam> and <f:viewAction> instead. See also Creating master-detail pages for entities, how to link them and which bean scope to choose.
If you want to preserve the model (the items property) across postbacks on the same view (e.g. CRUD table/dialog), then make the bean #ViewScoped, else the model won't be in sync with the view when the same model is concurrently edited elsewhere. See also Creating master-detail table and dialog, how to reuse same dialog for create and edit.
If you utilize JPA's #Version feature on the model, then you can catch OptimisticLockException to deal with it and show a message like "The data has been edited by someone else, please refresh/review if the desired changes are as intended". See also Letting the presentation layer (JSF) handle business exceptions from service layer (EJB).
See also:
Why JSF calls getters multiple times
What can <f:metadata>, <f:viewParam> and <f:viewAction> be used for?
How to choose the right bean scope?
JSF Controller, Service and DAO

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...

Resources