event change jsf primefaces constructor cdi glassfish-4

jsf - change - onload primefaces



El constructor del bean administrado CDI se invoca dos veces al abrir la página (1)

Estoy tratando de usar la muestra ChartBean de PrimeFaces. Esta es la vista:

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

Este es el frijol:

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

Mientras lo ejecuto, noté que el constructor de este bean se invoca dos veces al abrir la página. Los registros muestran lo siguiente:

INFORMACIÓN: ChartBean construido
INFORMACIÓN: ChartBean construido

Entonces el bean fue instanciado dos veces. ¿Cómo es esto causado y cómo puedo evitar eso? Estoy interactuando con la base de datos para obtener algunos datos para mostrar en la interfaz de usuario y de esta manera los datos se obtienen innecesariamente dos veces.


La primera creación es el contenedor que crea un proxy con ámbito de su bean. El proxy con ámbito es un objeto que extiende su bean y se inyecta siempre que algún otro componente necesite su bean. Sin embargo, sus métodos no ejecutan la lógica real, sino que delegan su ejecución en la instancia contecta correcta de su bean. Un ejemplo aclarará:

Supongamos 2 solicitudes, R1, R2. Debe haber 2 instancias de ChartBean , B1 y B2. Digamos que otro componente, C, depende de ChartBean . El campo relevante de C debe inyectarse con una instancia de ChartBean en el momento de inicio de la aplicación y llamar a la instancia de bean correcta en el momento de la ejecución. PERO en la hora de inicio de la aplicación no hay solicitud y ciertamente no B1, B2. ¿Qué hace el contenedor? Crea el proxy con ámbito y lo inyecta a quien lo necesite. Luego, cada vez que se llama a ChartBean.method() , se llama al proxy que decide cuál es el bean correcto para llamar (B1 para R1, B2 para R2, lanza excepción si ninguna solicitud está activa, por ejemplo, llamada desde un MessageDrivenBean ).

Habiendo dicho lo anterior: NO EJECUTE LA LÓGICA EMPRESARIAL EN CONSTRUCTORES EN JAVA EE COMPONENTES , porque los constructores pueden ser llamados desde el sistema / contenedor. Use un método @PostConstruct lugar:

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

Por cierto, puede verificar que se llama al constructor desde una implementación de proxy imprimiendo el nombre de clase en el constructor:

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

La primera vez que se llame, será una clase diferente a la suya.