【问题标题】:Problem with spring defined @ManagedProperty弹簧定义的问题@ManagedProperty
【发布时间】:2020-10-09 04:20:37
【问题描述】:

我目前正在维护一个基于 Maven 的 JSF Web 应用程序,结合 Spring Framework 和 JPA 并连接到 SQL Server 数据库。

在应用程序中,我创建了一个使用@ViewScoped@Scope("view") 注释定义的@ManagedBean 类。

这个类被命名为AvisoRecaladaBean,它有3个用@ManagedProperty注解定义的属性,如下所示:

@ManagedProperty("#{jsf2Util}")
private Jsf2Util jsf2Util;

@ManagedProperty("#{avisoRecaladaService}")
private ISigcueCertAvisoRecaladaService avisoRecaladaService;

@ManagedProperty("#{usuarioService}")
private IUsuarioService usuarioService;

第一个和第三个属性在同一应用程序的其他托管 bean 中使用。此外,IUsuarioServiceISigcueAvisoRecaladaService 是接口,每个接口都由一个使用@Service 注释定义的类实现。实现后一个接口的类也有@Transactional注解。 JsfUtil 是一个也用@Service 定义的类。

另外,我定义了一个名为folioBusquedaInteger 属性和一个名为listadoList<SigcueCertAvisoRecalada> 属性。 SigcueCertAvisoRecalada 是一个实体类,指向开头提到的数据库中的一个表。

上面提到的每个属性都有它的getter和setter。

另一方面,我创建了一个名为 avisoRecalada.xhtml 的 XHTML 页面,它与 AvisoRecaladaBean 托管 Bean 一起使用。

XHTML 页面有一个面板网格,定义如下:

<h:panelGrid columns="3">
    <label>Ingrese Número de Folio: *</label>
    <p:inputNumber placeholder="Folio del Aviso Recalada"
                   value="#{avisoRecaladaBean.folioBusqueda}"
                   required="true"
                   id="numeroFolio"/>
    <p:commandButton value="Obtener Certificado Aviso" 
                     actionListener="#{avisoRecaladaBean.buscarRegistro()}" 
                     update="idTablaAviso"/>
    <h:message for="numeroFolio" style="color:red"/>
</h:panelGrid>

命令按钮内的actionListener参考AvisoRecaladaBean中的如下方法

public void buscarRegistro() {
    SigcueCertAvisoRecalada item = avisoRecaladaService.findByFolio(folioBusqueda);
    listado.clear();
    if(item!=null) {
        listado.add(item);
    }
}

Spring 配置定义在一个 XML 文件中,定义如下(我只展示重要部分):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:jee="http://www.springframework.org/schema/jee"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xmlns:jpa="http://www.springframework.org/schema/data/jpa"
    xmlns:drools="http://drools.org/schema/drools-spring"   
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee.xsd
        http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd
        http://drools.org/schema/drools-spring http://anonsvn.jboss.org/repos/labs/labs/jbossrules/trunk/drools-container/drools-spring/src/main/resources/org/drools/container/spring/drools-spring-1.0.0.xsd
        http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring http://ehcache-spring-annotations.googlecode.com/svn/schema/ehcache-spring/ehcache-spring-1.2.xsd
        http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd
        http://www.springframework.org/schema/data/jpa
        http://www.springframework.org/schema/data/jpa/spring-jpa.xsd       
        ">      
    <context:component-scan base-package="cl.sernapesca" />
    <context:annotation-config />

    <!-- Bean definitions -->

    <tx:annotation-driven/> 
    <tx:jta-transaction-manager />  

    <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
        <property name="ignoreUnresolvablePlaceholders" value="true" />
        <property name="locations">
            <list>
                <value>classpath:singleSingOn.properties</value>
                <value>classpath:revision.properties</value>
                <value>classpath:ldapExternos.properties</value> 
            </list>
        </property>
    </bean>  

    <!-- View Scope para JSF2 -->
    <bean class="org.springframework.beans.factory.config.CustomScopeConfigurer">
        <property name="scopes">
            <map>
               <entry key="view">
                       <bean class="cl.sernapesca.mantenedorcentral.arquitectura.ViewScope" />
               </entry>
            </map>
        </property>
    </bean>

    <!-- More Bean definitions -->
</beans>

faces-config.xml 只定义了以下托管 bean:

<managed-bean>
  <managed-bean-name>currentDate</managed-bean-name>
  <managed-bean-class>java.util.Date</managed-bean-class>
  <managed-bean-scope>request</managed-bean-scope>
 </managed-bean>

