Integración de Spring JSF: ¿cómo inyectar un componente/servicio de Spring en JSF managed bean?


Entiendo que un bean administrado funciona como un controlador, porque su única tarea es "vincular" la capa de vista con el Modelo.

Para usar un bean como un bean administrado debo declarar @ManagedBeananotación, haciendo eso puedo comunicar JSF con bean directamente.

Si quiero inyectar algún componente (de Spring) en este ManagedBean tengo dos maneras posibles:

  1. Elija la propiedad en ManagedBean (como "BasicDAO dao") y declare @ManagedProperty(#{"basicDAO"}) encima de la propiedad. Haciéndolo, estoy inyectar el frijol "basicDAO" desde la primavera en el frijol manejado.

  2. Declarado @ Controller en la clase ManagedBean, entonces tendré @ManagedBean y @Controller anotaciones, todas juntas. Y en propiedad "BasicDAO dao" debo usar @Autowired desde la Primavera.

, Es mi entendimiento correcto?

Author: BalusC, 2013-08-22

3 answers

Hay otra forma de usar frijoles administrados por Spring en frijoles administrados por JSF simplemente extendiendo su frijol JSF desde SpringBeanAutowiringSupport y Spring manejará la inyección de dependencia.

@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean extends SpringBeanAutowiringSupport {

    @Autowired
    private SpringBeanClass springBeanName; // No setter required.

    // springBeanName is now available.
}
 3
Author: tylerdurden,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-30 22:15:50

@ManagedBean vs @Controller

En primer lugar, debe elegir un marco para administrar sus frijoles. Debe elegir JSF o Spring (o CDI) para administrar sus frijoles. Mientras que las siguientes obras, es fundamentalmente incorrecto:

@ManagedBean // JSF-managed.
@Controller // Spring-managed.
public class BadBean {}

Terminas con dos instancias completamente separadas de la misma clase de bean administrada, una administrada por JSF y otra administrada por Spring. No está directamente claro cuál en realidad se usaría en EL cuando usted lo hace referencia como #{someBean}. Si usted tiene el SpringBeanFacesELResolver registrado en faces-config.xml, entonces sería el administrado por Spring, no el administrado por JSF. Si no tienes eso, entonces sería el administrado por JSF.

También, cuando se declara un ámbito específico de frijol administrado por JSF, como @RequestScoped, @ViewScoped, @SessionScoped o @ApplicationScoped del paquete javax.faces.*, solo será reconocido y utilizado por @ManagedBean. No será entendido por @Controller ya que espera su propia anotación @Scope. El valor predeterminado es singleton (ámbito de aplicación) cuando esté ausente.

@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
@Controller // Spring-managed (without own scope, so actually becomes a singleton).
public class BadBean {}

Cuando hace referencia al bean anterior a través de #{someBean}, devolvería el bean con ámbito de aplicación administrado por Spring, no el bean con ámbito de vista administrado por JSF.


@ManagedProperty vs @Autowired

El @ManagedProperty específico de JSF funciona solo en frijoles administrados por JSF, es decir, cuando se está utilizando @ManagedBean. El @Autowired específico para la primavera solo funciona en frijoles administrados en primavera, es decir, cuando se usa @Controller. Por debajo de los enfoques son menos o más equivalentes y no puede ser mixto:

@ManagedBean // JSF-managed.
@RequestScoped // JSF-managed scope.
public class GoodBean {

    @ManagedProperty("#{springBeanName}")
    private SpringBeanClass springBeanName; // Setter required.
}
@Component // Spring-managed.
@Scope("request") // Spring-managed scope.
public class GoodBean {

    @Autowired
    private SpringBeanClass springBeanName; // No setter required.
}

Tenga en cuenta que cuando usted tiene la SpringBeanFacesELResolver registered in faces-config.xml as per the javadoc ,

<application>
    ...
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>

Y por lo tanto puede hacer referencia a los frijoles administrados de primavera en EL vía #{springBeanName}, entonces puede simplemente hacer referencia a ellos en @ManagedProperty también, ya que básicamente establece el resultado evaluado de la expresión EL dada. Al revés, inyectar un frijol administrado por JSF a través de @Autowired, no es compatible de ninguna manera. Sin embargo, puede usar @Autowired en un frijol administrado por JSF cuando manualmente registre la instancia de JSF managed bean en el contexto Spring autowirable como se muestra a continuación. Ver también Cómo integrar JSF 2 y Spring 3 (o Spring 4) muy bien para el truco.

@ManagedBean // JSF-managed.
@ViewScoped // JSF-managed scope.
public class GoodBean implements Serializable {

    @Autowired
    private SpringBeanClass springBeanName; // No setter required.

    @PostConstruct
    private void init() {
        FacesContextUtils
            .getRequiredWebApplicationContext(FacesContext.getCurrentInstance())
            .getAutowireCapableBeanFactory().autowireBean(this);

        // springBeanName is now available.
    }
}

@XxxScoped vs @Scope

Spring's @Scope tiene soporte limitado para los ámbitos JSF. No hay equivalente para JSF @ViewScoped. Básicamente, crearía sus propios alcances o se limitaría a registrar manualmente la instancia de JSF managed bean en el contexto autowirable de Spring, como se muestra arriba.

Y, desde el otro lado, Spring WebFlow fue tomado en JSF 2.2 a través de una nueva anotación @FlowScoped. Entonces, si ya está en JSF 2.2, no necesariamente necesita usar Spring WebFlow si solo desea el ámbito de flujo.


CDI - tratando de unificarlo todo

Desde Java EE 6, CDI se ofrece como alternativa estándar a Spring DI. Tiene respectivamente @Named y @Inject anotaciones para esto y también su propio conjunto de ámbitos. No estoy seguro de cómo interactúa con Spring ya que no uso Spring, pero @Inject funciona dentro de un @ManagedBean, y @ManagedProperty dentro de un @ManagedBean puede hacer referencia a un @Named bean. Por otro lado, @ManagedProperty no funciona dentro de un frijol @Named.

El propósito de CDI es unificar todos los diferentes marcos de gestión de bean en una sola especificación/inteface. Spring podría haber sido una implementación completa de CDI, pero optaron por implementarla solo parcialmente (solo JSR-330 javax.inject.* está soportado, pero JSR-299 javax.enterprise.context.* no). Véase también Soporte de primavera CDI? y este tutorial.

JSF se moverá a CDI para la gestión de frijol y deprecate @ManagedBean y amigos en una versión futura.

Véase también:

 69
Author: BalusC,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:10:44

La forma fácil de hacerlo es a través de XML. Usé @Component en ya hecho jsf managed bean pero @Autowired no funcionó porque managed bean ya estaba allí en faces-config.XML. Si es obligatorio mantener esa definición de frijol administrado junto con su propiedad administrada en el archivo xml, se sugiere agregar el frijol de primavera como otra propiedad administrada dentro de la etiqueta de frijol administrado. Aquí el frijol de primavera se define en spring-config.xml (puede ser autowired en algún lugar alternativamente). por favor refiérase https://stackoverflow.com/a/19904591/5620851

Editado por mí. Sugiero implementarlo por completo a través de annotation @ Managed y @ Component o a través de xml para ambos.

 1
Author: hi.nitish,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:25