简体   繁体   中英

Problem with spring defined @ManagedProperty

I'm currently mantainning a Maven based JSF Web Application combined with Spring Framework and JPA and connected to a SQL Server database.

Inside the application, I created one @ManagedBean class defined with the @ViewScoped and @Scope("view") annotations.

This class is named AvisoRecaladaBean and it has 3 attributes defined with the @ManagedProperty annotation as follows:

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

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

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

The first and third attributes were used in other managed beans in the same application. Also, IUsuarioService and ISigcueAvisoRecaladaService are interfaces, each one implemented by one class defined with the @Service annotation. The class that implements the latter interface also has the @Transactional annotation. JsfUtil is a class also defined with @Service .

Also, I defined one Integer attribute named folioBusqueda and one List<SigcueCertAvisoRecalada> attribute named listado . SigcueCertAvisoRecalada is an entity class pointing to a table in the database mencioned in the beginning.

Each attribute mentioned above has it's getter and setter.

In the other hand, I created one XHTML page named avisoRecalada.xhtml, that works with the AvisoRecaladaBean managed Bean.

The XHTML page has, among other things, one Panel Grid defined as follows:

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

The actionListener inside the command button refeers to the following method in AvisoRecaladaBean

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

The Spring configuration is defined in an XML file defined as follows (I show only the important part):

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

The faces-config.xml has only the following managed-beans defined:

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

And it's resolver is defined as:

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

When I deploy the application using a WildFly 10 Application Server, I get no error messages. Also, I get no errors when I access the XHTML page.

However, when I input one value in the input text and push the command button, I get one NullPointerException . The stack trace indicates that the exception were launched when trying to execute the first line of buscarRegistro() .

After some debugging, I found that the avisoRecaladaService attribute was null, but the other two managed properties weren't .

I tried the following solutions with no avail

  1. Add and/or replace @ManagedProperty with @Autowired
  2. Use the @Qualifier annotation to name the bean (I named it "avisoRecaladaService" ) and use the current ApplicationContext to get the bean (Source: Spring Bean never set as ManagedProperty in JSF Bean ). I got a NoSuchBeanException with this solution:
WebApplicationContext webAppContext = ContextLoader.getCurrentWebApplicationContext();
avisoRecaladaService = (IAvisoRecaladaService) webAppContext.getBean("avisoRecaladaService");
  1. EDIT : Instantiate avisoRecaladaService directly. Not desirable. Also, autowired attributes of SigcueCertAvisoRecaladaService are null :
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. EDIT : Replace @ManagedAttribute with @Resource (Source: @ManagedProperty equivalent in Spring )
  2. Replace @ManagedAttribute with @Inject (same source as the previous solution)

Any advice for a definitive solution would be really much obligated.

EDIT

As requested by Kukeltje, according to the application's pom.xml, the involved libraries are the following:

  • jboss-jsf-api 2.2
  • jboss-el-api 3.0 spec
  • spring-core 4.2.8
  • spring-web 4.2.8
  • spring-expression 4.2.8
  • spring-context-support 4.2.8
  • spring-web-mvc 4.2.8
  • JDK 1.8.0_191
  • Developed in Eclipse Oxygen (if relevant)

SOLVED

Thanks to a partner of mine, We discovered that @ManagedProperty is very sensitive about names. The name of the bean must be exactly the same as the class, with it's first letter in lower case. If the object is an interface instance, like in my case, it must be the name of the class implementing it.

So, I had to change this:

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

Into this:

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

Thanks to all of you for reading this and I hope this helps to similar problems in the future

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM