Announcement Announcement Module
Collapse
No announcement yet.
JSF/Mojarra 2.0.3 + Spring 3.0.5 + DI problems Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • JSF/Mojarra 2.0.3 + Spring 3.0.5 + DI problems

    Hi all!

    I need to inject a Spring service into ManagedBean!
    But with my config DI doesn't work and the service into the Faces BB is null...

    web.xml
    Code:
      <!-- JSF MOJARRA CONTEXT PARAM -->
      <context-param>
      	<param-name>javax.faces.PROJECT_STAGE</param-name> 
      	<param-value>Development</param-value> 
      </context-param>
      
      <!-- PRIMEFACES 2.2 CONTEXT PARAM -->
      <context-param>
    	<param-name>com.sun.faces.allowTextChildren</param-name>
    	<param-value>true</param-value>
      </context-param>
      
      <context-param>
      	<param-name>primefaces.SKIN</param-name>
    	<param-value>none</param-value>
      </context-param>
      
      <!-- SPRING APPLICATION CONTEXT PARAM -->
      <context-param>
      	<param-name>contextClass</param-name>
      	<param-value>org.springframework.web.context.support.AnnotationConfigWebApplicationContext</param-value>
      </context-param>
      
      <context-param>
       	<param-name>contextConfigLocation</param-name>
       	<param-value>
       		/WEB-INF/spring-properties-from-file-context.xml,
       		/WEB-INF/spring-properties-from-db-context.xml,
       		/WEB-INF/spring-service-context.xml
       	</param-value>
      </context-param>
      
      <!-- GO WEB SESSIONTIMEOUT FILTER -->
      <filter>
     	 <filter-name>SessionTimeoutFilter</filter-name>
         <filter-class>it.niuma.goWeb.sessionTimeoutFilter.GOWebSessionTimeoutFilter</filter-class>
      </filter>
      <filter-mapping>
         <filter-name>SessionTimeoutFilter</filter-name>
         <url-pattern>*.xhtml</url-pattern>
      </filter-mapping>
      
      <!-- SPRING LISTENER -->
      <listener>
    	<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
      </listener>
      
      <listener>
        <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>   
      </listener> 
        
      <!-- SESSION PERSISTANCE LISTENER --> 
      <listener>
        <listener-class>it.niuma.goWeb.sessionListener.GOWebSessionListener</listener-class>
      </listener>
      
      <!-- JSF MOJARRA SERVLET -->
      <servlet>
      	<servlet-name>Faces Servlet</servlet-name> 
      	<servlet-class>javax.faces.webapp.FacesServlet</servlet-class> 
      </servlet>
      <servlet-mapping>
      	<servlet-name>Faces Servlet</servlet-name> 
      	<url-pattern>*.xhtml</url-pattern> 
      </servlet-mapping>
    application-context.xml
    Code:
    	
                 <context:component-scan base-package="it.niuma.goWeb.services" /> 	
    	 	
    	<!-- DATABASE SECTION CONFIG -->
    	<bean id="dataSource" name="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean" scope="singleton">
    		<property name="jndiName">
    			<value>${database.datasource}</value>
    		</property>
    	</bean>
    	
    	<!-- DEFAULT LOB HANDLER CONFIG -->
    	<bean id="lobHandler" class="org.springframework.jdbc.support.lob.DefaultLobHandler" lazy-init="true"/>
    	
    	<!-- SESSION FACTORY CONFIG -->
    	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    		<property name="dataSource">
    			<ref bean="dataSource" />
    		</property>
    				
    		<property name="lobHandler">
    			<ref bean="lobHandler" />
    		</property>
    		
    		<property name="packagesToScan" value="it.niuma.goWeb.dao" />
    				
    		<property name="configLocation">
    			<value>/WEB-INF/hibernate.cfg.xml</value>
    		</property>		
    		
    		<property name="mappingResources">
    			<list>
    				......
    			</list>
    		</property>
    	</bean>
    	
    	<!-- TRANSACTION MANAGER -->
    	<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
    		<property name="sessionFactory">  
    			<ref bean="sessionFactory" />  
    		</property>  
    	</bean>  
    
    	<tx:annotation-driven />  	
    </beans>
    faces-config.xml
    Code:
      <application>
      	<!-- LOCALE & INTERNATIONALIZATION MANAGE -->
      	<locale-config>
    		<default-locale>it</default-locale>
    		<supported-locale>en</supported-locale>
    		<supported-locale>fr</supported-locale>
    	</locale-config>
    	<message-bundle></message-bundle>
    	<resource-bundle>
    		<base-name>ApplicationResourceMsg</base-name>
    		<var>ApplResMsg</var>		
    	</resource-bundle>
    	<resource-bundle>
    		<base-name>ApplicationResourceLabel</base-name>
    		<var>ApplResLbl</var>		
    	</resource-bundle>
    	
    	<!-- SPRING INJECTION -->
    	<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
      </application>
    spring service
    Code:
    @Service
    public class LoginMgmtServiceImpl implements LoginMgmtService{
    	
    	private static final long serialVersionUID = 1L;
    	org.apache.log4j.Logger log = Logger.getLogger(this.getClass());
    	private UserDAO userDAO;
    
    	public Collection<Utente> userLogin(Utente currentUser) throws GOWebDatabaseException, GOWebBusinessException {
    		Collection<Utente> userResult = new HashSet<Utente>();
    		
    		try{			
    			if(currentUser.getUsername() != null){				
    				userResult = userDAO.findToLogin(currentUser);
    				log.info("Login Utente: " + currentUser.getUsername());
    			}
    		}
    		catch(GOWebDatabaseException daoExc){
    			log.error(daoExc);
    			throw new GOWebDatabaseException(GOWebDatabaseErrors.SELECT_EXC);
    		}
    		catch(Exception exc){
    			log.error(exc);
    			throw new GOWebBusinessException(GOWebBusinessErrors.GENERIC_EXC);
    		}
    		return userResult;
    		
    	}
    
                 @Autowired
    	public void setUserDAO(UserDAO userDAO) {this.userDAO = userDAO;}
    	
    }
    JSF BackingBean
    Code:
    @ManagedBean(name="BeanUser")
    @SessionScoped
    public class BeanUser implements Serializable{
    
    	private static final long serialVersionUID = 1L;
    		
    	private Utente currentUser = new Utente();
    	private boolean isLogged = false;
    	
    	@ManagedProperty(name="beanProperties", value="#{beanProperties}")
    	private BeanProperties beanProperties;
    	
    	@ManagedProperty(name="loginMgmtService", value="#{loginMgmtService}")
    	private LoginMgmtService loginMgmtService;
    	
    	
    	public String login(String username, String pwd){
    		
    		// La homepage interna č comune a tutti gli utenti
    		String toReturn = null;
    			
    		// User Login
    		try {			
    			if(username != null && username.trim().length() > 0 && 
    			   pwd != null && pwd.trim().length() > 0){
    				
    				// Encode Password
    				String md5Val = MessageDigestUtility.obtaindMD5Value(pwd);
    				
    				// Set the username and the encoding password
    				getCurrentUser().setUsername(username);
    				getCurrentUser().setPassword(md5Val);
    				
    				Collection<Utente> currentUser = loginMgmtService.userLogin(getCurrentUser());
    				//userToLogin = null;
    				
    				if(currentUser != null && currentUser.size() > 0){
    					
    				   Iterator<Utente> iterUser = currentUser.iterator();
    				   while(iterUser.hasNext()){
    					   
    					   Utente userLogin = (Utente)iterUser.next();
    				   }
    				}					   
    			}
    		}
    		catch (GOWebDatabaseException RfxDataExc) {
    			throw RfxDataExc;
    		}
    		catch (GOWebBusinessException RfxExc) {
    			throw RfxExc;
    		}
    		catch (Exception Exc) {
    			Exc.printStackTrace();
    			throw new GOWebBusinessException(GOWebBusinessErrors.GENERIC_EXC);
    		}
    		
    		return toReturn;
    	}
    	
    	// LOCALE MANAGE
    	public Locale getLocale() {return FacesContext.getCurrentInstance().getViewRoot().getLocale();}
    	public void setLocale(Locale locale) {FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);}
    	
    	public void updateToEnglish() {this.setLocale(Locale.ENGLISH);}
    	
    	public void updateToItalian() {this.setLocale(Locale.ITALIAN);} 
    	
    	public void updateToFrench() {this.setLocale(Locale.FRANCE);}
    	
    	// GETTERS & SETTERS FOR BEAN USER PROPERTIES
    	public Utente getCurrentUser() {return currentUser;}
    	public void setCurrentUser(Utente currentUser) {this.currentUser = currentUser;}
    
    	public Set<Ruolo> getRuoliUtente() {return getCurrentUser().getRuoliUtente();}
    	public void setRuoliUtente(Set<Ruolo> ruoliUtente) {getCurrentUser().setRuoliUtente(ruoliUtente);}
    
    	public boolean isLogged() {return this.isLogged;}
    	public void setLogged(boolean isLogged) {this.isLogged = isLogged;}
    	
    	
    	// SPRING's SERVICES INJECTION
    	public LoginMgmtService getLoginMgmtService() {return loginMgmtService;}
    	public void setLoginMgmtService(LoginMgmtService loginMgmtService) {this.loginMgmtService = loginMgmtService;}
    	
    	public BeanProperties getBeanProperties() {return beanProperties;}
    	public void setBeanProperties(BeanProperties beanProperties) {this.beanProperties = beanProperties;}	
    }
    Thanks in advance for any suggestions!

    Cheers, Vale

  • #2
    Hi,

    if you use

    Code:
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
    it means you're telling jsf to use Spring beans as managed beans. Thus, you shouldn't define any managed bean by using
    Code:
    @ManagedBean(name="BeanUser")
    @SessionScoped
    (jsf annotations).

    Instead, you should define your BeanUser class as a Spring bean (by either defining the bean in applicationContext.xml or marking it with @Component and do context:component-scan on its package) and then define dependency injection either by specifying property ref in xml or by using @Autowired annotation.

    This way, your BeanUser will be a Spring bean AND a managed bean at the same time, so you will be able to use it as backing bean for jsf page but also be able to get Spring dependency injection working properly.

    With your current configuration the BeanUser class is not a Spring bean so DI is not possible.

    Best regards,

    Enrico

    Comment


    • #3
      Hi Enrico,

      thanks for your suggestions!
      I modified my code and the injection works fine in BeanUser now....but I have a new problem...

      BeanUser:
      Code:
      @Component
      public class BeanUser implements Serializable{
      
               private LoginMgmtService loginMgmtService;
                         ........
                         ...........
                         ...............
      
               @Autowired
               public void setLoginMgmtService(LoginMgmtService loginMgmtService) {this.loginMgmtService = loginMgmtService;}
      }
      So....I need to get a BB by name like a regular Servlet:
      EXAMPLE:
      Bean bean = (Bean) request.getAttribute("beanName");

      I try with:
      Code:
      public BeanUser getBeanUser() {
      		if(beanUser == null){
      			beanUser = (BeanUser) FacesContext.getCurrentInstance().getApplication().evaluateExpressionGet(FacesContext.getCurrentInstance(), "#{BeanUser}", BeanUser.class);
      		}
      		return beanUser;
      	}
      but for JSF/Spring bean the value is null.
      If I load a normal JSF BB I will obtain the object.
      For bean annotated with @Component I received null value

      Thanks in advance for your help!

      Have a good day!
      Cheers, Valentina

      Comment


      • #4
        Hi,

        your approach doesn't work because it's based on standard JSF EL resolver. Since you specified in your faces context that you want to use org.springframework.web.jsf.el.SpringBeanFacesELRe solver to resolve your beans, you should also use it yourself to get your backing beans programmatically from one another. This means you should obtain the ELContext this way:

        Code:
        FacesContext context = FacesContext.getCurrentInstance();
        ELContext elContext = context.getELContext();
        this way your ELContext implementation will be the Spring implementation since you configured it this way. Then use it like this:

        Code:
        Application application = context.getApplication();
        ExpressionFactory ef = application.getExpressionFactory();
        ValueExpression ve = ef.createValueExpression(elContext, "#{BeanUser}", UserBean.class);
        UserBean beanUser = (UserBean) ve.getValue(elContext);
        I, however, strongly suggest a different approach: since your backing beans are also Spring beans, why not dependency injecting them in one another when needed? In the bean that needs to use BeanUser, just do
        Code:
        @Autowired
        private BeanUser beanUser;
        and voilą...you have your bean user dependency injected and ready to use.

        Hope this helps

        Enrico

        Comment


        • #5
          Thanks Enrico!

          Now it works ...but only if I add a ref-name for the component like this:
          @Component("BeanUser")

          I can't autowire the BeanUser in this case for a set of problems but for the others I will use your precius suggested approch!!!

          Thanks a lot for your explanations!

          Cheers, Vale

          Comment

          Working...
          X