它的解析器定义为:

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

当我使用 WildFly 10 应用服务器部署应用程序时,我没有收到任何错误消息。此外,当我访问 XHTML 页面时,我没有收到任何错误。

但是,当我在输入文本中输入一个值并按下命令按钮时,我得到一个NullPointerException。堆栈跟踪表明在尝试执行buscarRegistro() 的第一行时引发了异常。

经过一番调试,发现avisoRecaladaService属性为空,而其他两个托管属性却不是

我尝试了以下解决方案均无济于事

  1. 添加和/或替换@ManagedProperty@Autowired
  2. 使用@Qualifier注解命名bean(我将其命名为"avisoRecaladaService")并使用当前的ApplicationContext获取bean(来源:Spring Bean never set as ManagedProperty in JSF Bean)。我收到了NoSuchBeanException 这个解决方案:
WebApplicationContext webAppContext = ContextLoader.getCurrentWebApplicationContext();
avisoRecaladaService = (IAvisoRecaladaService) webAppContext.getBean("avisoRecaladaService");
  1. 编辑:直接实例化avisoRecaladaService。 不可取。此外,SigcueCertAvisoRecaladaService 的自动装配属性为空
public void buscarRegistro() {
        if(avisoRecaladaService==null)
            avisoRecaladaService=new SigcueCertAvisoRecaladaService();
        SigcueCertAvisoRecalada item = avisoRecaladaService.findByFolio(folioBusqueda);
        listado.clear();
        if(item!=null) {
            if(listado==null)
                listado=new ArrayList<>();
            listado.add(item);
        }
    }
  1. 编辑:将@ManagedAttribute 替换为@Resource(来源:@ManagedProperty equivalent in Spring
  2. @ManagedAttribute 替换为@Inject(与上一个解决方案的来源相同)

任何关于最终解决方案的建议都会非常有义务。

编辑

根据 Kukeltje 的要求,根据应用的 pom.xml,涉及到的库如下:

  • jboss-jsf-api 2.2
  • jboss-el-api 3.0 规范
  • 弹簧芯 4.2.8
  • 弹簧网 4.2.8
  • 弹簧表达式 4.2.8
  • spring-context-support 4.2.8
  • spring-web-mvc 4.2.8
  • JDK 1.8.0_191
  • 在 Eclipse Oxygen 中开发(如果相关)

【问题讨论】:

  • 您好,感谢您的详细描述(甚至可能有点过多)和代码片段。下次还请添加所涉及库的版本信息(以及相关的实现)(您可以编辑问题)。如果您最后一个公告列表中的“2”不起作用(modelOperations 应该是avisoRecaladaService?),它看起来与 JSF 或 EL 解析器无关,或者......纯弹簧的东西。 '1' 仅在将 bean 制成 spring 管理的而不是 JSF 管理的 bean 时才有帮助。而@ViewScoped@Scope("view") 在同一个bean 上并不“正确”(后者是多余的)
  • 是的,我在几分钟前替换了modelOperations。 @ViewScoped 和 @Scope("view") 在所有托管 Bean 上(我只是将它们复制到我的新类上)。就像我说的,beans.xml 文件的组件扫描标签涵盖了项目中的所有包。现在我正在尝试另一种解决方案,所以我更有可能必须编辑问题的描述。非常感谢。

标签: spring jsf managed-bean managed-property


【解决方案1】:

已解决

感谢我的一个合作伙伴,我们发现@ManagedProperty 对姓名非常敏感。 bean 的名称必须与类完全相同,并且它的第一个字母小写。如果对象是一个接口实例,就像我的例子,它必须是实现它的类的名称。

所以,我不得不改变这个:

@ManagedProperty("#{avisoRecaladaService}")
private ISigcueCertAvisoRecaladaService avisoRecaladaService;

进入这个:

@ManagedProperty("#{sigcueCertAvisoRecaladaService}")
private ISigcueCertAvisoRecaladaService sigcueCertAvisoRecaladaService;

感谢大家阅读本文,希望对以后遇到类似问题有所帮助

【讨论】:

  • 在我看来,这与 bla 与 'Bla` 之类的名称中的“敏感性”无关,而是关于无法基于接口“注入”。
猜你喜欢
  • 1970-01-01
  • 2012-05-22
  • 2015-08-05
  • 2012-05-15
  • 2012-11-19
  • 2013-10-15
  • 1970-01-01
  • 1970-01-01
  • 2018-10-12
相关资源
最近更新 更多