Search code examples
jsfprimefacesspring-securityuicomponents

Why does SpringBeanFacesELResolver cancel UIComponent binding?


I have a web app that uses Primefaces. I bind some facelet components to UIComponent type fields in my backing managed beans. Something like this:

 <p:panel id="loginPanel"
             rendered="false"
             binding="#{loginBean.loginPanel}"
             style="border: none">

And no additional annotations in bean just like this:

@ManagedBean
public class LoginBean {

    String name;
    String password;
    UIComponent loginPanel;
//...}

I decided to use Spring Security for authentication management. So I implemented

UserDetailsService

interface, specified implementation in spring security config to be injected into my managed bean:

<!-- Set MemberDetailsService class as the authentication Manager -->
   <sec:authentication-manager alias="authenticationManager">
          <sec:authentication-provider user-service-ref="memberDetailsService">
                 <sec:password-encoder hash="plaintext"/>
          </sec:authentication-provider>
   </sec:authentication-manager>

   <!-- Inject authentication Manager to our LoginBean -->
   <beans:bean id="loginBean" name="loginBean" class="com.mycompany.managed.LoginBean" scope="prototype">
          <beans:property name="authenticationManager" ref="authenticationManager"/>
   </beans:bean>

I also added Spring's filters and listeners into web.xml - nothing fancy. I was expecting that by annotating my new field in LoginBean like:

@ManagedProperty("#{authenticationManager}")
AuthenticationManager authenticationManager;

the work will be done. But AuthenticationManager was not injected during runtime it resulted in NullPointerException. I used this solution

and created faces-config.xml with just:

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

Authentication works fine now. The problem is UIComponent binding doesn't work anymore UIComponent field in my LoginBean is null during the runtime. Beans that have bindings but no managed properties injected do not have that problem. What is going on? I don't really understand the connection...

Thx.


Solution

  • As explained in this answer.

    My backing bean for login page initially had been managed by JSF. JSF had been initializing UIcomponent property. When I added a new managed property and configured its injection in spring security config I actually made my bean managed by Spring. Thus properties previously had been initialized by JSF became null.

    As a w\a I decided to split functionality in the bean into two separate beans. One of them will be managed by Spring and another one by JSF.