3

I have an Actor class that handle user session scoped data

    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>

In older project that worked fine so I supposed the version of JSF is the cause I'm using version 2.2.12 with Spring 4.1.4. I tried to downgrade JSF version or upgrade Spring version with no luck. Another problem is that Actor constructor is called multiple times.

So is there a hidden behavior here, is that true that Spring should see FacesContext since the request is mapped by JSF servlet or it can't since FacesContext is in another scope.

I supposed that Spring is initialized before JSF therefore it sees FacesContext as null if so how you order the initialization containers

Thanks in advance

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Youans
  • 4,801
  • 1
  • 31
  • 57
  • 1
    Why are those listeners mapped/registered twice? Do you really need to map `FacesServlet` to `*.html`? And do initialization of bean in `@PostConstruct`. – Tiny Sep 10 '15 at 16:09
  • @Tiny Sorry my mistake I will edit it – Youans Sep 10 '15 at 16:20
  • @Tiny And Yes I need all requests to be JSF scoped and using `PostConstruct` has same effect of the constructor – Youans Sep 10 '15 at 16:24
  • Does it make a difference, when you place those two listeners before `javax.faces.webapp.FacesServlet` in `web.xml`? – Tiny Sep 10 '15 at 16:31
  • 1
    I guess Spring is constructing your `Actor` bean, so it's not related with any JSF request at all. AFAIK, the faces context can't be accesed outside the JSF lifecycle, so this method should return a null value. However, you should be able to access JSF session and application managed beans retrieving them using the standard servlet API. – Aritz Sep 10 '15 at 19:04

1 Answers1

1

I have LoggedInFilter that is not posted on the question

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());
        }
    }

Digging the problem found the cause was on filters

Filters can't see FacesContext cause Faces servlet is not yet initialized on the filter scope see this answer for more info so when injecting actor on filter it's constructor begins and BAM NullPointerException is thrown if you tried to use FacesContext at that point

My mistake I didn't really think the filters can affect the understanding of the question thus I can see that no one could solve the question at the first place sorry for all

Community
  • 1
  • 1
Youans
  • 4,801
  • 1
  • 31
  • 57