1
votes

we want to create web app by integrating Spring CDI + JSF + Spring Security. We have configured all of above frameworks and we have thought that everything is ok, but during implementing logout functionality we have realized that JSF's ManagedBeans are not created when they should. For example: We have created managed bean in session scope, and we have expected that bean will be deleted after logout and invalidating session.

Unfortunately, after re-login managed bean instance is still alive (every user information is the same as before logout :(). We have added more logs, and we have noticed our managed bean is created during starting application, not during initialization user session. We have found that it is caused by context:component-scan base-package="..." in spring application context config file, so we have added context:exclude-filter type="" expression="" but after that any managed bean is not created any more :(. We have added some listing below.

applicationContext.xml

<context:property-placeholder location="classpath:application.properties"/>

<context:component-scan base-package="com.teaman" />
<mongo:repositories base-package="com.teaman.dao" />

<mongo:mongo host="${mongodb.hostname}" port="${mongodb.port}" id="mongo" />
<mongo:db-factory id="mongoDbFactory" mongo-ref="mongo" dbname="${mongodb.dbname}" />
<mongo:mapping-converter id="converter" db-factory-ref="mongoDbFactory" />

<bean id="mongoTemplate" class="org.springframework.data.mongodb.core.MongoTemplate">
    <constructor-arg name="mongoDbFactory" ref="mongoDbFactory" />
    <constructor-arg name="mongoConverter" ref="converter"/>
    <property name="writeConcern">
        <util:constant static-field="com.mongodb.WriteConcern.SAFE" ></util:constant>
    </property>
</bean>

<!-- Use this post processor to translate any MongoExceptions thrown in @Repository annotated classes -->
<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"/>

<bean id="gridTemplate" class="org.springframework.data.mongodb.gridfs.GridFsTemplate">
    <constructor-arg ref="mongoDbFactory" />
    <constructor-arg ref="converter" />
</bean>

<bean id="teaManAuthenticationSuccessHandler" class="com.teaman.authentication.handler.TeaManAuthenticationSuccessHandler"/>

beans.xml

<beans xmlns="http://java.sun.com/xml/ns/javaee"
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
   xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/beans_1_0.xsd">
 </beans>

faces-config.xml

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

    <locale-config>
        <default-locale>pl</default-locale>
    </locale-config>

    <resource-bundle>
        <base-name>com.teaman.locales.locale</base-name>
        <var>msg</var>
    </resource-bundle>
</application> 

<application>
    <message-bundle>com.teaman.ValidationMessages</message-bundle>
</application>

<lifecycle>
    <phase-listener>com.teaman.bean.LoginErrorPhaseListener</phase-listener>
</lifecycle>

web.xml

<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/applicationContext.xml
        /WEB-INF/securityContext.xml
    </param-value>
</context-param>

<context-param>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>

<context-param>
    <param-name>javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL</param-name>
    <param-value>true</param-value>
</context-param>

<!-- Context listener responsible for loading spring applicationContext file -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>

<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>/faces/*</url-pattern>
    <url-pattern>/javax.faces.resource/*</url-pattern>
</servlet-mapping>

ManagedBean

package com.teaman.bean;

import java.io.Serializable;
import javax.enterprise.context.SessionScoped;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.inject.Named;
import org.apache.log4j.Logger;

@Named(value = "teaManUserSessionBean")
@SessionScoped
public class TeaManUserSessionBean implements Serializable {

     ....
     public void initUserSession(ComponentSystemEvent e) {
           logger.debug("TeaManUserSession init...");
     }
     ....
}

Maybe anyone has already met with the same problem, and could help us ? :) Thanks a lot for every tips/note/comment.

1
what is Spring CDI? - I know Spring (DI), and CDI, but no Spring CDI - Ralph
there should be Spring + CDI + JSF ... my mistake, sorry. - BartekR
Is there any good reason for using Spring and CDI? - if not I strongly recommend to use only one of them (I would choose Spring when you want to use Spring-Secruity too). - Ralph
what about jsf managed beans ? I read that if we want use jsf with spring we should use CDI (@Named etc.). Clear jsf managed bean does not work correctly with spring layer. - BartekR
Spring's default scope is application scope. So I guess something went wrong as to bean management configuration and your backing beans are actually treated as Spring managed beans not as CDI managed beans. Related: stackoverflow.com/q/18387993 - BalusC

1 Answers

1
votes

I advise you to use @Scope("session") from Spring library instead of @SessionScoped from CDI. It seems you have a conflict with the default Spring scope (which is application scope) so it does not work.