SystemEventListener + @Value null on Websphere 8.5



我在一个我实施的一个SystemEventListener中面临问题。我正在使用注释@Value从属性文件注入值。问题在于注释@Value在应用程序的其他部分(例如@controller)运行良好,但是在此SystemEventListener中,效果不佳。它还在tomcat上工作,但在WebSphere 8.5上不工作。

你知道会是什么吗?

实施

public class PreRenderViewListener implements SystemEventListener {
    @Value("${path}/fileName.properties")
    private String filePath;

faces-config.xml

<system-event-listener>
            <system-event-listener-class>com.package.PreRenderViewListener</system-event-listener-class>
            <system-event-class>javax.faces.event.PreRenderViewEvent</system-event-class>
</system-event-listener>

解析器是一种bean,它扩展了 PropertyPlaceholderConfigurer的类,该类正常运行。

<bean id="uxMasterConfigBean" class="com.csc.cscip.ux.common.util.UXPropertiesConfigurer">
        <property name="ignoreUnresolvablePlaceholders" value="true" />
        <property name="ignoreResourceNotFound" value="true" />
        <property name="locations">
            <list>
                <value>classpath:/resources/master/ux.default.configuration.properties</value>
                <value>${ux.master.configuration.file.path}</value>
            </list>
        </property>
    </bean>

这种配置在Tomcat中运行良好,因此我认为这不是代码中的问题,也许这是与WebSphere 8.5有关的问题。我一直在互联网上寻找这个问题,但没有找到这样的东西。

感谢您的帮助!

如M. Deinum所说,

prerenderviewlistener是JSF(面)托管bean,而不是 春季托管bean因此@Value不应该工作。

因此,要使您能够工作,您必须在春季进行PreRenderViewListener"认可",这意味着它必须是弹簧组件。
我现在正在使用的解决方案(我希望对此有所评论)是使用multicaster,例如org.springframework.web.jsf.DelegatingPhaseListenerMulticaster,它将在Faces Config中注册,并将将所有工作委派给实现SystemEventListener的其他Spring Bean。

这是多层官员的代码(它是从提到的春季多层器中启发的)。

package org.example.listeners;
import java.util.Collection;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.SystemEvent;
import javax.faces.event.SystemEventListener;
import org.springframework.beans.factory.BeanFactoryUtils;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.jsf.FacesContextUtils;

public class DelegatingSystemEventListenerMulticaster implements SystemEventListener{
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
    for (SystemEventListener listener : getDelegates(FacesContext.getCurrentInstance())) {
        if(listener.isListenerForSource(event.getSource())){
            listener.processEvent(event);
        }
    }
}
@Override
public boolean isListenerForSource(Object source) {
    for (SystemEventListener listener : getDelegates(FacesContext.getCurrentInstance())) {
        if(listener.isListenerForSource(source)){
          return true;
        }
    }
    return false;
}

/**
 * Obtain the delegate PhaseListener beans from the Spring root WebApplicationContext.
 * @param facesContext the current JSF context
 * @return a Collection of PhaseListener objects
 * @see #getBeanFactory
 * @see org.springframework.beans.factory.ListableBeanFactory#getBeansOfType(Class)
 */
protected Collection<SystemEventListener> getDelegates(FacesContext facesContext) {
    ListableBeanFactory bf = getBeanFactory(facesContext);
    return BeanFactoryUtils.beansOfTypeIncludingAncestors(bf, SystemEventListener.class, true, false).values();
}
/**
 * Retrieve the Spring BeanFactory to delegate bean name resolution to.
 * <p>The default implementation delegates to {@code getWebApplicationContext}.
 * Can be overridden to provide an arbitrary ListableBeanFactory reference to
 * resolve against; usually, this will be a full Spring ApplicationContext.
 * @param facesContext the current JSF context
 * @return the Spring ListableBeanFactory (never {@code null})
 * @see #getWebApplicationContext
 */
protected ListableBeanFactory getBeanFactory(FacesContext facesContext) {
    return getWebApplicationContext(facesContext);
}
/**
 * Retrieve the web application context to delegate bean name resolution to.
 * <p>The default implementation delegates to FacesContextUtils.
 * @param facesContext the current JSF context
 * @return the Spring web application context (never {@code null})
 * @see FacesContextUtils#getRequiredWebApplicationContext
 */
protected WebApplicationContext getWebApplicationContext(FacesContext facesContext) {
    return FacesContextUtils.getRequiredWebApplicationContext(facesContext);
}
}

faces-config.xml中:

<system-event-listener>
        <system-event-listener-class>org.example.listeners.DelegatingSystemEventListenerMulticaster</system-event-listener-class>
<!--Use any event you want here -->
        <system-event-class>javax.faces.event.PostAddToViewEvent</system-event-class>
    </system-event-listener> 

,最后创建您的 SystemEventListener bean,例如:

@Component
public class FooComponentListener  implements SystemEventListener{
@Autowired
private FooService fooService;
@Override
public void processEvent(SystemEvent event) throws AbortProcessingException {
    //Do your business
}
@Override
public boolean isListenerForSource(Object source) {
//Or any other condition
    return (source instanceof HtmlInputText || source instanceof HtmlOutputText || source instanceof HtmlOutputLabel);
}

}

我希望这会有所帮助,即使有点晚。

最新更新