The managed CDI bean constructor is called twice when a page is opened.

I am trying to use a ChartBean sample from PrimeFaces. This is the view:

 <h:form> <p:layoutUnit position="center"> <p:lineChart id="linear" value="#{chartBean.linearModel}" legendPosition="e" title="Linear Chart" minY="0" maxY="1000" style="height:600px"/> </p:layoutUnit> </h:form> 

This is a bean:

 @Named @RequestScoped public class ChartBean implements Serializable { private CartesianChartModel categoryModel; private CartesianChartModel linearModel; public ChartBean() { System.out.println("ChartBean constructed"); createCategoryModel(); createLinearModel(); } // ... } 

While I run it, I noticed that the constructor of this bean runs twice when the page opens. Logs show the following:

INFO: Built by ChartBean
INFO: ChartBean Built

So, the bean was created twice. How is this caused and how can I avoid it? I interact with the database to get some data to display in the user interface, and thus the data is unnecessarily retrieved twice.

+3
source share
1 answer

The first creation is a container that creates a limited proxy for your bean. A proxy object with scope is an object that extends your bean and is introduced when any other component needs your bean. However, the methods do not execute the real logic, but delegate their execution to the correct conflicting instance of your bean. An example will explain:

Suppose 2 queries, R1, R2. There must be two instances of ChartBean , B1 and B2. Let's say another component, C, depends on ChartBean . An instance of ChartBean must be entered in the C field at application startup time and the correct bean instance must be ChartBean at run time. BUT at the time of launching the application there is no request and, of course, there is no B1, B2. What does the container do? He creates a trusted proxy and introduces it to those who need it. Then, when ChartBean.method() is called, it is called in the proxy server, which decides which correct bean to call (B1 for R1, B2 for R2, throw exception if no request is active, for example, called from MessageDrivenBean )

Having said the previous: DO NOT START BUSINESS LOGIC IN DESIGNERS IN JAVA EE COMPONENTS , since constructors can be called from the system / container. Use the @PostConstruct method @PostConstruct :

 ... public class ChartBean implements Serializable { public ChartBean() { // only construction logic here } ... @PostConstruct void postConstruct() { createCategoryModel(); createLinearModel(); } } 

By the way, you can verify that the constructor is called from the proxy implementation by printing the class name in the constructor:

  public ChartBean() { System.out.println("ChartBean as " + this.getClass().getName()); } 

At the first call, it will be a different class than yours.

+11
source

All Articles