Spring 会话 bean 将 FacesContext.getCurrentInstance() 视为空引用
Spring session bean sees FacesContext.getCurrentInstance() as Null reference
我有一个 Actor
class 来处理用户会话范围内的数据
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component(value = "actor")
@Scope(value = "session")
public class Actor{
public Actor() {
System.out.println("Inside void init Actor..........");
System.out.println(JsfUtils.getFacesContext());// This prints Null
}
}
web.xml
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
</web-app>
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd">
<context:load-time-weaver aspectj-weaving="off" />
<task:scheduler id="taskScheduler"/>
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="2" />
<property name="maxPoolSize" value="8" />
<property name="queueCapacity" value="2000" />
</bean>
<task:annotation-driven executor="taskExecutor" scheduler="taskScheduler"/>
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="contextApplicationContextProvider" class="net.main.spring.context.ApplicationContextProvider"></bean>
// <context:component-scan base-package="net.main.x">//</context:component-scan> more goes here
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="Default_Persistence_Unit"/>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL"/>
<property name="showSql" value="false"/>
</bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
</property>
</bean>
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="jpaTransactionManager" proxy-target-class="true"/>
</beans>
在旧项目中运行良好,所以我认为 JSF 的版本是我使用 2.2.12 版和 Spring 4.1.4 的原因。我尝试降级 JSF 版本或升级 Spring 版本,但没有成功。另一个问题是 Actor
构造函数被多次调用。
所以这里有隐藏的行为吗,Spring 应该看到 FacesContext
是真的吗,因为请求是由 JSF servlet 映射的,或者它不能,因为 FacesContext
在另一个范围。
我假设 Spring 是在 JSF 之前初始化的,因此它将 FacesContext
视为空,如果是这样的话,您如何订购初始化容器
提前致谢
我有 LoggedInFilter
没有发布在问题上
public class LoggedInFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
Actor actor = SpringUtils.getBean(Actor.class);
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI();
boolean isAdminPage = uri.contains("/cpanel/");
if (!actor.isLoggedIn() && (uri.contains("/select-issue") || isAdminPage)) {
request.getRequestDispatcher("/login.html").forward(request, response);
} else if (isAdminPage) {
if (actor.isAdmin()) {
chain.doFilter(request, response);
} else {
res.sendRedirect("/404.html");
}
} else {
chain.doFilter(request, response);
}
} catch (Exception ex) {
SystemLogger.getLogger(getClass().getSimpleName()).error(ex.getMessage());
}
}
挖掘问题发现原因在过滤器上
过滤器看不到 FacesContext
,因为 Faces servlet
尚未在过滤器范围上初始化,请参阅此 answer 了解更多信息
因此,当在过滤器上注入 actor 时,它的构造函数开始,如果您当时尝试使用 FacesContext
,则会抛出 BAM NullPointerException
我的错误我真的不认为过滤器会影响对问题的理解因此我可以看到没有人能在第一时间解决这个问题对不起大家
我有一个 Actor
class 来处理用户会话范围内的数据
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
@Component(value = "actor")
@Scope(value = "session")
public class Actor{
public Actor() {
System.out.println("Inside void init Actor..........");
System.out.println(JsfUtils.getFacesContext());// This prints Null
}
}
web.xml
<web-app version="3.1" xmlns="http://xmlns.jcp.org/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd">
<servlet>
<servlet-name>Faces Servlet</servlet-name>
<servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
<servlet-name>Faces Servlet</servlet-name>
<url-pattern>*.html</url-pattern>
</servlet-mapping>
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
<listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>
</web-app>
applicationContext.xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:task="http://www.springframework.org/schema/task"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-4.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd">
<context:load-time-weaver aspectj-weaving="off" />
<task:scheduler id="taskScheduler"/>
<bean id="taskExecutor" class="org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor">
<property name="corePoolSize" value="2" />
<property name="maxPoolSize" value="8" />
<property name="queueCapacity" value="2000" />
</bean>
<task:annotation-driven executor="taskExecutor" scheduler="taskScheduler"/>
<bean class="org.springframework.context.annotation.CommonAnnotationBeanPostProcessor"/>
<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>
<bean id="contextApplicationContextProvider" class="net.main.spring.context.ApplicationContextProvider"></bean>
// <context:component-scan base-package="net.main.x">//</context:component-scan> more goes here
<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
<property name="persistenceUnitName" value="Default_Persistence_Unit"/>
<property name="jpaDialect">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaDialect"/>
</property>
<property name="jpaVendorAdapter">
<bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
<property name="database" value="MYSQL"/>
<property name="showSql" value="false"/>
</bean>
</property>
<property name="loadTimeWeaver">
<bean class="org.springframework.instrument.classloading.ReflectiveLoadTimeWeaver"/>
</property>
</bean>
<bean id="jpaTransactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
<property name="entityManagerFactory" ref="entityManagerFactory"/>
</bean>
<tx:annotation-driven transaction-manager="jpaTransactionManager" proxy-target-class="true"/>
</beans>
在旧项目中运行良好,所以我认为 JSF 的版本是我使用 2.2.12 版和 Spring 4.1.4 的原因。我尝试降级 JSF 版本或升级 Spring 版本,但没有成功。另一个问题是 Actor
构造函数被多次调用。
所以这里有隐藏的行为吗,Spring 应该看到 FacesContext
是真的吗,因为请求是由 JSF servlet 映射的,或者它不能,因为 FacesContext
在另一个范围。
我假设 Spring 是在 JSF 之前初始化的,因此它将 FacesContext
视为空,如果是这样的话,您如何订购初始化容器
提前致谢
我有 LoggedInFilter
没有发布在问题上
public class LoggedInFilter implements Filter {
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
try {
Actor actor = SpringUtils.getBean(Actor.class);
HttpServletRequest req = (HttpServletRequest) request;
HttpServletResponse res = (HttpServletResponse) response;
String uri = req.getRequestURI();
boolean isAdminPage = uri.contains("/cpanel/");
if (!actor.isLoggedIn() && (uri.contains("/select-issue") || isAdminPage)) {
request.getRequestDispatcher("/login.html").forward(request, response);
} else if (isAdminPage) {
if (actor.isAdmin()) {
chain.doFilter(request, response);
} else {
res.sendRedirect("/404.html");
}
} else {
chain.doFilter(request, response);
}
} catch (Exception ex) {
SystemLogger.getLogger(getClass().getSimpleName()).error(ex.getMessage());
}
}
挖掘问题发现原因在过滤器上
过滤器看不到 FacesContext
,因为 Faces servlet
尚未在过滤器范围上初始化,请参阅此 answer 了解更多信息
因此,当在过滤器上注入 actor 时,它的构造函数开始,如果您当时尝试使用 FacesContext
NullPointerException
我的错误我真的不认为过滤器会影响对问题的理解因此我可以看到没有人能在第一时间解决这个问题对不起大家