Проблема с Spring, определенная @ManagedProperty - PullRequest
0 голосов
/ 19 июня 2020

В настоящее время я использую веб-приложение JSF на основе Maven в сочетании со Spring Framework и JPA и подключено к базе данных SQL сервера.

Внутри приложения я создал один класс @ManagedBean, определенный с помощью аннотаций @ViewScoped и @Scope("view").

Этот класс называется AvisoRecaladaBean и имеет 3 атрибута, определенных с помощью аннотации @ManagedProperty следующим образом:

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

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

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

Первый и третий атрибуты использовались в других управляемых bean-компонентах в то же приложение. Кроме того, IUsuarioService и ISigcueAvisoRecaladaService - это интерфейсы, каждый из которых реализуется одним классом, определенным с помощью аннотации @Service. Класс, реализующий последний интерфейс, также имеет аннотацию @Transactional. JsfUtil - это класс, также определенный с @Service.

Кроме того, я определил один атрибут Integer с именем folioBusqueda и один атрибут List<SigcueCertAvisoRecalada> с именем listado. SigcueCertAvisoRecalada - это класс сущности, указывающий на таблицу в базе данных, упомянутую в начале.

Каждый атрибут, упомянутый выше, имеет свои методы получения и установки.

С другой стороны, я создал один X HTML страница с именем avisoRecalada.x html, которая работает с управляемым компонентом AvisoRecaladaBean.

Страница X HTML, помимо прочего, имеет одну сетку панелей, определенную следующим образом:

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

Face-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, я не получаю сообщений об ошибках. Кроме того, я не получаю ошибок при доступе к странице X HTML.

Однако, когда я ввожу одно значение во входной текст и пу sh командную кнопку, я получаю одно NullPointerException. Трассировка стека показывает, что исключение было запущено при попытке выполнить первую строку buscarRegistro().

После некоторой отладки я обнаружил, что атрибут avisoRecaladaService был нулевым, но два других управлялись свойства не были .

Я пробовал следующие решения безрезультатно

  1. Добавить и / или заменить @ManagedProperty на @Autowired
  2. Использовать аннотация @Qualifier для имени компонента (я назвал его "avisoRecaladaService") и использования текущего ApplicationContext для получения компонента (Источник: Spring Bean никогда не устанавливается как ManagedProperty в JSF Bean ). Я получил NoSuchBeanException с этим решением:
WebApplicationContext webAppContext = ContextLoader.getCurrentWebApplicationContext();
avisoRecaladaService = (IAvisoRecaladaService) webAppContext.getBean("avisoRecaladaService");
ИЗМЕНИТЬ : создать экземпляр 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);
        }
    }
ИЗМЕНИТЬ : заменить @ManagedAttribute на @Resource (источник: @ ManagedProperty эквивалент в Spring ) Заменить @ManagedAttribute на @Inject (то же исходный код, как в предыдущем решении)

Любой совет по окончательному решению будет действительно очень обязательным.

EDIT

По запросу Kukeltje , согласно pom. xml приложения, задействованные библиотеки следующие:

  • jboss-jsf-api 2.2
  • jboss-el-api 3.0 spe c
  • пружинный сердечник 4.2.8
  • пружинная перемычка 4.2.8
  • пружинное выражение 4.2.8
  • пружинно-контекстная опора 4.2.8
  • Spring-Web- mvc 4.2.8
  • JDK 1.8.0_191
  • Разработано в Eclipse Oxygen (если применимо)

1 Ответ

0 голосов
/ 19 июня 2020

РЕШЕНО

Благодаря моему партнеру, мы обнаружили, что @ManagedProperty очень чувствителен к именам. Имя bean-компонента должно быть точно таким же , что и класс, с первой буквой в нижнем регистре. Если объект является экземпляром интерфейса, как в моем случае, это должно быть имя класса, реализующего его.

Итак, мне пришлось изменить это:

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

На это:

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

Спасибо всем за то, что прочитали это, и я надеюсь, что это поможет в решении подобных проблем в будущем

...